Optimal linking script of doom

From pisswiki
Revision as of 16:04, 19 July 2021 by Polsaker (talk | contribs) (Restoring the bang)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
#!/usr/bin/env python3

import re
import socket
import subprocess

import requests

_re_ping = re.compile(r".+= .+?/(.+?)/.+?/.+? ms", re.MULTILINE)

print("Hello There!\n")
print("Fetching hubs from the wiki....")
query = "[[Server:+]] [[Category:Nodes]] [[Node Type::Hub]]|?Server Name|?IPv4|?IPv6"
all_hubs = requests.get("https://wiki.letspiss.net/api.php", params={'action': 'ask', 'query': query, 'format': 'json'})
all_hubs = all_hubs.json()['query']['results']

all_pings = []
print(f"\nI got {len(all_hubs)} hubs. Pinging 'em all:")
for hub in all_hubs.values():
    ipv4 = None
    ipv6 = None
    server_name = hub['printouts']['Server Name'][0]
    print(f" - {server_name}...", end="", flush=True)
    if hub['printouts']['IPv4']:
        ipv4 = hub['printouts']['IPv4'][0]

    if hub['printouts']['IPv6']:
        ipv6 = hub['printouts']['IPv6'][0]

    if not ipv4 and not ipv6:  # resolve
        try:
            ipv4 = socket.getaddrinfo(server_name, None, family=socket.AF_INET, type=socket.SOCK_RAW)[0][4][0]
        except socket.gaierror:
            pass
        try:
            ipv6 = socket.getaddrinfo(server_name, None, family=socket.AF_INET6, type=socket.SOCK_RAW)[0][4][0]
        except socket.gaierror:
            pass

    ipv4_ping = 0
    ipv6_ping = 0
    # Do the pinging
    if ipv4:
        command = ['ping', '-c', '5', ipv4]
        try:
            data = subprocess.check_output(command)
            match = _re_ping.findall(data.decode())
            ipv4_ping = float(match[0])
            print(f" v4: {ipv4_ping}ms.", end="", flush=True)
        except subprocess.CalledProcessError:
            print(" v4: error.", end="", flush=True)

    if ipv6:
        command = ['ping', '-c', '5', ipv6]
        try:
            data = subprocess.check_output(command, stderr=subprocess.DEVNULL)
            match = _re_ping.findall(data.decode())
            ipv6_ping = float(match[0])
            print(f" v6: {ipv6_ping}ms.")
        except subprocess.CalledProcessError:
            print(" v6: error.")
    else:
        print()

    # Average because why not
    server_ping = ipv4_ping + ipv6_ping
    if ipv4_ping and ipv6_ping:
        server_ping /= 2

    if server_ping:
        all_pings.append((server_name, server_ping))


# Do the sortin'
all_pings.sort(key=lambda x: x[1])
winners = all_pings[0:3]

print(f"\nI'm choosing {', '.join([x[0] for x in winners])}")

print("Grabbing the link blocks from the wiki...\n\n")

all_blocks = ""
for i in winners:
    query = "{{Link_Block|[[Server:" + i[0] + "]]}}"

    block = requests.get("https://wiki.letspiss.net/api.php",
                         params={'action': 'expandtemplates', 'text': query, 'format': 'json', 'prop': 'wikitext'})
    block = block.json()['expandtemplates']['wikitext']

    # Strip wiki stuff
    block = block.replace("\n ", "\n").replace("[[SMW::off]]\n", "").replace("[[SMW::on]]", "")
    block = block.replace("<br/>", "\n").replace("&nbsp;", " ")
    block = block.replace("{ tls;", "{ tls; autoconnect;")
    all_blocks += block

print("PUT THIS IN YOUR CONFIG FILE")
print("//", "-" * 70)
print(all_blocks)
print("//", "-" * 70)