def __init__(self, table):
        """
        Populate self.found with legitimate entries
        Works by looking for target date on the backend, and then finding all entries with matching dates...
           ... and then adding any entries with any that share the same recordid
        """
        super().__init__()
        d = {"table": table}

        self.name = self.__class__.__name__.replace("_", " ")
        self.define()
        self.setup_date()

        self.repeatingevents = RepeatingEvents(self.repeating_events_db_path, self.unique)

        self.priority_one_users = []
        for user_id in self.priority_ids:
            self.priority_one_users.append(self.get_user_name(user_id))
        self.verbose and print(self.priority_one_users)

        # Initial values
        month = self.date.month
        day = self.date.day
        year = self.date.year

        self.final = []
        self.field_updater = RelativeDateFieldUpdater("Maths Club Sign up", "Date to Attend")

        d["date_to_check"] = self.field_updater.format_date(self.date)
        d["field_id"] = self.field_updater.target_id
        potential_rows = self.sql(
            "select * from {table} where content like '%{date_to_check}%' and fieldid={field_id}".format(**d)
        )()
        for row in potential_rows:
            recordid = row[2]
            user = self.get_user_name_from_recordid(recordid)
            self.final.append({"user": user, "content": row[3]})
        self.verbose and input(self.found)
        self.reconstruct_found()
class Maths_Club(DragonNetDBConnection):
    """
    Converts a database on moodle into a useable system that emails users
    """

    verbose = False

    def __init__(self, table):
        """
        Populate self.found with legitimate entries
        Works by looking for target date on the backend, and then finding all entries with matching dates...
           ... and then adding any entries with any that share the same recordid
        """
        super().__init__()
        d = {"table": table}

        self.name = self.__class__.__name__.replace("_", " ")
        self.define()
        self.setup_date()

        self.repeatingevents = RepeatingEvents(self.repeating_events_db_path, self.unique)

        self.priority_one_users = []
        for user_id in self.priority_ids:
            self.priority_one_users.append(self.get_user_name(user_id))
        self.verbose and print(self.priority_one_users)

        # Initial values
        month = self.date.month
        day = self.date.day
        year = self.date.year

        self.final = []
        self.field_updater = RelativeDateFieldUpdater("Maths Club Sign up", "Date to Attend")

        d["date_to_check"] = self.field_updater.format_date(self.date)
        d["field_id"] = self.field_updater.target_id
        potential_rows = self.sql(
            "select * from {table} where content like '%{date_to_check}%' and fieldid={field_id}".format(**d)
        )()
        for row in potential_rows:
            recordid = row[2]
            user = self.get_user_name_from_recordid(recordid)
            self.final.append({"user": user, "content": row[3]})
        self.verbose and input(self.found)
        self.reconstruct_found()

    def __del__(self):
        self.field_updater.update_menu_relative_dates(forward_days=14)
        super().__del__()

    def setup_date(self):
        """
        Responsible for setting up date variables, self.date and self.custom_date
        """
        if self.search_date == "same day":
            self.date = today()
        elif self.search_date == "next day":
            self.date = tomorrow()
        elif self.search_date == "day before":
            self.date = yesterday()
        else:
            raise Nothing

        self.custom_date = custom_strftime("%A %B {S}, %Y", self.date)
        print(self.date)

    def define(self):
        """
        Override in subclass in order to specify the fields
        """
        # priority_ids
        self.priority_ids = []
        # priority_ids have to be list of id numbers of users whose posts should be given priority 1

        # fields
        self.fields = ["date"]
        # fields has to be typed in the order in which it appears
        # when sorted in ascending order by recordid on the backend

        # search_date
        self.search_date = "same day"
        # one of three values "next day", "same day", or "day before" which determines how self.date is set up
        # "day before" is useful mostly for testing

        # repeatingevents
        self.repeating_events_db_path = ""
        # to enable repeatingevents, just add the path here

        # Which field defines the unique one, used by repeatingevents
        self.unique = lambda x: x
        # often it'll be something like lambda x: x['content']

        # agentmap
        self.agent_map = {}
        # keys are the tags, and the list of the object is who to send that information to
        # TODO: Implement

        # agents
        self.agents = [
            "*****@*****.**",
            "*****@*****.**",
            "*****@*****.**",
            "*****@*****.**",
            "*****@*****.**",
        ]
        # list of who to send all the data to

        # sender
        self.sender = "DragonNet Admin <*****@*****.**>"

        # formatting options
        self.start_html_tag = "<html>"
        self.end_html_tag = "</html>"
        self.header_pre_tag = "<p><b>"
        self.header_post_tag = "</b></p>"
        self.begin_section_tag = "<ul>"
        self.end_section_tag = "</ul><br />"
        self.colon = ":"
        # These values work well for self.format_for_email's default behavior

    def determine_priority(self, the_item):
        """
        Puts any user who prioritized number 1
        """
        self.verbose and print(the_item)
        user = the_item["user"]
        if user in self.priority_one_users:
            the_item["priority"] = 1  # one digit for highest priority
        else:
            the_item["priority"] = 10  # two digits for lower priority

    def reconstruct_found(self):
        """
        Takes sql information found and converts it into a usable dictionary full of information
    
        Object breaks down thus:
        self.final              = {}     # keys composed of self.tags
        self.final[key]         = []     # list of all objects that share the same tag
        self.final[key][0]      = {}     # each object is a dict
        self.final[key][0][key] = ""     # object keys composed of self.fields
        """
        pass

    def get_user_name_from_recordid(self, recordid):
        userid = self.sql("select userid from ssismdl_data_records where id = {}".format(recordid))()[0][0]
        self.verbose and print("User id: {}".format(userid))
        return self.get_user_name(userid)

    def get_user_name(self, userid):
        """
        Pulls in name info from user's profile
        """
        name_info = "firstname, lastname, username"
        name = self.sql("select {} from ssismdl_user where id = {}".format(name_info, userid))()[0]
        firstname, lastname, username = name
        email = '<a href="mailto:{username}@student.ssis-suzhou.net">email</a>'.format(**dict(username=username))
        name = "{} {} ({})".format(firstname, lastname, email)
        self.verbose and print("Name: {}".format(name))
        return name

    def tag_not_found(self, tag):
        """
        Special processing for when tag not found?
        """
        pass

    def html(self, the_html, format=True):
        if format:
            self.html_output += the_html.format(**self.__dict__)
        else:
            self.html_output += the_html

    def subject(self, the_subject):
        self.subject_output = the_subject.format(**self.__dict__)

    def derive_content(self, item):
        """
        Formats the content of the item
        Removes the tailing </p> (which the front end always puts)
        Adds user info, and recloses it
        """
        content = item["content"]
        user = item["user"]
        return self.list(user)

    def format_for_email(self):
        """
        Responsible for setting up html_output and subject_output
        Default behavior assumes:
        * Tags are headers
        * Each item in the tag is a listed item in that tag
        """
        self.html_output = ""
        self.subject_output = ""

        self.subject(self.name + "{colon} {custom_date}")

        self.html("{start_html_tag}")
        self.html("<p>The following students have signed up for today's Maths Club:</p>")

        for item in self.final:
            self.html(self.derive_content(item))  # puts in the content

        if not self.final:
            self.html("<p>No one has signed up for today</p>")

        if self.final:
            self.html("{end_section_tag}")

    def email_to_agents(self):
        """
        Follows the internal constructs and sends emails with associated tags to the agents
        """
        if self.agents:
            self.verbose and print("Sending {} to {}".format(self.name, self.agents))
            self.format_for_email()
            send_html_email(
                self.sender, self.agents, self.get_subject(), self.get_html(), domain="student.ssis-suzhou.net"
            )
        if self.agent_map:
            for agent in self.agent_map.keys():
                tags = self.agent_map[agent]
                self.format_for_email(tags)
                self.verbose and print("Sending {} to {}".format(self.name, agent))
                send_html_email(
                    self.sender, agent, self.get_subject(), self.get_html(), domain="student.ssis-suzhou.net"
                )

    def post_to_wordpress(self, blog, hour):
        """
        Simplistic way to get what could be an email onto a wordpress blog
        Requires wp-cli https://github.com/wp-cli/wp-cli
        Assuming wp installation is multisite, but works with standalone (blog parameter not needed)
        """
        replace_apostrophes = "'\\''"  # workaround for bash
        d = {
            "path": "/var/www/wordpress",  # path to wordpress installation, needed for wp command
            "title": self.get_subject(),
            #'author': ??,  get ID in table by using wp user list | grep 'peterfowles'
            "content": self.get_html().replace("'", replace_apostrophes),  # escape apostrophes for bash
            "post_status": "future",  # schedule it, don't do it immediately, 'publish' for now
            "date": self.date.strftime("%y-%m-%d {}:00:00".format(hour)),  # post on hour on target date
            "blog": blog,  # blog path for multisite
        }
        command = """/usr/bin/wp post create --path=/var/www/wordpress --post_type=post --post_title='{title}' --post_content='{content}' --post_author={author} --post_status=future --post_date='{date}' --blog={blog}""".format(
            **d
        )
        import subprocess

        print("Posting to wordpress")
        subprocess.call(command, shell=True)

    def get_subject(self, **kwargs):
        return self.subject_output.format(**kwargs)

    def get_html(self, **kwargs):
        return self.html_output.format(**kwargs)

    def list(self, s):
        """
        Can be used by formatting engine to make a list
        """
        return "<li>{}</li>".format(s)