def main() -> None: """Main function for running this module""" # Setup API API = nsapi.NSRequester(config.userAgent) # Set endorser nation to check for nation = "kuriko" logging.info("Collecting data") logging.info("Current time is %s UTC", datetime.datetime.utcnow()) region, unendorsed = unendorsed_nations(API, nation) logging.info("Formatting results") # Create output display strings header = f"{nation} has not endorsed the following WA Members in {region}:" nationURLs = "\n".join( # Increment step so that the list is 1-indexed f"{step+1}. https://www.nationstates.net/nation={name}" for step, name in enumerate(unendorsed) ) # Output unendorsed nations logging.info("Writing results") with open(nsapi.absolute_path("endorsements.txt"), "w") as f: # Header print(header, file=f) # Formatted nation urls print(nationURLs, file=f) logging.info("Current time is %s UTC", datetime.datetime.utcnow())
def main() -> None: """Main function""" requester = nsapi.NSRequester(config.userAgent) for output in answer_all(requester, "nation", "autologin"): print(output)
def main() -> None: """Main function""" requester = nsapi.NSRequester(config.userAgent) with open(nsapi.absolute_path("delegacy.txt"), "w") as f: logging.info("Outputting to file.") print("Delegacy changes in the last twelve hours") print( "\n".join( re.sub( # In the text returned by NS api, nation names are enclosed by @@ # and region names by %%. @@(.*?)@@ is a regex pattern that matches # anything surrounded by the @@, as well as the @@ @@. we pull the nation name # by taking group 1 of the match (0 is the entire match). # the nation name is a group because of the () surround the .*? # .*? lazily matches any number of any characters "%%(.*?)%%", lambda match: f"https://www.nationstates.net/region={match.group(1)}", re.sub( "@@(.*?)@@", lambda match: f"https://www.nationstates.net/nation={match.group(1)}", happening.text, ), ) for happening in delegacy(requester) ), file=f, )
def main() -> None: """Main function, mainly for testing purposes.""" parser = argparse.ArgumentParser( description="Collects various information on WA residents of a region." ) parser.add_argument("region", help="Region to search.") parser.add_argument( "-c", "--count", help="Only collect residents with less endorsements than this.", type=int, default=None, ) parser.add_argument("-o", "--output", help="File name to output to instead of stdout.", default=None) # Parse args # Check sys.argv first; if no args provided run interactive mode if len(sys.argv) <= 1: # Interactive mode region = input("Region to search: ") count_raw = input( "Endorsement boundary (type nothing to get all WA): ") count: t.Optional[int] if count_raw: count = int(count_raw) else: count = None output = input("File name to output to: ") else: args = parser.parse_args() region = args.region count = args.count # Setup requester requester = nsapi.NSRequester(config.userAgent) # Use api if getting all residents if not count: nations = residents(requester, region) # Use dump if filtering else: nations = low_endorsements(requester, region, count) # print(listLinks(nations)) # print(nations) if output: with open(output, "w") as out_file: print(listNationCodes(nations), file=out_file) else: print(listNationCodes(nations))
def main() -> None: """Main function""" print( "Specify a file to load the nation list from. (Based on this script's directory)" ) print( "Nation name and password should be seperated with a single comma, no space." ) inputPath = input("File: ") print( "\nShould the passwords be interpreted as autologins keys (encrypted versions)? (y/n)" ) autologinInput = input("Interpret as autologins? ").lower() if autologinInput in ("yes", "y"): isAutologin = True print("Okay, will interpret as autologin keys.") else: isAutologin = False print("Okay, will interpret as regular passwords.") print( "\nEnter a file to generate autologin keys in, or enter nothing to not generate a file." ) outputPath = input("Autologin Output File: ") requester = nsapi.NSRequester(config.userAgent) # Collect nationlist nations = {} with open(nsapi.absolute_path(inputPath), "r") as file: for line in file: # Ignore empty lines if not line == "\n": # Split exactly once to allow passwords that contain commas nation, password = line.strip().split(",", maxsplit=1) nations[nation] = password output = autologin(requester, nations, isAutologin) # Summarize results for nation, result in output.items(): if result: string = f"Successfully logged {nation} in. (Region: {result.region})" if result.wa: string += " (WA)" print(string) else: print(f"Failed to log in {nation}. Likely an incorrect password.") # Only generate output if desired if outputPath != "": with open(nsapi.absolute_path(outputPath), "w") as file: for nation, result in output.items(): print(f"{nation},{result.autologin if result else None}", file=file)
def main() -> None: """Main method for standalone""" requester = nsapi.NSRequester(config.userAgent) rarity = input("Rarity to search for: ") find_rarities(requester, rarity) print(f"Saved results to `{rarity}Cards.json`")
def main() -> None: """Main function""" # Provide proper user agent to api requester requester = nsapi.NSRequester(config.userAgent) # Function arguments, could be connected to command line, etc nation = "ne hcea" lead = "panther" # Actually run the bulk logic print(uncrossed(requester, nation, lead, duration=3600 * 3))
def main() -> None: """Main function""" parser = argparse.ArgumentParser( description="Check for WA Delegacy changes.\n", epilog=delegacy.__doc__, ) parser.add_argument( "-s", "--start", help="Start time, in timestamp seconds.", type=int, default=None, dest="start", ) parser.add_argument( "-e", "--end", help="End time, in timestamp seconds.", type=int, default=None, dest="end", ) parser.add_argument( "-d, --duration", help="Duration, in seconds.", type=int, default=None, dest="duration", ) parser.add_argument("-o", "--output", help="Output file to write to.", default=None, dest="output") args = parser.parse_args() requester = nsapi.NSRequester(config.userAgent) results = delegacy(requester, startTime=args.start, endTime=args.end, duration=args.duration) if args.output: with open("args.output", "w", encoding="utf-8") as file: write_output(results, file) else: write_output(results, sys.stdout)
def main() -> None: """Main function""" requester = nsapi.NSRequester(config.userAgent) print("Specify the region you want to search for card farmers.") region = input("Region: ") print( "\nOptionally, provide a previous output file that indicates nations to not count." ) print( "(i.e. the script will only output nations not in the previous output, i.e. new farmers)." ) print("Or, press enter to not use a previous file.") previousPath = input("Previous Output File: ") print( "\nEnter the name of the output file (defaults to `participants.txt`)") outputPath = input("Output Path: ") if not outputPath: outputPath = "participants.txt" # Load previous file if provided previous: set[str] = set() if previousPath: with open(previousPath, "r", encoding="utf-8") as f: # Each nation name is surrounded by [nation]...[/nation] tags # we remove the leading ones, and then split on the trailing ones # this leaves an extra empty element due to the trailing end tag at the end, # so that is removed with the slice. This process is done for each line, # creating a 2D iterator, which is then flattened using `a for b in c for a in b` # (the double for acts like a nested for loop) previous = { nation for nationLine in ( line.replace("[nation]", "").split("[/nation]")[:-1] for line in f.readlines()) for nation in nationLine } participants = check_region(requester, region, previous) with open(outputPath, "w", encoding="utf-8") as file: for participant in participants: print(f"[nation]{participant}[/nation]", file=file, end="") # Print a trailing newline print("", file=file) print(f"\nCollection complete. ({len(participants)} nations selected.)")
def main() -> None: """Main function""" requester = nsapi.NSRequester(config.userAgent) nation = input("Nation: ") try: autologin = requester.nation( nation, auth=nsapi.Auth( password=getpass.getpass("Password: "******"Something went wrong, likely incorrect password") else: print(f"Autologin: {autologin}")
def main() -> None: """Autlogin a list of nations. Each line should contain a <nation>,<password> pair. Blank lines and lines without a comma are ignored. """ parser = argparse.ArgumentParser(description="Autologin a list of nations.") parser.add_argument( "--plain", action="store_true", dest="plain", help="Treat passwords as plaintext instead of autologin keys.", ) parser.add_argument( "-o", "--output", default=None, help="Output destination of autologin keys." ) args = parser.parse_args() requester = nsapi.NSRequester(config.userAgent) # Parse input results = [] for nation, key in (parse_line(line) for line in sys.stdin): if key: result = login( requester, nation, key if not args.plain else None, key if args.plain else None, ) if result: string = f"Success: {nation} ({result.region})" if result.wa: string += " (WA)" print(string) else: print(f"Failed: {nation}") results.append((nation, result)) # Only generate output if desired if args.output: with open(args.output, "w", encoding="utf-8") as file: for nation, result in results: print(f"{nation},{result.autologin if result else None}", file=file)
def main() -> None: """Main function for running this module""" # Parse nation from command line parser = argparse.ArgumentParser( description="Determine who has not been endorsed.") parser.add_argument("nation", help="Check who this nation has not endorsed.", default=None) parser.add_argument( "--format", help="Format output.", action="store_true", ) args = parser.parse_args() nation: str = args.nation if args.nation else input("Nation: ") # Setup API API = nsapi.NSRequester(config.userAgent) logger.info("Collecting data") logger.info("Current time is %s UTC", datetime.datetime.utcnow()) region, unendorsed = unendorsed_nations(API, nation) # Output unendorsed nations lines: Iterable[str] if args.format: logger.info("Formatting results") # Header header = f"{nation} has not endorsed the following WA Members in {region}:" # Formatted nation urls # Create output display strings # Increment step so that the list is 1-indexed nation_lines = (f"{step+1}. https://www.nationstates.net/nation={name}" for step, name in enumerate(unendorsed)) lines = itertools.chain([header], nation_lines) else: lines = unendorsed logger.info("Writing results") for line in lines: # Print to stdout print(line) logger.info("Current time is %s UTC", datetime.datetime.utcnow())
def main() -> None: """Main method""" requester = nsapi.NSRequester(config.userAgent) endings = founder_endings(requester) # Define default window in seconds # DEFAULT_WINDOW = 24 * 3600 # beforetime = int(time.time()) # sincetime = beforetime - DEFAULT_WINDOW # # Retrieve endings happening data # happenings = requester.world().happenings( # safe=False, sincetime=str(sincetime), beforetime=str(beforetime) # ) print(list(endings))
def update_roster( oldRosterPath: t.Optional[str], outputPath: t.Optional[str], dataPath: str, newPath: t.Optional[str], *, parse_old: bool = True, ) -> None: """Update a roster using the given paths.""" requester = nsapi.NSRequester(config.userAgent) # Collect data with open(dataPath, "r", encoding="utf-8") as file: known: t.Mapping[str, t.Collection[str]] = normalize_known(json.load(file)) # collect current/old roster current: t.Mapping[str, str] if oldRosterPath: with open(oldRosterPath, "r", encoding="utf-8") as file: current = read_old_roster(file, parse_old) else: # read from stdin current = read_old_roster(sys.stdin, parse_old) current = normalize(current) # compare deltas = wa_deltas(requester, current, known) results = wa_changes(deltas) # Summarize results if outputPath: with open(outputPath, "w", encoding="utf-8") as file: print_output(file, results) else: print_output(sys.stdout, results) # Optionally output reorganized known data if newPath: with open(newPath, "w", encoding="utf-8") as file: print_known(file, reorganize(known, extract_new(deltas)))
def main() -> None: """Main function""" print( "Specify a json file to load the nation data from. (Based on this script's directory)" ) inputPath = input("File: ") print("Specify a json file to load old WA data from for comparison.") oldDataPath = input("Old Data File: ") print( "\nEnter a file to generate output in, or enter nothing to output to standard output." ) outputPath = input("Output File: ") requester = nsapi.NSRequester(config.userAgent) # Collect data with open(nsapi.absolute_path(inputPath), "r") as file: nations: t.Mapping[str, t.Collection[str]] = json.load(file) # collect current/old roster with open(nsapi.absolute_path(oldDataPath), "r") as file: current: t.Mapping[str, str] = json.load(file) output = check_roster(requester, nations) # compare changes = { nation: output[nation] if nation in output else Result(None) for nation, oldWA in current.items() if nation not in output or output[nation].wa != oldWA } # Summarize results if outputPath != "": with open(nsapi.absolute_path(outputPath), "w") as file: print_output(file, changes) else: print_output(sys.stdout, changes)
def main() -> None: """Main function""" requester = nsapi.NSRequester(config.userAgent) print("Enter keywords to search for, split with commas.") print("Any region with at least one keyword in the WFE is returned.") keywords = input("Keywords: ").split(",") print("Enter the minimum number of residents of a region.") print("Regions with less residents than this number will not be reported.") print("0 can be used to report all regions that match the keywords.") minimum = int(input("Minimum: ")) print("\nResults:") for region in factbook_searcher(requester, *keywords, populationMinimum=minimum): print( f"https://www.nationstates.net/region={nsapi.clean_format(region.name)}" )
def main() -> None: """Execute main module operations.""" nsapi.enable_logging() parser = argparse.ArgumentParser(description=""" Determine which nations are deployed. Takes roster data from stdin and outputs results to stdout. """) parser.add_argument("leads", nargs="*", metavar="lead", help="Lead nations to check.") args = parser.parse_args() roster = json.load(sys.stdin) requester = nsapi.NSRequester(config.userAgent) deploys = deployments(requester, args.leads, roster) for lead, endos in deploys.items(): print(format_deployed(lead, endos))
def main() -> None: """Main function, mainly for testing purposes.""" requester = nsapi.NSRequester("HN67 API Reader") print(listLinks(residents(requester, "shinka")))
def main(argv: t.Optional[t.Sequence[str]] = None) -> None: """Main function. If args is provided, it is passed to the argparser. Otherwise, first falls back on sys.argv, and then stdin. """ delim = "\t" parser = argparse.ArgumentParser( description="Checks the status of a list of nations.") parser.add_argument( "source", help= """File name or URL to retrieve data from. Expects a tsv formatted file, with the first row being a header including 'nation'. The output will be this data with the new data columns appended. """, ) parser.add_argument( "-u", "--url", action="store_true", help= "Specifies to treat the source argument as a URL, instead of file path.", ) parser.add_argument( "output", help="""File path to write output table to. Outputs a tsv file.""") # Parse args, checking argument, then sys, then stdin if argv: args = parser.parse_args(argv) elif len(sys.argv) > 1: args = parser.parse_args() else: inputString = input("Arguments (One line, -h for help): ") args = parser.parse_args(shlex.split(inputString)) # Get input data if args.url: text = requests.get(args.source).text table = [line.split(delim) for line in text.splitlines()] else: with open(args.source) as file: table = [line.strip().split(delim) for line in file.readlines()] # Create requester requester = nsapi.NSRequester(config.userAgent) output = report_status(requester, table) # Define generator combined = (itertools.chain.from_iterable(twopart) for twopart in zip(table, output)) # Write output logging.info("Writing output to %s", os.path.abspath(args.output)) with open(args.output, "w") as file: for line in combined: print("\t".join(line), file=file)
def main() -> None: """Main function""" # Provide proper user agent to api requester requester = nsapi.NSRequester(config.userAgent) # Function arguments, could be connected to command line, etc # Get nations nations = [] print("Enter the name of the file to load nations from.") print("Nation names in the file can be divided by commas and lines.") print("If you dont wont to load from a file, just press enter.") fileName = input("File name: ") if fileName != "": # Read each line, and split on , with open(fileName, "r") as file: for line in file: nations.extend(line.strip().split(",")) print("\nEnter the names of any regions to search.") print("Every nation in any of the regions provided will be searched.") print( "Seperate multiple regions with a comma, no space (e.g. 'REGION1,REGION 2,REGION 3')." ) print("Enter nothing to not search any regions.") regionsInput = input("Regions: ") if regionsInput != "": regions = regionsInput.split(",") for region in regions: nations.extend( requester.region(region).shard("nations").split(":")) print("\nEnter the names of additional nations you want to search.") print( "Seperate names with a comma, no space (e.g. 'NATION,NATION II,NATION III')." ) extraNations = input("Nations: ") # If they enter nothing, we dont want to add an empty string if extraNations != "": nations.extend(extraNations.split(",")) print(f"\n Checking the following nations: {nations}.") print("\nEnter the card rarities you want to view.") print( "Possibile rarities are: 'common', 'uncommon', 'rare', 'ultra-rare', 'epic', 'legendary'." ) print("You can provide multiple by seperating with a comma, no space.") print("(e.g. 'common,ultra-rare,legendary')") print("Alternatively, enter nothing to view all rarities.") raritiesInput = input("Rarities: ") if raritiesInput == "": rarities = [ "common", "uncommon", "rare", "ultra-rare", "epic", "legendary" ] else: # rarities are case insensitive rarities = [rarity.lower() for rarity in raritiesInput.split(",")] print("Enter whether to collect duplicates of a card on the same nation.") print( "Enter 'yes'/'y' to collect duplicates, or 'no' (or anything else) to not." ) print( "'no' will cause each card to have its own row, even if they are duplicates." ) collectInput = input("Collect duplicates? ").lower() if collectInput in ("yes", "y"): collect = True print("Will collect duplicates.") else: collect = False print("Will not collect duplicates.") # Actually run the bulk logic data = sorted_cards(requester, nations) names = named_cards(requester, extracted_cards(data)) # Output the data as a csv file format path = Path("cardsort.csv").resolve() with open(path, "w") as f: # Write the csv headers headers = "card, cardName, nation, rarity" # Only add copies header if collecting if collect: headers += ", copies" print(headers, file=f) # Unpack the (triple?) mapping, which basically sorts for us for rarity, rarityData in data.items(): # Only output the rarity if desired if rarity in rarities: for nation, nationData in rarityData.items(): for card, count in nationData.items(): # Unroll duplicates if collect option is false row = ("https://www.nationstates.net/page=deck/" f"card={card.id}/season={card.season}" f", {names[card.id]}, {nation}, {rarity}") if not collect: for _ in range(count): print( row, file=f, ) # Write each data in a different column else: print( row + f", {count}", file=f, ) print(f"Outputted to {path}") # prevents the window from immediately closing if opened standalone time.sleep(2)
def main() -> None: """Main function""" # Create requester requester = nsapi.NSRequester(config.userAgent) print("Provide a data file to work through.") print( "Ideally, the file should be a csv-type text format, with each row in this format:" ) print("<card_link>,<sender>,<receiver>,<sender_password>") print( "e.g.: 'https://www.nationstates.net/page=deck/card=926511/season=1,hn67,hn67_ii,aPassword" ) print( "Technically, only the 'card=num/season=num' part of the link is required." ) print( "Also, the password is only required for the first occurence of a nation." ) print( "If your password contains a comma (','), it should be enclosed with double quotes (\")." ) print( "The path to the file is relative to this script. If the file is in the same directory," ) print("just enter the name (e.g. 'gifts.csv')") dataPath = input("Data file: ") print("\nInstead of saving your password in the file," " you can alternatively provide an API autologin,") print("which is a encrypted by NationStates version.") print("Enter 'yes'/'y' to interpret the passwords as autologins," " or 'no' (or anything else) to not.") autologinInput = input("Interpret password fields as autologin? ").lower() if autologinInput in ("yes", "y"): autologin = True print("Interpreting password field as autologins.") else: autologin = False # We save Nation objects so that they can all use the same Auth, i.e. pin nations: MutableMapping[str, nsapi.Nation] = {} with open(nsapi.absolute_path(dataPath), "r", newline="") as file: csvReader = csv.reader(file) for row in csvReader: try: # We need to prepare or find the nation object first (of the sender) nation = nsapi.clean_format(row[1]) if nation not in nations: nations[nation] = requester.nation(nation) # Update the nation auth using given password (or autologin) # Autologin is True if the passwords are actually autologins if autologin: nations[nation].login(row[3]) else: nations[nation].auth = nsapi.Auth(password=row[3]) # Now we can delegate to the function send_card(link=row[0], sender=nations[nation], receiver=row[2]) print(f"Sent {row[0]} from {nation} to {row[2]}") # Broad error cause we want to catch anything, so the whole # program doesnt crash. logs the message except Exception as exception: # pylint: disable=broad-except print("Failed to send a card. Error:", exception)
def main() -> None: """Main entrypoint""" requester = nsapi.NSRequester(config.userAgent)
def main() -> None: """Main method""" # TODO add type checking into the arguments? # would possibly provide better error messages parser = argparse.ArgumentParser( description="Count the issues answered by a set of nations.") subparsers = parser.add_subparsers( help="The possible modes, rerun with [mode] -h for more info.", dest="sub", ) datesParser = subparsers.add_parser("dates") datesParser.add_argument("start", help="The start date, in YYYY-MM-DD format.") datesParser.add_argument("end", help="The end date, in YYYY-MM-DD format.") datesParser.add_argument( "-m", "--month", help="The month to use for a report. Defaults to month of end date.", default=None, ) monthParser = subparsers.add_parser("month") monthParser.add_argument( "month", help=("The month to count across, in YYYY-MM format. " "Compares issue counts from YYYY-MM-01 to (MM+1)-01."), ) # monthParser.add_argument( parser.add_argument( "-r", "--report", action="store_true", help=("Create output in report mode. Produces a formatted file in " "Issue Payout Reports folder for the given month. " "The report is labelled using the month of the starting date, " "unless specified by month parameter."), ) # XKI Puppet List default_source = ( "https://docs.google.com/spreadsheets/d/e/2PACX-1vSem15AVLXgdjxWBZOnWRFnF6NwkY0gVKPYI8" "aWuHJzlbyILBL3o1F5GK1hSK3iiBlXLIZBI5jdpkVr/pub?gid=1588413756&single=true&output=tsv" ) parser.add_argument( "-s", "--source", help=("""URL or file name to retrieve nation list from. Expects either one or two nations seperated by a tab per line, where the second is interpreted as the puppetmaster. Defaults to the XKI puppets URL.""" ), default=default_source, ) parser.add_argument( "-f", "--file", action="store_true", help="Makes the script source from a file instead of URL.", ) parser.add_argument( "-o", "--output", help= "File name to write (raw) output to. Outputs to stdout if not provided.", default=None, ) if len(sys.argv) > 1: args = parser.parse_args() else: inputString = input("Arguments (One line, -h for help): ") args = parser.parse_args(shlex.split(inputString)) requester = nsapi.NSRequester(config.userAgent) # Get input data if args.file: with open(nsapi.absolute_path(args.source)) as file: nations = [line.split("\t") for line in file.readlines()] else: text = requests.get(args.source).text nations = [line.split("\t") for line in text.split("\r\n")] # Convert to puppetmaster dicts # nation[1] is "" if no master, which is falsy # Clean the format of all the names puppets = { nsapi.clean_format(nation[0]): nsapi.clean_format(nation[1]) if nation[1] else nsapi.clean_format(nation[0]) for nation in nations } # Convert dates to start and end date objects if args.sub == "dates": start = datetime.date.fromisoformat(args.start) end = datetime.date.fromisoformat(args.end) # Usually makes sense to have the 'month' (for reports) be the ending date if not provided if args.month: month = datetime.date.fromisoformat(args.month + "-01") else: month = end.replace(day=1) elif args.sub == "month": month = datetime.date.fromisoformat(args.month + "-01") # Last day of previous month, i.e. 08 -> 07-31 start = month - datetime.timedelta(days=1) # Last day of this month, i.e. 08 -> 08-31 end = month.replace( day=calendar.monthrange(month.year, month.month)[1]) logging.info("month: %s start: %s end: %s", month, start, end) counts = count_change(requester, puppets.keys(), start, end) changes = counts[0] # Collect puppetmaster counts collected_count = {puppetmaster: 0 for puppetmaster in puppets.values()} for puppet, change in changes.items(): collected_count[puppets[puppet]] += change def write_output(file: t.TextIO) -> None: for puppetmaster, count in collected_count.items(): print(f"{puppetmaster},{count}", file=file) # Write output if args.output is not None: with open(args.output, "w") as file: write_output(file) else: write_output(sys.stdout) # Generate report if chosen. # Check the subcommand first, because if month # wasnt chosen, the .report attribute wont exist # this avoids any exception due to lazy eval # if args.sub == "month" and args.report: if args.report: report = generate_report(month, collected_count) # Check for output directory if not os.path.isdir(nsapi.absolute_path("IssuePayoutReports")): os.mkdir(nsapi.absolute_path("IssuePayoutReports")) # Write the report with open( nsapi.absolute_path( # Format the month to always be 2-digit f"IssuePayoutReports/issuePayoutReport_{month.year}-{month.month:0>2d}.txt" ), "w", ) as f: f.write(report)
def main() -> None: """Main function""" requester = nsapi.NSRequester(config.userAgent) with open("defenderNations.txt", "w") as f: print(assemble_defender_announcment(requester), file=f)
import config import nsapi from cards import rarityfinder PUPPET_SPREADSHEET = "https://docs.google.com/spreadsheets/d/e/2PACX-1vQolEKIC63tiAK1qpAGac6e-eT99-rjFl6oI8UYf0Rt2CVwWp9KsjOPk8R65O8SS_1yS2Af2fBfR7ly/pub?gid=1588413756&single=true&output=tsv" # pylint: disable=line-too-long # noqa # Set logging level level = logging.INFO logging.basicConfig(level=level) # Name logger logger = logging.getLogger() # Change nsapi logging level nsapi.logger.setLevel(level=level) requester = nsapi.NSRequester(config.userAgent) # load legendary cards rarityfinder.verify_rarity_data(requester, "legendary") cards = rarityfinder.load_rarity_data("legendary") # load member nations response = requests.get(PUPPET_SPREADSHEET) members = { nsapi.clean_format(line.split("\t")[0]) for line in response.text.split("\r\n") } print("Enter the timestamp to check trading since,") print("or press enter to default to the first day of the previous month.") boundInput = input("Timestamp: ")