User:Crasstun/Sandbox

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
#!/home/sigma/.local/bin/python3
# -*- coding: utf-8 -*-
# LGPLv2+ license, look it up

import sys
import os
import builtins

import ceterach
from ceterach import passwords

import mwparserfromhell as mwparser

builtins.print = lambda *args, **kwargs: None

def main():
    global api
    api = ceterach.api.MediaWiki("https://en.wikipedia.org/w/api.php")
    api.login("Lowercase sigmabot II", passwords.lcsb2)
    api.set_token("edit")
    bot = SandBot1(api)
    bot.run()

class SandBot1:
    REINSERT = "{{Please leave this line alone (SB)}}\n\n"
    SANDBOXES = {"Wikipedia:Sandbox",
                 "Wikipedia:Tutorial/Editing/sandbox",
                 "Wikipedia:Tutorial/Formatting/sandbox",
                 "Wikipedia:Tutorial/Wikipedia links/sandbox",
                 "Wikipedia:Tutorial/Citing sources/sandbox",
                 "Wikipedia:Tutorial/Keep in mind/sandbox"
    }
    TEMPLATES = {"Template:Please leave this line alone (Sandbox heading)",
                 "Template:Sandbox heading/noedit",
                 "Template:Sandbox header (do not remove)",
                 "Template:PLTLA (SH)",
                 "Template:Please leave this line alone (sandbox heading)",
                 "Template:Sandbox heading"
    }

    def __init__(self, api, shutoff="User:Lowercase sigmabot II/Shutoff"):
        self.api = api
        self.shutoff_page = api.page(shutoff)

    @property
    def is_allowed(self):
        return self.shutoff_page.content.lower() == "true" #or True

    def check_if_heading_is_gone(self, box):
        tl = self.api.iterator(500, prop="templates", tlnamespace=10, tllimit=500, titles=box.title)
        res = {x['title'] for x in next(tl).get("templates", "")}
        return not res & self.TEMPLATES

    def run(self):
        if not self.is_allowed:
            return
        for sandbox in self.SANDBOXES:
            box = self.api.page(sandbox)
            if box.revision_user.name == "Lowercase sigmabot II":
                continue
            if self.check_if_heading_is_gone(box):
                box.prepend(self.REINSERT, summary="Reinserting sandbox header) (bot", bot=True)
                print("\thad a header reinserted!")

if __name__ == "__main__":
    main()

Sandbot2.py[edit]

{{Please leave this line alone (sandbox heading)}}<!--
*               Welcome to the sandbox!              *
*            Please leave this part alone            *
*           The page is cleared regularly            *
*     Feel free to try your editing skills below     *
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■-->
#!/home/sigma/.local/bin/python3
# -*- coding: utf-8 -*-
# LGPLv2+ license, look it up

import time
import os
import sys
import pickle
import threading

import arrow

import ceterach
from ceterach import passwords

reset_text = "{{subst:Sandbox reset}}"
tpl_reset_text = "{{subst:Template sandbox reset}}"
 
def main():
    global api
    api = ceterach.api.MediaWiki("https://en.wikipedia.org/w/api.php")
    with open("opener.pkl", 'rb') as fp:
        api.opener = pickle.load(fp)
    bot = SandBot2(api)
    bot.run()

class SandBot2:
    SANDBOXES = ("Wikipedia:Sandbox",
                 "Wikipedia:Tutorial/Editing/sandbox",
                 "Wikipedia:Tutorial/Formatting/sandbox",
                 "Wikipedia:Tutorial/Wikipedia links/sandbox",
                 "Wikipedia:Tutorial/Citing sources/sandbox",
                 "Wikipedia:Tutorial/Keep in mind/sandbox"
    )
    SANDBOXES = {"Wikipedia:Sandbox",
                 "Wikipedia:Tutorial/Editing/sandbox",
                 "Wikipedia:Tutorial/Formatting/sandbox",
                 "Wikipedia:Tutorial/Wikipedia links/sandbox",
                 "Wikipedia:Tutorial/Citing sources/sandbox",
                 "Wikipedia:Tutorial/Keep in mind/sandbox",
                 "Wikipedia talk:Sandbox",
                 "Wikipedia talk:Tutorial/Editing/sandbox",
                 "Wikipedia talk:Tutorial/Formatting/sandbox",
                 "Wikipedia talk:Tutorial/Wikipedia links/sandbox",
                 "Wikipedia talk:Tutorial/Citing sources/sandbox",
                 "Wikipedia talk:Tutorial/Keep in mind/sandbox",
                 "User:Sandbox",
                 "Template:Template sandbox",
    }

    def __init__(self, api, shutoff="User:Lowercase sigmabot II/Shutoff"):
        self.api = api
        self.shutoff_page = api.page(shutoff)

    @property
    def is_allowed(self):
        return self.shutoff_page.content.lower() == "true"

    def wait(self, box):
        for __ in range(3):
            # Sleep for 3 minutes
            print("3 minute sleep on {!r}".format(box.title))
            time.sleep(60 * 3)
            if self.box_needs_reset(box):
                break
        # After the bot sleeps on this box for 9 minutes, it
        # will clear the box regardless.
        print("Done with sleeping, clearing {!r}".format(box.title))
        self.api.login("Lowercase sigmabot II", ceterach.passwords.lcsb2)
        self.api.set_token("edit")
        text = tpl_reset_text if box.namespace == 10 else reset_text
        box.edit(text, "Clearing sandbox) (bot", bot=True, force=True)

    def parse_date(self, date):
        return arrow.Arrow.strptime(date, '%Y-%m-%dT%H:%M:%SZ')

    def box_needs_reset(self, box):
        now = arrow.utcnow()
        three_min = arrow.util.timedelta(seconds=60 * 3)
        # there's probably a way to use MediaWiki.iterator(), but too lazy
        res = self.api.call(action="query", prop="revisions", titles=box.title, rvprop="timestamp", limit="2")
        str_stamp = next(iter(res["query"]["pages"].values()))["revisions"][0]["timestamp"]
        box_stamp = self.parse_date(str_stamp)
        if box_stamp < (now - three_min):
            return True
        return False

    def run(self):
        if not self.is_allowed:
            print("Check the shutoff page")
            return
        for sandbox in self.SANDBOXES:
            box = self.api.page(sandbox)
            if box.revision_user.name in ("Lowercase sigmabot II", "Hazard-Bot") or\
               box.content == reset_text:
                continue
            if self.box_needs_reset(box):
                print("Clearing {!r}".format(sandbox))
                print(box.edit(reset_text, "Clearing sandbox) (bot", bot=True, force=True))
            else:
                # The bot will fork, and continue on to the next sandbox
                # while the child process waits 3 to 9 minutes
#               if os.fork() == 0: # Child process
#                   self.wait(box) # Wait takes place in the child process
#                   os._exit(0) # Exit the child process
                threading.Thread(target=self.wait, args=(box,)).start()

if __name__ == "__main__":
    main()