コード例 #1
0
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)
コード例 #2
0
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())
コード例 #3
0
ファイル: update.py プロジェクト: swordrager/nsapi
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,
        )
コード例 #4
0
ファイル: regioncardpop.py プロジェクト: swordrager/nsapi
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 = nsapi.absolute_path(input("Output Path: "))

    # Load previous file if provided
    if previousPath:
        with open(nsapi.absolute_path(previousPath), "r") 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") 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.)")
コード例 #5
0
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)
コード例 #6
0
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)
コード例 #7
0
ファイル: issuecounter.py プロジェクト: swordrager/nsapi
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)
コード例 #8
0
            - datetime.timedelta(days=1)
        )
        # Replace the day with first day, and time with 0
        .replace(day=1, hour=0, minute=0, second=0, microsecond=0).timestamp()
    )

    bound = lastMonth

output = input(
    "Enter the file name to generate output in (will override existing): ")

# check trades of each card
trades = []
for card in cards:
    for trade in requester.card(cardid=int(card["cardid"]),
                                season=card["season"]).trades(
                                    safe=False, sincetime=str(bound)):
        if (nsapi.clean_format(trade.buyer) in members
                or nsapi.clean_format(trade.seller) in members):
            trades.append((card, trade))

# display filtered trades
with open(nsapi.absolute_path(output), "w", encoding="utf-8") as file:
    for card, trade in trades:
        print(
            f"{card['name']} "
            "(https://www.nationstates.net/page=deck/card=926511/season=1/trades_history=1): "
            f"Sold from {trade.seller} to {trade.buyer}.",
            file=file,
        )
コード例 #9
0
            - datetime.timedelta(days=1)
        )
        # Replace the day with first day, and time with 0
        .replace(day=1, hour=0, minute=0, second=0, microsecond=0).timestamp()
    )

    bound = lastMonth

output = input(
    "Enter the file name to generate output in (will override existing): ")

# check trades of each card
trades = []
for card in cards:
    for trade in requester.card(cardid=int(card["cardid"]),
                                season=card["season"]).trades(
                                    safe=False, sincetime=str(bound)):
        if (nsapi.clean_format(trade.buyer) in members
                or nsapi.clean_format(trade.seller) in members):
            trades.append((card, trade))

# display filtered trades
with open(nsapi.absolute_path(output), "w") as file:
    for card, trade in trades:
        print(
            f"{card['name']} "
            "(https://www.nationstates.net/page=deck/card=926511/season=1/trades_history=1): "
            f"Sold from {trade.seller} to {trade.buyer}.",
            file=file,
        )
コード例 #10
0
ファイル: endorsed.py プロジェクト: swordrager/nsapi
# Pull target endorsement list
endorsers = set(requester.nation(target).shard("endorsements").split(","))

# Pull all nations in the region that are WA members
logging.info("Collecting %s WA Members", region)

# Pull all world wa nations
worldWA = set(requester.wa().shard("members").split(","))

# Pull all region nations
regionNations = set(requester.region(region).shard("nations").split(":"))

# Intersect wa members and region members
citizens = worldWA & regionNations

logging.info("Comparing WA Member list with target endorsers")
# Determine WA members who have not endorsed target
nonendorsers = citizens - endorsers

# Print output in formatted manner
logging.info("Outputting results\n")
with open(nsapi.absolute_path("endorsed.txt"), "w") as f:
    # Header
    print(f"The following WA Members of {region} have not endorsed {target}:",
          file=f)
    for step, nonendorser in enumerate(nonendorsers):
        # Increment step so that it is 1-based
        print(f"{step+1}. https://www.nationstates.net/nation={nonendorser}",
              file=f)
コード例 #11
0
def resolve_path(rarity: str) -> str:
    """Generates an absolute path using the rarity name"""
    return nsapi.absolute_path(f"{rarity}Cards.json")