This repository was archived by the owner on Dec 12, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi_interfaces.py
More file actions
362 lines (292 loc) · 16.3 KB
/
api_interfaces.py
File metadata and controls
362 lines (292 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
from dap_logging import dap_log_pipl, dap_log_clicksend, dap_log_lob, dap_log_facebook, dap_log_compliance, LogLevel
def api_pipl(defendant_name, business_tier=False):
# submit api call to pipl using defendant name, city columbus, county muscogee, state georgia
# code snippets
# https://docs.pipl.com/docs/code-snippets
# python library
# https://docs.pipl.com/docs/code-libraries#section-python
# get first match back, which is the most likely candidate, ignore multiple matches for now
# if a match from pipl, set match_true = true, populate return variables with data from ppl
# if no match from pipl, set met_true = false, leave other return variables blank
# adapted from sample code:
from api_keys import pipl_social_api_key, pipl_biz_api_key, pipl_contact_api_key
from piplapis.search import SearchAPIRequest
from piplapis.search import SearchAPIResponse
from piplapis.search import SearchAPIError
from piplapis.data import Person, Name, Address
import pipl_processing
import datetime
# create return object + set default state
defendant = {"match_true": False}
SearchAPIRequest.set_default_settings(api_key=pipl_contact_api_key, minimum_probability=0.8,
use_https=True) # use encrypted connection and ensure 80% probability matching
# Split name supplied into values parsable by request api
names = defendant_name.split(' ')
defendant_last_name = names[0]
defendant_middle_name = "" # ensures always initialized
# handle cases 2, 3 or more total names
if len(names) == 2:
defendant_first_name = names[1]
elif len(names) == 3:
defendant_middle_name = names[2]
defendant_first_name = names[1]
else:
# TODO: handle >3 names
dap_log_pipl(LogLevel.ERROR, "invalid name format: %s" % defendant_name)
return defendant
fields = [Name(first=defendant_first_name, middle=defendant_middle_name, last=defendant_last_name),
Address(country=u'US', state=u'GA', city=u'Columbus') # all cases on this mainframe will be located here,
]
# prepare request (use contact-tier key by default, business-tier if specificied)
key = pipl_biz_api_key if business_tier else pipl_contact_api_key
request = SearchAPIRequest(person=Person(fields=fields), api_key=key)
# for debugging
dap_log_pipl(LogLevel.DEBUG, str(request.__dict__))
# TODO: log api messages to pipl.log
# assures that reference is assigned before later access
response = None
person = None
# try fetching a request
try:
dap_log_pipl(LogLevel.DEBUG, "fetching request...")
response = request.send()
except SearchAPIError as e:
message = "SearchAPIError: %i: %s" % (e.http_status_code, e.error)
dap_log_pipl(LogLevel.CRITICAL, message)
# direct match found!
if response and response.person:
dap_log_pipl(LogLevel.DEBUG, "direct match!")
person = response.person
# possible matches found, pick most likely candidate
elif response and len(response.possible_persons) > 0:
dap_log_pipl(LogLevel.DEBUG, "possible matches, searching...")
local_list = list()
for possible in response.possible_persons:
local_addresses = pipl_processing.get_matching_addresses(addresses=possible.addresses,
city="Columbus",
state="GA")
# Person is a local resident, add them to list of local_list
if len(local_addresses) != 0:
local_list.append(possible)
# TODO: pick from list of possible persons, placeholder for further processing
if len(local_list) != 0:
dap_log_pipl(LogLevel.DEBUG, "match found!")
person = local_list[0]
# no match found or empty response
else:
if not response:
message = "Empty response!"
dap_log_pipl(LogLevel.ERROR, message)
else:
message = "No matching person found for %s." % defendant_name
dap_log_pipl(LogLevel.WARN, message)
if person:
# TODO: catch index exceptions thrown in case of empty arrays?
# a match was found!
defendant["match_true"] = True
# set default values before parsing person object
defendant_house = None
defendant_address = None
defendant_apartment = None
defendant_email = ""
defendant_facebook = ""
# parse addresses, see https://docs.pipl.com/reference#address
# Get addresses from within Columbus, GA
addresses = pipl_processing.get_matching_addresses(addresses=person.addresses,
city="Columbus",
state="GA")
# for matching addresses within the state find latest (if > 1)
last_seen = None
for address in addresses:
# This is the marked current address, break out of loop
if address.current and address.current == True:
defendant_address = address
break
# Skip if old, skip if work and record to compliance log, default type is home
if address.type:
if address.type == "work":
# TODO: record a note to compliance.log
dap_log_pipl(LogLevel.INFO, "Work address found for %s, skipping." % defendant_name)
elif address.type == "old":
continue
# address has last_seen date, compare to set as latest
if address.last_seen:
if not last_seen or address.last_seen >= last_seen:
last_seen = address.last_seen
defendant_address = address
# if no last_seen on any address supplied, pick first from array
# and set last_seen to unix epoch (so any last_seen is bigger)
else:
if not defendant_address:
last_seen = datetime.datetime.utcfromtimestamp(0)
defendant_address = address
last_seen = None
for email in person.emails:
# This is the current email, break out of loop
if email.current and email.current == True:
defendant_email = email.address
break
# Skip if work email and record to compliance log, default type
# if omitted is personal
if email.type and email.type == "work":
dap_log_pipl(LogLevel.INFO, "Work email found for %s, skipping." % defendant_name)
continue
# email has last_seen date, compare to set as latest
if email.last_seen:
if not last_seen or email.last_seen >= last_seen:
last_seen = address.last_seen
defendant_email = email.address
# if no last_seen on any email supplied, pick first from array
# and set last_seen to unix epoch (so any last_seen is bigger)
else:
if not defendant_email:
last_seen = datetime.datetime.utcfromtimestamp(0)
defendant_email = email.address
# parse facebook, see see https://docs.pipl.com/reference#user-id
last_seen = None
for id in person.user_ids:
# empty id or not a facebook id, continue through loop
if not id.content or not id.content.endswith("@facebook"):
continue
# email has last_seen date, compare to set as latest
if id.last_seen:
if not last_seen or id.last_seen >= last_seen:
last_seen = id.last_seen
defendant_facebook = id.content[0:-9] # remove '@facebook'
# if no last_seen on any email supplied, pick first from array
# and set last_seen to unix epoch (so any last_seen is bigger)
else:
if not defendant_facebook:
last_seen = datetime.datetime.utcfromtimestamp(0)
defendant_facebook = id.content[0:-9] # remove '@facebook'
# handle usage of contact vs. business tier api keys
if business_tier:
if not defendant_email:
dap_log_pipl(LogLevel.ERROR, "business-tier api requested, but no email returned!")
# if running at business tier, only return dict with email supplied, as this
# call of api_pipl() will have been made recursively from a contact-tier call
# to api_pipl()
defendant["email"] = defendant_email
return defendant
else:
if defendant_email == "full.email.available@business.subscription":
dap_log_pipl(LogLevel.DEBUG, "contact-tier email returned, re-running with business api keys")
defendant_email = api_pipl(defendant_name, business_tier=True)["email"]
elif defendant_email != "":
dap_log_pipl(LogLevel.ERROR, "contact-tier returned non-null, valid (?) email: %s" % defendant_email)
# set all parsed values
if not defendant_address: defendant_address = Address()
defendant["house"] = defendant_address.house if defendant_address.house else ""
defendant["street"] = defendant_address.street if defendant_address.street else ""
defendant["apartment"] = defendant_address.apartment if defendant_address.apartment else ""
defendant["city"] = defendant_address.city if defendant_address.city else ""
defendant["state"] = defendant_address.state if defendant_address.state else ""
defendant["zip"] = defendant_address.zip_code if defendant_address.zip_code else ""
defendant["email"] = defendant_email
defendant["facebook"] = defendant_facebook
dap_log_pipl(LogLevel.DEBUG, "%s: %s" % (defendant_name, str(defendant)))
return defendant
def api_lob(court_name, case_number, date_filed, plaintiff_name, defendant_name, defendant_house, defendant_street, defendant_apt, defendant_city,
defendant_state, defendant_zip):
# api documentation
# https://lob.com/docs/python#letters_create
# python library
# https://github.com/lob/lob-python
import datetime
from api_keys import lob_api_key
import lob
lob.api_key = lob_api_key
d = datetime.datetime.today()
# split and reorganize defendant_name into first, middle, last
dap_log_lob(LogLevel.INFO, "sending letter to: %s" % defendant_name)
names = defendant_name.split(' ')
defendant_last_name = names[0]
defendant_middle_name = ""
if len(names) == 2:
defendant_name = names[1] + " " + names[0]
elif len(names) == 3:
defendant_name = names[1] + " " + names[2] + ". " + names[0]
else:
dap_log_lob(LogLevel.ERROR, "invalid name format: %s" % defendant_name)
return defendant_name
# convert
if defendant_apt == "":
address_line1 = defendant_house + " " + defendant_street
else:
address_line1 = defendant_house + " " + defendant_street + " " + defendant_apt
dap_log_lob(LogLevel.DEBUG, address_line1)
try:
dap_log_lob(LogLevel.DEBUG, "creating letter...")
letter = lob.Letter.create(
description='Bankruptcy Letter',
to_address={
'name': defendant_name,
'address_line1': address_line1,
'address_city': defendant_city,
'address_state': defendant_state,
'address_zip': defendant_zip
},
from_address='adr_a35f94ee46742f37', # ID of a return address saved in lob account
file='tmpl_e5ad54069175664', # ID of an HTML template saved in lob account, uses merge variables from below
# see guide https://lob.com/resources/guides/general/templates
# use simple template like https://lob.com/resources/template-gallery/failed-payment-notice-letter-template/gtmpl_962f66c6ba95bd
merge_variables={
'defendant_name': defendant_name,
'defendant_name_normalized' : str.title(defendant_name),
'plaintiff_name': plaintiff_name,
'plaintiff_name_normalized': str.title(plaintiff_name),
'court_name': court_name,
'case_number': case_number,
'date_filed': date_filed,
'date_filed_year': date_filed[-2:],
'todays_date': d.strftime('%-m/%-d/%Y'),
},
color=True
)
except Exception as e:
dap_log_lob(LogLevel.ERROR, str(e))
return {"success": False}
else:
dap_log_lob(LogLevel.INFO,
f"id={letter['id']}, expected_delivery_date={letter['expected_delivery_date']}, " +
f"tracking_number={letter['tracking_number']}")
mail_results = {"success": True}
mail_results.update(letter)
return mail_results
def api_clicksend(court_name, case_number, date_filed, plaintiff_name, defendant_name, defendant_email):
# https://developers.clicksend.com/docs/rest/v3/?python#ClickSend-v3-API-Transactional-Email
# to get e-mail address from pipl API, need to upgrade pipl api key from social to business level (leave at social until turn on e-mail)
# adapted from sample code:
import clicksend_client
from clicksend_client.rest import ApiException
from clicksend_client import EmailRecipient
from clicksend_client import EmailFrom
from clicksend_client import Attachment
configuration = clicksend_client.Configuration()
from api_keys import configuration_username, configuration_password
api_instance = clicksend_client.TransactionalEmailApi(clicksend_client.ApiClient(configuration))
email_recipient = EmailRecipient(email=defendant_email, name=defendant_name)
email_from = EmailFrom(email_address_id='6467', name='Hayden Barnes')
email = clicksend_client.Email(to=[defendant_email],
bcc=[email_recipient], # send to storage e-mail account for arching
_from=[email_from],
subject="Legal Advertising: Lawsuit Filed In Muscogee County",
body="Court records show that a lawsuit was filed against [defendant_name] in Muscogee County, Georgia by [plaintiff_name_normalized] on [date_filed].\nIf you are the {{defendant_name_normalized}} named in this lawsuit and you are struggling to pay your bills we are here to help. We are bankruptcy lawyers dedicated to helping individuals and families experiencing temporary hardship regain their financial independence.\nAnyone can experience financial difficulties. Bankruptcy is designed to give those individuals and families a fresh start. Rather than waiting and worrying you can take your first steps to your financial freedom today.\nYou may be eligible to consolidate your debts into one lower monthly payment through a Chapter 13 reorganization. You may also be eligible to discharge your debts with a Chapter 7 bankruptcy. Both methods will stop creditors from calling, garnishing your wages, or taking your property.\nWe provide a free, no-obligation consultation to discuss your financial situation and whether bankruptcy is an option for you. Call us at 706.690.4471 day or night so we can schedule an appointment for you.")
try:
api_response = api_instance.email_send_post(email)
dap_log_clicksend(LogLevel.DEBUG, str(api_response))
# ! record clicksend api response to clicksend.log
except ApiException as e:
dap_log_clicksend(LogLevel.ERROR, "exception when calling TransactionalEmailApi->email_send_post: %s" % str(e))
return 0
def api_facebook(court_name, case_number, date_filed, plaintiff_name, defendant_name, defendant_facebook):
# https://fbchat.readthedocs.io/en/latest/intro.html
# adapted from sample code:
# from fbchat import Client
# import fbchat.models
# from api_keys import facebook_email, facebook_password
# client = Client(facebook_email, facebook_password)
# client.send(fbchat.models.Message(text="Message"), thread_id=client.uid,
# thread_type=fbchat.models.ThreadType.USER)
# ! record facebook response to facebook.log
return 0