示例#1
0
# endDate = date(2020, 9, 1).isoformat()
# startDate = date(2020, 9, 1).isoformat()
# endDate = date(2020, 11, 20).isoformat()
startDate = date(2020, 11, 20).isoformat()
endDate = date(2020, 12, 5).isoformat()
queryParams = f'?templateId=5f037d852d421&limit=100&fromDts={startDate}&toDts={endDate}'
data = ''
url = S_baseURL + resourcePath + queryParams

## Uncomment the following three lines to do a command line query for a specific name
# firstName = input("First name: ")
# lastName = input("Last name: ")
# url = baseURL + resourcePath + queryParams + f'&firstName={firstName}&lastName={lastName}'

# Make request
response = apiCall(httpVerb, url, data, S_headers)
print(f"Signed waivers retrieved: {len(response['waivers'])}")

# Smartwaiver returns a max of 100 waivers and does not indicate when there is additional data to retrieve
# Print warning to the console to alert users there may be missing data.
if len(response['waivers']) == 100:
    print(
        "WARNING - Max responses received.  Results may not be complete.  Try resubmitting query with tighter date range."
    )

# Convert to pandas DataFrame for data cleaning and merging with Neon info
jsonSigned = json.dumps(response['waivers'])
signed = pd.read_json(jsonSigned)
signed = signed.rename(columns={
    "firstName": "First Name",
    "lastName": "Last Name"
示例#2
0
neonFilename = "Neon/memberAccounts.json"

neonAccounts = {}

# ##### NEON ######
with open(neonFilename) as neonFile:
    neonAccountJson = json.load(neonFile)
    for account in neonAccountJson:
        neonAccounts[neonAccountJson[account]
                     ["Account ID"]] = neonAccountJson[account]

### NOTE this GET has a limit of 1000 users.  If we grow that big, this will be the least of our problems
httpVerb = 'GET'
resourcePath = f'/users?offset=0&sort=identity.lastName&order=asc'
url = url = O_baseURL + resourcePath
opResponse = apiCall(httpVerb, url, "", O_headers)
#pprint(opResponse)

opUsers = {}

if opResponse.get("data"):
    for i in opResponse.get("data"):
        opUsers[i["id"]] = i

opExists = 0
opSuspended = 0
opSubscribers = 0
opMissingWaiver = 0
opMissingTour = 0
opNotReady = 0
opReady = 0
示例#3
0
import json

from config import D_APIkey, D_APIuser
from util import apiCall

### Discourse Account Info
D_baseURL = 'https://yo.atxhs.org'
D_headers = {'Api-Key': D_APIkey, 'Api-Username': D_APIuser}

# Request Info
# Get a list of all active members on Discourse
httpVerb = 'GET'
resourcePath = '/admin/users/list/active.json'
data = ''
url = D_baseURL + resourcePath
usersResponse = apiCall(httpVerb, url, data, D_headers)

# # Print to file
# with open('./Discourse/users.json', 'w') as outfile:
#     json.dump(usersResponse, outfile, indent=4)

print(usersResponse[0]["username"])
print(usersResponse[0]["name"])

# # Request Info
# httpVerb ='GET'
# # resourcePath = '/groups/haxor.json' # id 42
# # resourcePath = '/groups/members2B.json' # id 52
# data = ''

# # Request Info
    for account in neonAccountJson:
        neonAccountList.append(neonAccountJson.get(account))


#check if we have user data cached.  If we do, use it.
if os.path.exists(discourseFilename) and os.access(discourseFilename, os.R_OK):
    with open(discourseFilename) as discourseFile:
        fullDlist = json.load(discourseFile)
else:
    #before doing all the Discourse-fetching, make sure we can write our output file
    outfile = open(discourseFilename, 'w')

    while True:
        resourcePath = f'/admin/users/list/active.json?page={page}'
        url = D_baseURL + resourcePath
        memberResponse = apiCall(httpVerb, url, data, D_headers)
        fullDlist = fullDlist + memberResponse
        if len(memberResponse) < 100:
            break
        else:
            print(f'{len(fullDlist)} active users retrieved from Discourse... Querying for more data.')
            page += 1

    # Fetching emails and checking for weirdness (the weirdness is not coming from here.)
    # this email check is janky somehow - sometimes we get "email":null for accounts with valid emails in their Discourse profile
    # so far the error count has been low enough I've just been updating them in Neon manually
    for i, response in enumerate(fullDlist):
        dID = response['username']
        resourcePath = f'/users/{dID}/emails.json'
        url = D_baseURL + resourcePath
        emailResponse = apiCall(httpVerb, url, data, D_headers)
########### ATXHS NeonCRM & Discourse API Integrations ############
#      Neon API docs - https://developer.neoncrm.com/api-v2/     #
#################################################################

from pprint import pprint
import base64

from config import N_APIkey, N_APIuser
from util import apiCall

# Neon Account Info
N_auth = f'{N_APIuser}:{N_APIkey}'
N_baseURL = 'https://api.neoncrm.com/v2'
N_signature = base64.b64encode(bytearray(N_auth.encode())).decode()
N_headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Basic {N_signature}',
    'NEON-API-VERSION': '2.1'
}

##### NEON #####
# Get possible search fields for POST to /accounts/search
httpVerb = 'GET'
resourcePath = '/accounts/search/searchFields'
queryParams = ''
data = ''
url = N_baseURL + resourcePath + queryParams
response = apiCall(httpVerb, url, data, N_headers)
print("### SEARCH FIELDS ###\n")
pprint(response)
    if (neonAccounts[account].get("validMembership")
            and not neonAccounts[account].get("AccessSuspended")
            and not neonAccounts[account].get("FacilityTourDate")):
        print(
            f'Populating FacilityTourDate for {neonAccounts[account].get("First Name")} {neonAccounts[account].get("Last Name")} ({neonAccounts[account].get("Account ID")})'
        )
        if not dryRun:
            ##### NEON #####
            # Update part of an account
            # https://developer.neoncrm.com/api-v2/#/Accounts/patchAccount
            httpVerb = 'PATCH'
            resourcePath = f'/accounts/{neonAccounts[account].get("Account ID")}'
            queryParams = '?category=Account'
            data = f'''
            {{
            "individualAccount": {{
                "accountCustomFields": [
                {{
                    "id": "182",
                    "name": "FacilityTourDate",
                    "value": "01/01/1970",
                    "status": "ACTIVE"
                }}
                ]
            }}
            }}
            '''
            url = N_baseURL + resourcePath + queryParams
            patch = apiCall(httpVerb, url, data, N_headers)
            pprint(patch)
        "Preferred Name",
        "Account ID",
        "Membership Expiration Date",
        "Membership Start Date",
        85
    ],
    "pagination": {{
    "currentPage": 0,
    "pageSize": 200
    }}
}}
'''

url = N_baseURL + resourcePath + queryParams
neon_accounts = {}
responseAccounts = apiCall(httpVerb, url, data, N_headers)

# exit()

#re-shuffle the data into a format that's a little easier to work with
for acct in responseAccounts["searchResults"]:
    neon_accounts[acct["Account ID"]] = acct

#Because Neon API is dumb, the "expiration date" of an account might not be real --
#The API counts failed renewals as valid as long as automatic renewal is enabled
httpVerb = 'GET'
resourcePath = '/accounts/search'
queryParams = ''
data = ''

for account in neon_accounts: