initial commit

This commit is contained in:
nolan 2023-12-02 20:20:00 -08:00
commit 9f641c2bbf
7 changed files with 397 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
venv/
test-venv/
*.pyc
__pycache__/
instance/
.pytest_cache/
.coverage
htmlcov/
dist/
build/
*.egg-info/
node_modules/
.envs
session_files/
mongo_data/
test_data/

1
README.md Normal file
View File

@ -0,0 +1 @@
Library AF Mosiac

10
lib_afc_mosiac/__init__.py Executable file
View File

@ -0,0 +1,10 @@
"""
lib_afc_mosiac
---------------------------------------
A Python library for working with AFC Mosiac files
"""
from lib_afc_mosiac.universe_map_file import AFCM_UniverseMapFile
#from lib_afc_api.afccampaign import AFCCampaign

View File

@ -0,0 +1,210 @@
import sys
import base64
import requests
import datetime
import json
# added this to silence annoying SSL warnings in requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class AFCBusiness:
def __init__( self, api_url=None, api_jwt=None, username=None, password=None ):
# Update this as we modify the library for newer versions
self.api_version = 'v1'
self.api_jwt = api_jwt
#self.api_url = f"https://afaccount.roosevelt.hyperscaleaf.com/api/{self.api_version}/businesses"
# Dev
self.api_url = f"https://afaccount.eisenhower.hyperscaleaf.com/api/"
# Prod
#self.api_url = f"https://afaccount.roosevelt.hyperscaleaf.com/api/"
self.credentials = {}
self.credentials['user_name'] = username #'rross'
self.credentials['password'] = password #'rGstj!f672q5FBZ'
self.headers = {}
self.headers['content-type'] = "application/json"
self.headers['accept'] = "application/json"
if self.api_jwt == None:
if self.credentials['user_name'] and self.credentials['password']:
self.Set_JWT()
else:
print("Unable to connect to API without jwt or authentication credentials")
sys.exit(1)
self.headers['authorization'] = "Bearer " + self.api_jwt
self.params = {}
def Set_JWT( self ):
url = f"{self.api_url}{self.api_version}/auth/authenticate"
try:
response = requests.post(url, headers=self.headers, json=self.credentials)
except requests.exceptions.RequestException as e:
print("exception: {}".format(e))
sys.exit(1)
try:
response.raise_for_status()
except requests.exceptions.HTTPError as err:
print("http error: {}".format(err))
sys.exit(1)
rj = response.json();
self.api_jwt = rj['jwt']
return
def Submit_Get( self, full_url, input_params={} ):
if not isinstance(full_url, str):
print("Submit_Get() error: must provide the full url string")
return None
try:
self.response = requests.get(full_url, verify=False, headers=self.headers, params=input_params)
#print("debug: url = {}".format(self.response.url))
except requests.exceptions.RequestException as e:
print("exception: {}".format(e))
#sys.exit(1)
return None
try:
self.response.raise_for_status()
except requests.exceptions.HTTPError as err:
print("http error: {}".format(err))
#sys.exit(1)
return None
return self.response
def Submit_Post( self, full_url, input_params={}, data={} ):
if not isinstance(full_url, str):
print("Submit_Post() error: must provide the full url string")
return None
print(f"\ndata = {data}")
try:
this_headers = self.headers
this_headers['Content-Type'] = 'application/json'
#self.response = requests.post(full_url, verify=False, headers=this_headers, params=input_params, data=data)
self.response = requests.post(full_url, verify=False, headers=this_headers, data=json.dumps(data))
#print("debug: url = {}".format(self.response.url))
except requests.exceptions.RequestException as e:
print("exception: {}".format(e))
#sys.exit(1)
return None
try:
self.response.raise_for_status()
except requests.exceptions.HTTPError as err:
print("http error: {}".format(err))
print(f"\nself.response.attributes = {self.response.__dict__}")
#sys.exit(1)
return None
return self.response
def Submit_Patch( self, full_url, input_params={}, data={} ):
if not isinstance(full_url, str):
print("Submit_Patch() error: must provide the full url string")
return None
#print(f"\ndata = {data}")
try:
this_headers = self.headers
this_headers['Content-Type'] = 'application/json'
#self.response = requests.post(full_url, verify=False, headers=this_headers, params=input_params, data=data)
self.response = requests.patch(full_url, verify=False, headers=this_headers, data=json.dumps(data))
#print("debug: url = {}".format(self.response.url))
except requests.exceptions.RequestException as e:
print("exception: {}".format(e))
#sys.exit(1)
return None
try:
self.response.raise_for_status()
except requests.exceptions.HTTPError as err:
print("http error: {}".format(err))
print(f"\nself.response.attributes = {self.response.__dict__}")
#sys.exit(1)
return None
return self.response
def GetBusinesses(self):
business_url = f"{self.api_url}{self.api_version}/businesses"
input_params = {}
# offset number in list
#input_params['start'] = 0
# max number of businesses to return in list
input_params['limit'] = 200
# filter to these status values
#input_params['status'] = ['active','archived']
r = self.Submit_Get(business_url, input_params)
results = r.json()
if 'values' in results:
# print(f"AFC Business List")
# for b in results['values']:
# print(f"{b}\n")
return results['values']
return None
def PostBusiness(self, business=None):
business_url = f"{self.api_url}{self.api_version}/businesses"
input_params = {}
# business_object = {
# 'name' : 'string',
# "account_id_legacy": "string",
# "primary_contact_name": "string",
# "primary_contact_phone": "string",
# "primary_contact_email": "string",
# "company_public_name": "string",
# "logo_url": "string",
# "bandwidth_campaign_id": "string",
# "reports_required": true,
# "sms_base_price_contract": 0,
# "mms_base_price_contract": 0,
# "mms_included_characters": 0,
# "afc_connect_base_price_contract": 0,
# "afc_crystal_pricing": 0
# }
r = self.Submit_Post(business_url, input_params, data=business)
if r == None:
return None
results = r.json()
return results
def PatchBusiness(self, business_key=None, fields=None):
if business_key == None:
print(f"Can't patch a business without the business key")
return None
if fields == None:
print(f"Can't patch a business without a dict of fields")
return None
business_url = f"{self.api_url}{self.api_version}/businesses/{business_key}"
r = self.Submit_Patch(business_url, input_params={}, data=fields)
if r == None:
return None
results = r.json()
return results

View File

@ -0,0 +1,6 @@
"""
AF Mosiac exceptions
"""
class AFCMUniverseMapFileError(Exception):
"""AFCMUniverseMapFileError class. Custom Exception object."""

View File

@ -0,0 +1,122 @@
"""
AFCMUniverseMapFile Class object
"""
import json
class AFCMUniverseMapFile:
"""
AFCMUniverseMapFile class
"""
def __init__( self, mosaic_filename=None ):
"""
__init__
:param mosaic_filename:
"""
self.mosaic_filename = mosaic_filename
self.mosaic_head = {
"filetype": "universe map file",
"version": '0.10'
}
self.metadata = {
"mosaic_filename": "TeirabDelegateTextFile_MOSIAC.csv",
"mosaic_file_url": None,
"tags": None,
"total_rows": 0,
"total_removed": 0,
"total_optout": 0,
"processing_time": 0
}
self.mosaic_file_list = {}
self.files = []
def read_mosaic_map_file( self, filename ):
"""
read_mosaic_map_file
"""
if filename == '' or filename is None:
return None
with open(filename, encoding='utf-8-sig') as json_file:
data = json.load(json_file)
#print("Type:", type(data))
if 'mosaic' in data:
self.mosaic_head = data['mosaic']
if 'metadata' in data:
self.metadata = data['metadata']
if 'files' in data:
self.mosaic_file_list = data['files']
return data
def write_mosaic_map_file( self, filename ):
"""
write_mosaic_map_file
"""
if filename == '' or filename is None:
return None
output_object = json.dumps({"mosaic": self.mosaic_head,
"metadata": self.metadata,
"files": self.mosaic_file_list}, indent=4)
with open(filename, 'w', encoding="UTF-8") as outfile:
outfile.write(output_object)
return None
def create_new_input_file( self, filename=None ):
"""
create_new_input_file
"""
mosaic_input_file = {
"filename": filename,
"details": {
"csv_get_url": None,
"csv_get_prepped_url": None,
"csv_get_removed_url": None,
"csv_put_url": None,
"mapping": {
"UID": None,
"FName": None,
"LName": None,
"Cell_Phone": None,
"Party": None,
"State": None,
"Precinct": None,
"County": None,
"URL": None
},
"operations": {
"insert": {"field":"*", "operator":"=", "value":"*"}
}
}
}
return mosaic_input_file
def add_new_input_file( self, ifo ):
"""
add_new_input_file
"""
if ifo is None:
return
self.files.append(ifo)

25
setup.py Normal file
View File

@ -0,0 +1,25 @@
"""
Project build definition file.
"""
from setuptools import setup, find_packages
with open('README.md', 'r') as f:
long_description = f.read()
setup(
name='lib_afc_mosiac',
version='0.1.0',
author='',
author_email='',
description='',
long_description=long_description,
long_description_content_type='text/markdown',
zip_safe=False,
include_package_data=False,
packages=find_packages(),
python_requires='>=3.7',
install_requires=[
],
)