Started the migration tool scripts. Finished Karbon's script for mass delete and re-addition. Other small things.
This commit is contained in:
@ -218,3 +218,14 @@ https://login.account.wal-mart.com
|
||||
|
||||
Logout:
|
||||
https://www.walmartluminate.com
|
||||
|
||||
## 08-28-2024
|
||||
|
||||
Value they are tracking:
|
||||
* Feedback from clients
|
||||
* Airtable items are directly related to feedback
|
||||
* Defining success solely based on value-add to clients based on feedback.
|
||||
* Tracking declining tickets being opened
|
||||
* The whole goal with this is self service and remove hands-on touch points
|
||||
* Qualitatively, ticket numbers haven't changed much
|
||||
* Partly on how Luminate is structuring their content (shorter answers faster is their goal)
|
||||
|
||||
104
Scripts/Karbon/bulk_delete.py
Normal file
104
Scripts/Karbon/bulk_delete.py
Normal file
@ -0,0 +1,104 @@
|
||||
import requests
|
||||
import Apikeys
|
||||
import csv
|
||||
|
||||
BASEURL = "https://api.northpass.com/v2/"
|
||||
APIKEY = Apikeys.KARBON
|
||||
HEADERS = {
|
||||
"accept": "application/json",
|
||||
"content-type": "application/json",
|
||||
"X-Api-Key": APIKEY,
|
||||
}
|
||||
ADMIN_LIST = [
|
||||
"thea.schlobohm@karbonhq.com",
|
||||
"charles+karbon@northpass.com",
|
||||
"elizabeth.blass@karbonhq.com",
|
||||
"ian.clazie@karbonhq.com",
|
||||
"kelly.gabriel@karbonhq.com",
|
||||
"richard.newman@karbonhq.com",
|
||||
"steven.luu@karbonhq.com",
|
||||
]
|
||||
|
||||
|
||||
def get_people_first():
|
||||
count = 0
|
||||
delete_list = []
|
||||
while True:
|
||||
count += 1
|
||||
person_url = f"{BASEURL}people?page={count}"
|
||||
# &filter[partnerships_type][not_eq]=Partnerships::Admin&include=partnerships&page={count}"
|
||||
# person_url = f"{BASEURL}people?filter[email][not_cont]=karbonhq.com"
|
||||
person_resp = requests.get(person_url, headers=HEADERS)
|
||||
persjson = person_resp.json()
|
||||
nextlink = persjson["links"]
|
||||
|
||||
for people in persjson["data"]:
|
||||
# print(f"This is just everyone... {people['id']}")
|
||||
if people["attributes"]["email"] in ADMIN_LIST:
|
||||
pass
|
||||
else:
|
||||
learneruuid = people["id"]
|
||||
print(people["attributes"]["email"])
|
||||
delete_list.append(learneruuid)
|
||||
|
||||
if "next" not in nextlink:
|
||||
break
|
||||
|
||||
del_load = {"payload": delete_list}
|
||||
print(f"Deleting {len(delete_list)} people")
|
||||
delete_everyone(delete_list)
|
||||
|
||||
|
||||
def get_groups():
|
||||
group_list = []
|
||||
while True:
|
||||
groups_url = f"{BASEURL}groups"
|
||||
groups_resp = requests.get(groups_url, headers=HEADERS)
|
||||
groupjson = groups_resp.json()
|
||||
if len(groupjson['data']) == 0:
|
||||
break
|
||||
else:
|
||||
for groups in groupjson["data"]:
|
||||
guids = groups["id"]
|
||||
print(f"Deleting Group {groups['attributes']['name']}")
|
||||
group_list.append(guids)
|
||||
delete_groups(guids)
|
||||
|
||||
print(f"I've just processed {len(group_list)} groups and deleted them.")
|
||||
|
||||
|
||||
def delete_everyone(uuids):
|
||||
if len(uuids) > 1500:
|
||||
for chunk in range(0, len(uuids), 1500):
|
||||
i = chunk
|
||||
payload_1 = []
|
||||
i_to_add = uuids[i : i + 1500]
|
||||
for person in i_to_add:
|
||||
payload_1.append(person)
|
||||
print(f"This group of people has a count of {len(payload_1)}")
|
||||
payload = {"payload": payload_1}
|
||||
del_url = f"{BASEURL}bulk/people/delete"
|
||||
response = requests.post(del_url, headers=HEADERS, json=payload)
|
||||
print(response.status_code)
|
||||
print(response.text)
|
||||
|
||||
|
||||
def delete_groups(guids):
|
||||
gdel_url = f"{BASEURL}groups/{guids}"
|
||||
gresponse = requests.delete(gdel_url, headers=HEADERS)
|
||||
print(f"Deleted group {guids} with status code {gresponse.status_code}")
|
||||
codes = [500, 403, 404]
|
||||
if gresponse.status_code in codes:
|
||||
print(
|
||||
f"Hm. Something went wrong. Status code: {response.status_code} and text:"
|
||||
)
|
||||
print(response.text)
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Getting Group IDs and Deleting groups.")
|
||||
get_groups()
|
||||
# print("Groups have been deleted. Moving onto people.")
|
||||
# get_people_first()
|
||||
59
Scripts/Karbon/bulk_invite_w_groups.py
Normal file
59
Scripts/Karbon/bulk_invite_w_groups.py
Normal file
@ -0,0 +1,59 @@
|
||||
import requests
|
||||
import json
|
||||
import pprint
|
||||
import csv
|
||||
import pandas as pd
|
||||
import Apikeys
|
||||
import time
|
||||
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
APIKEY = Apikeys.KARBON
|
||||
HEADERS = {
|
||||
"accept": "application/json",
|
||||
"X-Api-Key": APIKEY,
|
||||
}
|
||||
BASEURL = "https://api.northpass.com/v2/"
|
||||
IMPORTFILE = "/Users/normrasmussen/Downloads/karbon-invite-users.csv"
|
||||
|
||||
|
||||
def bulk_invite_and_group():
|
||||
"""
|
||||
Bulk endpoint which invites new people and adds them to a group via this structure:
|
||||
{
|
||||
"email": "me@mac.com"
|
||||
"groups": "GroupA"
|
||||
}
|
||||
|
||||
This function looks for the group in the CSV as well.
|
||||
"""
|
||||
groups_list = []
|
||||
df = pd.DataFrame()
|
||||
data = pd.read_csv(IMPORTFILE)
|
||||
df2 = data[[ "email", "customer_name", "customer_id" ]].copy()
|
||||
customer_ids = df2["customer_id"].unique()
|
||||
customer_ids = list(customer_ids)
|
||||
for row in df2.itertuples():
|
||||
groupname = f"{row[2]}--{row[3]}"
|
||||
groups_list.append(groupname)
|
||||
|
||||
for customer in customer_ids:
|
||||
payload = ""
|
||||
tmp_group = data[data['customer_id'] == customer]
|
||||
people = list(tmp_group["email"])
|
||||
cust = str(tmp_group["customer_id"].unique())[2:-2]
|
||||
url = f"{BASEURL}bulk/people"
|
||||
payload_1 = []
|
||||
for group in groups_list:
|
||||
for person in people:
|
||||
if cust in group:
|
||||
miniload = {"email": person, "groups": group}
|
||||
payload_1.append(miniload)
|
||||
print(f"The {group} payload has {len(payload_1)}")
|
||||
payload = {"data": {"attributes": {"people": payload_1}}}
|
||||
print(payload)
|
||||
response = requests.post(url, headers=HEADERS, json=payload)
|
||||
print(f"Completed. Status code is {response.status_code}")
|
||||
print(response.text)
|
||||
|
||||
if __name__ == "__main__":
|
||||
bulk_invite_and_group()
|
||||
31551
Scripts/Karbon/karbon-doublecheck.txt
Normal file
31551
Scripts/Karbon/karbon-doublecheck.txt
Normal file
File diff suppressed because it is too large
Load Diff
72
Scripts/Karbon/typescript
Normal file
72
Scripts/Karbon/typescript
Normal file
@ -0,0 +1,72 @@
|
||||
Script started on Wed Aug 28 12:49:13 2024
|
||||
[0m[49m[39m[27m[24m
|
||||
[K
|
||||
|
||||
[2A7[0m[49m[39m[0m[49m[38;5;31m[1m[38;5;31m[38;5;39m~[0m[38;5;39m[49m[38;5;31m/Documents/[1m[38;5;31m[38;5;39mWork[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mScripts[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mKarbon[0m[38;5;39m[49m[38;5;31m[0m[38;5;31m[49m[38;5;31m[0m[38;5;31m[49m[30m [0m[30m[49m[39m[38;5;238m.........................................................................................................................................................................[0m[38;5;238m[49m[30m [0m[30m[49m[38;5;66m[39mat [0m[49m[38;5;66m12:49:13[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[39m
|
||||
[0m[49m[39m[0m[49m[38;5;76m>[0m[38;5;76m[49m[38;5;76m[0m[38;5;76m[49m[30m[0m[30m[49m[39m [0m[49m[39m[?2004h[?25l8[0m[38;5;31m[49m[39m[27m[24m[J
|
||||
[0m[27m[24m[J[0m[49m[39m
|
||||
M[0m[49m[38;5;31m[1m[38;5;31m[38;5;39m~[0m[38;5;39m[49m[38;5;31m/Documents/[1m[38;5;31m[38;5;39mWork[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mScripts[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mKarbon[0m[38;5;39m[49m[38;5;31m[0m[38;5;31m[49m[38;5;31m[0m[38;5;31m[49m [0m[38;5;31m[49m[30m[39mon [0m[49m[30m[38;5;244mmain[0m[38;5;244m[49m[30m[0m[30m[49m[30m [0m[30m[49m[39m[38;5;238m......................................................................................................................................................[0m[38;5;238m[49m[30m [0m[30m[49m[38;5;37mpy Scripts[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;66m [39mat [0m[49m[38;5;66m12:49:13[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[39m
|
||||
[0m[49m[39m[0m[49m[38;5;76m>[0m[38;5;76m[49m[38;5;76m[0m[38;5;76m[49m[30m[0m[30m[49m[39m [0m[49m[39m[K[?25h[?2004h[?25l
|
||||
|
||||
M[0m[27m[24m[J[0m[49m[39m
|
||||
M[0m[49m[38;5;31m[1m[38;5;31m[38;5;39m~[0m[38;5;39m[49m[38;5;31m/Documents/[1m[38;5;31m[38;5;39mWork[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mScripts[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mKarbon[0m[38;5;39m[49m[38;5;31m[0m[38;5;31m[49m[38;5;31m[0m[38;5;31m[49m [0m[38;5;31m[49m[38;5;178m[39mon [0m[49m[38;5;178m[38;5;76mmain [38;5;178m!1 [38;5;39m?4[0m[38;5;39m[49m[38;5;178m[0m[38;5;178m[49m[30m [0m[30m[49m[39m[38;5;238m................................................................................................................................................[0m[38;5;238m[49m[30m [0m[30m[49m[38;5;37mpy Scripts[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;66m [39mat [0m[49m[38;5;66m12:49:13[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[39m
|
||||
[0m[49m[39m[0m[49m[38;5;76m>[0m[38;5;76m[49m[38;5;76m[0m[38;5;76m[49m[30m[0m[30m[49m[39m [0m[49m[39m[K[?25hs[1m[31ms[0m[39m[1m[31ms[0m[39m[90msh root@192.168.200.19[39m[22D[1m[31ms[1m[31mc[0m[39m[39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [21D[90mp -r * 'root@192.168.200.18:/main/Media/Music/Sacred Harp Singers of Cork/'[39m[75D[1m[31ms[1m[31mc[1m[31mr[0m[39m[39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [74D[1m[31mr[1m[31mi[0m[39m[1m[31mi[1m[31mp[0m[39m[1m[31mp[1m[31mt[0m[39m[0m[32ms[0m[32mc[0m[32mr[0m[32mi[0m[32mp[0m[32mt[39m[32mt[32m [39m[32mt[39m[39m --eh hep lp[?25l[?2004l
|
||||
|
||||
M[0m[27m[24m[J[0m[49m[27m[24m[38;5;76m>[0m[38;5;76m[49m[39m[27m[24m [32mscript[39m --help[K[?25h
|
||||
|
||||
script: illegal option -- -
|
||||
usage: script [-aeFkpqr] [-t time] [file [command ...]]
|
||||
script -p [-deq] [-T fmt] [file]
|
||||
[1m[7m%[27m[1m[0m
|
||||
|
||||
|
||||
[0m[27m[24m[J[0m[49m[39m
|
||||
M[0m[49m[38;5;31m[1m[38;5;31m[38;5;39m~[0m[38;5;39m[49m[38;5;31m/Documents/[1m[38;5;31m[38;5;39mWork[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mScripts[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mKarbon[0m[38;5;39m[49m[38;5;31m[0m[38;5;31m[49m[38;5;31m[0m[38;5;31m[49m [0m[38;5;31m[49m[30m[39mon [0m[49m[30m[38;5;244mmain [38;5;244m!1 [38;5;244m?4[0m[38;5;244m[49m[30m[0m[30m[49m[30m [0m[30m[49m[39m[38;5;238m................................................................................................................................................[0m[38;5;238m[49m[30m [0m[30m[49m[38;5;37mpy Scripts[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;66m [39mat [0m[49m[38;5;66m12:49:21[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[39m
|
||||
[0m[49m[39m[0m[49m[38;5;196m>[0m[38;5;196m[49m[38;5;196m[0m[38;5;196m[49m[30m[0m[30m[49m[39m [0m[49m[39m[K[?2004h[?25l
|
||||
|
||||
M[0m[27m[24m[J[0m[49m[39m
|
||||
M[0m[49m[38;5;31m[1m[38;5;31m[38;5;39m~[0m[38;5;39m[49m[38;5;31m/Documents/[1m[38;5;31m[38;5;39mWork[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mScripts[0m[38;5;39m[49m[38;5;31m/[1m[38;5;31m[38;5;39mKarbon[0m[38;5;39m[49m[38;5;31m[0m[38;5;31m[49m[38;5;31m[0m[38;5;31m[49m [0m[38;5;31m[49m[38;5;178m[39mon [0m[49m[38;5;178m[38;5;76mmain [38;5;178m!1 [38;5;39m?4[0m[38;5;39m[49m[38;5;178m[0m[38;5;178m[49m[30m [0m[30m[49m[39m[38;5;238m................................................................................................................................................[0m[38;5;238m[49m[30m [0m[30m[49m[38;5;37mpy Scripts[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;37m[0m[38;5;37m[49m[38;5;66m [39mat [0m[49m[38;5;66m12:49:21[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[38;5;66m[0m[38;5;66m[49m[39m
|
||||
[0m[49m[39m[0m[49m[38;5;196m>[0m[38;5;196m[49m[38;5;196m[0m[38;5;196m[49m[30m[0m[30m[49m[39m [0m[49m[39m[K[?25hm[1m[31mm[0m[39m[1m[31mm[0m[39m[90mv translate_css.py ./Luminate[39m[29D[1m[31mm[1m[31ma[0m[39m[39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [28D[90mn curl[39m[1m[31mm[1m[31ma[1m[31mn[0m[39m[0m[32mm[0m[32ma[0m[32mn[39m[32mn[32m [39m[32mn[39m[39m [39ms[39m [39m [39m [90mips[39m[39mc[39m [39m ript[?25l[?2004l
|
||||
|
||||
M[0m[27m[24m[J[0m[49m[27m[24m[38;5;196m>[0m[38;5;196m[49m[39m[27m[24m [32mman[39m script[K[?25h
|
||||
|
||||
[?1049h[?1h=
|
||||
SCRIPT(1) General Commands Manual SCRIPT(1)
|
||||
|
||||
[1mNAME[0m
|
||||
[1mscript[0m – make typescript of terminal session
|
||||
|
||||
[1mSYNOPSIS[0m
|
||||
[1mscript[0m [[1m-aeFkqr[0m] [[1m-t[0m [4mtime[24m] [[4mfile[24m [[4mcommand[24m [4m...[24m]]
|
||||
[1mscript[0m [1m-p[0m [[1m-deq[0m] [[1m-T[0m [4mfmt[24m] [[4mfile[24m]
|
||||
|
||||
[1mDESCRIPTION[0m
|
||||
The [1mscript[0m utility makes a typescript of everything printed on your terminal. It is useful for students who need a hardcopy record of an interactive session as proof of an assignment, as the typescript file
|
||||
can be printed out later with lpr(1).
|
||||
|
||||
If the argument [4mfile[24m is given, [1mscript[0m saves all dialogue in [4mfile[24m. If no file name is given, the typescript is saved in the file [4mtypescript[24m.
|
||||
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K If the argument [4mcommand[24m is given, [1mscript[0m will run the specified command with an optional argument vector instead of an interactive shell.
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K The following options are available:
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K [1m-a[0m Append the output to [4mfile[24m or [4mtypescript[24m, retaining the prior contents.
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K [1m-d[0m When playing back a session with the [1m-p[0m flag, do not sleep between records when playing back a timestamped session.
|
||||
:[K
|
||||
[K [KESCESC[KOO[KBB
|
||||
[K
|
||||
@ -2,7 +2,7 @@ import Apikeys
|
||||
import requests
|
||||
import pandas as pd
|
||||
|
||||
IMPORTFILE = '~/Downloads/karbon-existing-groups.csv'
|
||||
IMPORTFILE = '~/Downloads/karbon-invite-users.csv'
|
||||
APIKEY = Apikeys.KARBON
|
||||
HEADERS = {"accept": "application/json", "X-Api-Key": APIKEY }
|
||||
BASEURL = "https://api.northpass.com/v2/"
|
||||
|
||||
1
Scripts/Migration_tool/Apikeys.py
Normal file
1
Scripts/Migration_tool/Apikeys.py
Normal file
@ -0,0 +1 @@
|
||||
SANDBOX = "SlpQlju219WnWogn94dQUT6Yt"
|
||||
BIN
Scripts/Migration_tool/__pycache__/Apikeys.cpython-310.pyc
Normal file
BIN
Scripts/Migration_tool/__pycache__/Apikeys.cpython-310.pyc
Normal file
Binary file not shown.
51
Scripts/Migration_tool/create_project.py
Normal file
51
Scripts/Migration_tool/create_project.py
Normal file
@ -0,0 +1,51 @@
|
||||
import requests
|
||||
import Apikeys
|
||||
import pprint
|
||||
|
||||
PP = pprint.PrettyPrinter(indent=4)
|
||||
APIKEY = Apikeys.SANDBOX
|
||||
HEADERS = {"content-type": "application/json", "X-Api-Key": APIKEY}
|
||||
BASEURL = "https://api.northpass.com/v2/migration"
|
||||
|
||||
def create_project():
|
||||
"""
|
||||
Function to create a project with just a name. While ID is in the example payload, it isn't needed.
|
||||
Will generate a project ID for you in the return that you can use to transfer everything.
|
||||
Note that it will not give you an error if a project already exists with that name!
|
||||
"""
|
||||
payload = { "data": {
|
||||
"type": "migration_projects",
|
||||
"attributes": {
|
||||
"name": "My Second Migration Project"
|
||||
},
|
||||
} }
|
||||
create_req = requests.post(f"{BASEURL}/projects", headers=HEADERS, json=payload)
|
||||
print(payload)
|
||||
print(create_req.status_code)
|
||||
print(create_req.text)
|
||||
|
||||
|
||||
def get_all_projects():
|
||||
"""
|
||||
Returns all projects. Leverage PrettyPrint or uncomment the name to just return names and ids.
|
||||
"""
|
||||
get_proj = requests.get(f"{BASEURL}/projects", headers=HEADERS)
|
||||
print(get_proj.status_code)
|
||||
# PP.pprint(get_proj.json())
|
||||
|
||||
for items in get_proj.json()['data']:
|
||||
print(f"{ items['attributes']['name'] } -- { items['id'] }")
|
||||
|
||||
def get_specific_project():
|
||||
"""
|
||||
Returns results from a specific project.
|
||||
"""
|
||||
proj_id = "13aa7aed-3fb5-4488-9185-3befd0c1ae86"
|
||||
get_spec_proj = requests.get(f"{BASEURL}/projects/{proj_id}", headers=HEADERS)
|
||||
print(get_spec_proj.status_code)
|
||||
PP.pprint(get_spec_proj.json())
|
||||
|
||||
if __name__ == "__main__":
|
||||
# create_project()
|
||||
# get_all_projects()
|
||||
get_specific_project()
|
||||
2
Todos.md
2
Todos.md
@ -371,7 +371,7 @@ message](https://northpasshq.slack.com/archives/C04RER4PH09/p1709147957374999?th
|
||||
|
||||
## 07-17-2024
|
||||
|
||||
- [ ] Chubb - Send Steve Google App Script & ask Kim what report she needs
|
||||
- [X] Chubb - Send Steve Google App Script & ask Kim what report she needs
|
||||
- [ ] Chubb - Ask SE for Delivery Log export from db. They are trying to find the best way to reminder agents who haven't started anything to actually start the path. Include all the data.
|
||||
- [X] Volt - They would like an Archive Webhook. "It's necessary for the whole equation of getting everything up to enterprise level standards." No rush but it would help fill in the whole circle.
|
||||
- [X] HH - Looker: Course Completion, only yes, last 24 hours, scheduled for "results are changed" and 8am every day.
|
||||
|
||||
Reference in New Issue
Block a user