initial commit
This commit is contained in:
commit
9f641c2bbf
|
|
@ -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/
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
"""
|
||||||
|
AF Mosiac exceptions
|
||||||
|
"""
|
||||||
|
|
||||||
|
class AFCMUniverseMapFileError(Exception):
|
||||||
|
"""AFCMUniverseMapFileError class. Custom Exception object."""
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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=[
|
||||||
|
|
||||||
|
],
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue