···
from base64 import b64encode
from argparse import ArgumentParser
···
145
-
def format_json(msg, object) -> str:
147
+
def format_json(object) -> str:
148
+
global noprettyprint
return json.dumps(object, indent=None if noprettyprint else 4)
148
-
def debug(msg, *arg, **kwarg) -> None:
151
+
def debug(msg, *arg, override=False, **kwarg) -> None:
153
+
if verbose or override:
print("\x1b[37m[*]", msg, *arg, "\x1b[0m", file=sys.stderr, **kwarg)
def info(msg, *arg, **kwarg) -> None:
···
def error(msg, *arg, **kwarg) -> None:
print("\x1b[31m[x]", msg, *arg, "\x1b[0m", file=sys.stderr, **kwarg)
172
+
def prompt_bool(msg, default: typing.Optional[bool] = True) -> bool:
174
+
Prompt the user for a y/n value until a valid input is entered.
176
+
:param msg: Message to display
177
+
:param default: What should the default value be if the user pressed enter. Pass in None to force user to pick one.
180
+
p_string = f"({'Y' if default else 'y'}/{'N' if not default else 'n'})" if default is not None else "(y/n)"
181
+
while not resolved:
182
+
print("\x1b[35m[?]", msg, f"\x1b[0m{p_string}", file=sys.stderr, end=" ")
186
+
debug("^D", override=True)
187
+
debug("gracefully handling EOF")
188
+
error("invalid input, please try again.")
191
+
if default is None and r.strip() == "":
192
+
error('a response is required. please enter either y or n.')
194
+
if r.strip() == "":
196
+
# if r.strip()[0].lower() not in ['y', 'n']:
197
+
# error('invalid input. please enter either y or n.')
199
+
match r.strip()[0].lower():
205
+
error('invalid input. please enter either y or n.')
parser = ArgumentParser()
parser.add_argument('-v', '--verbose', action='store_true', help="be more noisy")
···
222
+
global verbose, noprettyprint
args = parser.parse_args()
225
+
noprettyprint = args.no_pretty
info("nitter-guest-account.py (2023-08-25)")
info("This is free software: you are free to change and redistribute it, under the terms of the Apache-2.0 license")
···
success(f'flow token => {flow_token}')
info('Fetching final account object...')
217
-
tasks = send_req('post', TASKS_ENDPOINT, headers=request_headers, json=get_tasks_body(flow_token))
259
+
tasks = send_req('post', TASKS_ENDPOINT, headers=request_headers, json=get_tasks_body(flow_token)).json()
262
+
open_account_task = next(filter(lambda i: i.get('subtask_id') == "OpenAccount", tasks['subtasks']))
263
+
account = open_account_task['open_account']
264
+
except StopIteration:
265
+
debug("resulting tasks =>", format_json(tasks), override=True)
266
+
error("Unable to acquire guest account credentials as it isn't present in the API response.")
267
+
error("This might be because of a wide variety of reasons, but it most likely is due to your IP being rate-limited.")
268
+
error("Try again with a new IP address or in 24 hours after this attempt.")
271
+
if args.outfile == "-":
272
+
debug("outfile is `-`, printing to stdout")
273
+
print(format_json(account))
278
+
debug(f"attempting to read file: {args.outfile}")
279
+
with open(args.outfile) as f:
280
+
old_data = json.load(f)
281
+
except FileNotFoundError:
282
+
# that's okay, we might be able to create it later.
284
+
except PermissionError:
285
+
# that's not okay. we will need to access the file later anyways.
286
+
error("unable to read file due to a permission error.")
287
+
error("please make sure this script has read and write access to the file.")
288
+
print(format_json(account))
290
+
except json.JSONDecodeError:
291
+
error("could not parse the provided JSON file.")
292
+
if not prompt_bool("Do you want to overwrite the file?", default=None):
293
+
warn("Not overwriting file, printing to stdout instead.")
294
+
print(format_json(account))
296
+
debug('assuming old data is an empty array because we are overwriting')
298
+
if type(old_data) != list:
299
+
error("top-level object of the existing JSON file is not a list.")
300
+
error("due to the implementation, the file must be overwritten.")
301
+
if not (prompt_bool("Do you want to overwrite?", default=None)):
302
+
warn("Not overwriting existing data, printing to stdout instead.")
303
+
print(format_json(account))
305
+
debug("assuming old data is an empty array because we are overwriting")
308
+
old_data.append(account)
311
+
debug("attempting to write file")
312
+
with open(args.outfile, 'w+') as f:
313
+
f.write(format_json(old_data))
314
+
success(f"successfully written to file {args.outfile}")
316
+
except PermissionError:
317
+
error("unable to write to file due to permission error.")
318
+
error("please make sure this script has write access to the file.")
319
+
print(format_json(account))
321
+
except Exception as e:
322
+
error("Unable to write to file due to an uncaught error:", e)
323
+
tb = ''.join(traceback.TracebackException.from_exception(e).format())
324
+
debug("exception stacktrace\n" + tb)
325
+
print(format_json(account))
328
+
debug("resulting tasks =>", format_json(tasks), override=True)
329
+
error("an unhandled error occurred. the tasks object is printed to avoid losing otherwise successful data.")
330
+
error("please file a bug report and attach the traceback below.")