コード例 #1
0
ファイル: gthx.py プロジェクト: tfischer4765/gthx
    def __init__(self, dbUser, dbPassword, dbDatabase, nickservPassword):
        self.db = DbAccess(dbUser, dbPassword, dbDatabase)
        # Just setting this variable sets the nickserv login password
        # (Maybe? We still do our own procesing later)
        self.password = nickservPassword

        print "Connected to MySQL server"

        self.trackedpresent = dict()
        self.gotwhoischannel = False
        self.seenQuery = re.compile(
            "\s*seen\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)[\s\?]*"
        )
        self.tellQuery = re.compile(
            "\s*tell\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)\s*(.+)"
        )
        self.factoidQuery = re.compile(
            "(.+)[?!](\s*$|\s*\|\s*([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)$)"
        )
        self.factoidSet = re.compile("(.+?)\s(is|are)(\salso)?\s(.+)")
        self.googleQuery = re.compile(
            "\s*google\s+(.*?)\s+for\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)"
        )
        self.thingMention = re.compile(
            "http(s)?:\/\/www.thingiverse.com\/thing:(\d+)", re.IGNORECASE)
        self.youtubeMention = re.compile(
            "http(s)?:\/\/(www\.youtube\.com\/watch\?v=|youtu\.be\/)([\w\-]*)(\S*)",
            re.IGNORECASE)
        self.uptimeStart = datetime.now()
        self.lurkerReplyChannel = ""
コード例 #2
0
ファイル: test.py プロジェクト: tfischer4765/gthx
    def setUp(self):
        config = ConfigParser.ConfigParser()
        results = config.read('gthx.config.local')
        if not results:
            raise SystemExit("Failed to read config file 'gthx.config.local'")
        dbUser = config.get('MYSQL', 'GTHX_MYSQL_USER')
        dbPassword = config.get('MYSQL', 'GTHX_MYSQL_PASSWORD')
        dbName = config.get('MYSQL', 'GTHX_MYSQL_DATABASE')

        self.db = DbAccess(dbUser, dbPassword, dbName)
コード例 #3
0
def target_add(w_parms):
    # target add
    # print "Adding target -- opts %s " % str(w_parms)
    sql = """INSERT INTO targets (`target-handle`, `create-datetime`, `target-description`, ipv4, ipv6, domain) VALUES (%s, NOW(), %s, %s, %s, %s)"""
    #
    values = {
        "target-handle": "",
        "target-description": "",
        "ipv4": "",
        "ipv6": "",
        "domain": ""
    }
    print "Adding target:"
    for el in w_parms:
        if el[0] == "-f":
            el0parts = el[1].partition('=')
            if el0parts[1] != "":
                values[el0parts[0]] = el0parts[2]
    print "Values: %s" % str(values)
    # connect to DB
    db = DbAccess()
    db.cursor.execute(sql,
                      (values["target-handle"], values["target-description"],
                       values["ipv4"], values["ipv6"], values["domain"]))
    db.conn.close()
コード例 #4
0
def target_list():

    db = DbAccess()
    print "# Listing targets"
    print "#"

    db.cursor.execute("SELECT * FROM targets ORDER BY `id` DESC")

    cnt = 0
    print "{0:5} | {1:14} | {2:20} | {3:20} | {4:30} | {5:15} | {6:20}". \
        format("id","target-handle", "target-description", "create-datetime", "domain", "ipv4", "ipv6")
    while True:
        row = db.cursor.fetchone()
        if row == None:
            break
        print "{0:5} | {1:14} | {2:20} | {3:20} | {4:30} | {5:15} | {6:20}". \
            format(row["id"], row["target-handle"], row["target-description"][:19],
                   str(row["create-datetime"]), row["domain"],
                   row["ipv4"], row["ipv6"])
        cnt = cnt + 1

    print "#"
    print "# Total targets %s" % (cnt)

    db.conn.close()
コード例 #5
0
def target_import(w_parms):
    filename = None
    for x in w_parms:
        if x[0] == "-f":
            filename = x[1]
            break
    print "Importing targets from file: %s" % str(filename)

    # parse xml file
    try:
        doc1 = parse(filename)
        targets = doc1.getElementsByTagName("target")
    except Exception as e:
        # print "Error parsing XML file, aborting."
        print "Exception ocurred: %s" % str(e.args)
        return

    db = DbAccess()
    for t in targets:
        # values = {"target-handle":"", "target-description":"", "ipv4":"", "ipv6":"", "domain":""}
        values = {}
        print "Inserting target found: %s - %s" % (str(
            t.getAttribute("handle")), t.childNodes[0].nodeValue)
        values["target-handle"] = t.getAttribute("handle")
        values["domain"] = t.getAttribute("domain")
        values["ipv4"] = t.getAttribute("ipv4")
        values["ipv6"] = t.getAttribute("ipv6")
        values["target-description"] = t.childNodes[0].nodeValue
        values["create-datetime"] = time.strftime("%Y-%m-%d %H:%M:%S")
        try:
            # save to db
            db.autoInsert("targets", values)
            print "Success inserting record"
        except Exception as e:
            # print "Error parsing XML file, aborting."
            print "Warning - exception ocurred while inserting record: %s" % str(
                e.args)

    return


# END target_import

################################################################################
コード例 #6
0
ファイル: test.py プロジェクト: tfischer4765/gthx
class DbAccessYoutubeRefTest(unittest.TestCase):
    def setUp(self):
        config = ConfigParser.ConfigParser()
        results = config.read('gthx.config.local')
        if not results:
            raise SystemExit("Failed to read config file 'gthx.config.local'")
        dbUser = config.get('MYSQL', 'GTHX_MYSQL_USER')
        dbPassword = config.get('MYSQL', 'GTHX_MYSQL_PASSWORD')
        dbName = config.get('MYSQL', 'GTHX_MYSQL_DATABASE')

        self.db = DbAccess(dbUser, dbPassword, dbName)

    def test_youtube_refs(self):
        testItem = "I7nVrT00ST4"
        testTitle = "Pro Riders Laughing"

        # Verify that referencing an item the first time causes the ref count to
        # be set to 1
        rows = self.db.addYoutubeRef(testItem)
        self.assertEquals(
            len(rows), 1,
            "First youtube ref returned the wrong number of rows.")
        data = rows[0]
        self.assertEquals(
            data[0], 1,
            "First youtube ref returned wrong number of references.")
        self.assertIsNone(
            data[1],
            "First youtube ref returned a title when it shouldn't have.")

        rows = self.db.addYoutubeRef(testItem)
        self.assertEquals(
            len(rows), 1,
            "First youtube ref returned the wrong number of rows.")
        data = rows[0]
        self.assertEquals(
            data[0], 2,
            "Second youtube ref returned wrong number of references.")
        self.assertIsNone(
            data[1],
            "Second youtube ref returned a title when it shouldn't have.")

        self.db.addYoutubeTitle(testItem, testTitle)

        rows = self.db.addYoutubeRef(testItem)
        self.assertEquals(
            len(rows), 1,
            "First youtube ref returned the wrong number of rows.")
        data = rows[0]
        self.assertEquals(
            data[0], 3,
            "Third youtube ref returned wrong number of references.")
        self.assertEquals(
            data[1], testTitle,
            "Third youtube ref returned the wrong title: '%s'" % data[1])

    def tearDown(self):
        self.db.deleteAllYoutubeRefs()
コード例 #7
0
ファイル: gthx.py プロジェクト: quillford/gthx
 def __init__(self):
     self.db = DbAccess()
     self.trackedpresent = dict()
     self.gotwhoischannel = False
     self.seenQuery = re.compile("\s*seen\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)[\s\?]*")
     self.tellQuery = re.compile("\s*tell\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)\s*(.+)")
     self.factoidQuery = re.compile("(.+)[?!](\s*$|\s*\|\s*([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)$)")
     self.factoidSet = re.compile("(.+?)\s(is|are)(\salso)?\s(.+)")
     self.googleQuery = re.compile("\s*google\s+(.*?)\s+for\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)")
     self.uptimeStart = datetime.datetime.now()
     self.lurkerReplyChannel = ""
コード例 #8
0
def target_del(w_parms):
    sql1 = """DELETE FROM targets WHERE id = %s"""
    sql2 = """DELETE FROM targets WHERE target-handle = %s"""
    print "Deleting targets"
    values = {}
    print "Adding target:"
    for el in w_parms:
        if el[0] == "-f":
            el0parts = el[1].partition('=')
            if el0parts[1] != "":
                values[el0parts[0]] = el0parts[2]

    rk = values.popitem()
    print "Deleting targets where: %s" % str(rk)
    db = DbAccess()
    if rk[0] == "id":
        db.cursor.execute(sql1, (rk[1]))
    if rk[1] == "target-handle":
        db.cursor.execute(sql2, (rk[1]))
    print "Affected rows %s" % (db.cursor.rowcount)
    db.conn.close()
コード例 #9
0
def target_update(w_parms):
    # target add
    # print "Adding target -- opts %s " % str(w_parms)
    sql = """UPDATE targets SET """
    #
    # values = {"target-description":"", "ipv4":"", "ipv6":"", "domain":""}
    values = {}
    print "Adding target:"
    for el in w_parms:
        if el[0] == "-f":
            el0parts = el[1].partition('=')
            if el0parts[1] != "":
                values[el0parts[0]] = el0parts[2]
                sql = sql + "`{0}` = %({1})s, ".format(el0parts[0],
                                                       el0parts[0])
    sql = sql[0:len(sql) - 2] + " WHERE `target-handle`=%(target-handle)s"
    print "Values: %s" % str(values)
    # print "Sql: %s" % (sql)
    # connect to DB
    db = DbAccess()
    db.cursor.execute(sql, values)
    db.conn.close()
コード例 #10
0
ファイル: fetch_last.py プロジェクト: deaps/Python-Scripts
from RESTClient import RESTClient, Services
from DbAccess import DbAccess

# Get last/todays rates
client = RESTClient(Services.TODAYS_RATES)
data = client.call_service()
db = DbAccess()

# Get item
item = data.find('nsp:Cube', client.namespaces)

# Insert entry in DB
today = item.__getitem__(0).attrib['time']
today_id = db.insert_entry(today)

if today_id == -1:
    today_id = db.entry_get_id(today)[0]

# Insert rates in DB
for rate in item.find('nsp:Cube', client.namespaces):
    db.insert_exchangeRate(
        today_id, rate.attrib['currency'], 
        rate.attrib['rate']
    )
コード例 #11
0
from RESTClient import RESTClient, Services
from DbAccess import DbAccess

# Get last/todays rates
client = RESTClient(Services.ALL_RATES)
data = client.call_service()
db = DbAccess()

list = data.find('nsp:Cube', client.namespaces)

# Insert entries in DB
for entry in list:
    entry_date = entry.attrib['time']
    entry_date_id = db.insert_entry(entry_date)

    if entry_date_id == -1:
        entry_date_id = db.entry_get_id(entry_date)[0]

    # Insert rates in DB
    for rate in entry:
        db.insert_exchangeRate(entry_date_id, rate.attrib['currency'],
                               rate.attrib['rate'])
コード例 #12
0
ファイル: fetch_last.py プロジェクト: deaps/Python-Scripts
from RESTClient import RESTClient, Services
from DbAccess import DbAccess

# Get last/todays rates
client = RESTClient(Services.TODAYS_RATES)
data = client.call_service()
db = DbAccess()

# Get item
item = data.find('nsp:Cube', client.namespaces)

# Insert entry in DB
today = item.__getitem__(0).attrib['time']
today_id = db.insert_entry(today)

if today_id == -1:
    today_id = db.entry_get_id(today)[0]

# Insert rates in DB
for rate in item.find('nsp:Cube', client.namespaces):
    db.insert_exchangeRate(today_id, rate.attrib['currency'],
                           rate.attrib['rate'])
コード例 #13
0
ファイル: gthx.py プロジェクト: tfischer4765/gthx
class Gthx(irc.IRCClient):
    """An IRC bot for #reprap."""

    restring = ""

    def __init__(self, dbUser, dbPassword, dbDatabase, nickservPassword):
        self.db = DbAccess(dbUser, dbPassword, dbDatabase)
        # Just setting this variable sets the nickserv login password
        # (Maybe? We still do our own procesing later)
        self.password = nickservPassword

        print "Connected to MySQL server"

        self.trackedpresent = dict()
        self.gotwhoischannel = False
        self.seenQuery = re.compile(
            "\s*seen\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)[\s\?]*"
        )
        self.tellQuery = re.compile(
            "\s*tell\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)\s*(.+)"
        )
        self.factoidQuery = re.compile(
            "(.+)[?!](\s*$|\s*\|\s*([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)$)"
        )
        self.factoidSet = re.compile("(.+?)\s(is|are)(\salso)?\s(.+)")
        self.googleQuery = re.compile(
            "\s*google\s+(.*?)\s+for\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)"
        )
        self.thingMention = re.compile(
            "http(s)?:\/\/www.thingiverse.com\/thing:(\d+)", re.IGNORECASE)
        self.youtubeMention = re.compile(
            "http(s)?:\/\/(www\.youtube\.com\/watch\?v=|youtu\.be\/)([\w\-]*)(\S*)",
            re.IGNORECASE)
        self.uptimeStart = datetime.now()
        self.lurkerReplyChannel = ""

    def connectionMade(self):
        if self.password:
            self.log("IRC Connection made -- sending CAP REQ")
            self.sendLine('CAP REQ :sasl')
        else:
            self.log("IRC Connection made - no nickserv password")
        irc.IRCClient.connectionMade(self)

    def irc_CAP(self, prefix, params):
        self.log("Got irc_CAP")
        if params[1] != 'ACK' or params[2].split() != ['sasl']:
            print 'sasl not available'
            self.quit('')
        sasl = ('{0}\0{0}\0{1}'.format(
            self.nickname, self.password)).encode('base64').strip()
        self.sendLine('AUTHENTICATE PLAIN')
        self.sendLine('AUTHENTICATE ' + sasl)

    def irc_903(self, prefix, params):
        self.log("Got SASL connection successful.")
        self.sendLine('CAP END')

    def irc_904(self, prefix, params):
        print 'sasl auth failed', params
        self.quit('')

    def connectionLost(self, reason):
        irc.IRCClient.connectionLost(self, reason)
        self.log("[disconnected at %s]" %
                 time.asctime(time.localtime(time.time())))
        self.emailClient.send(
            "%s disconnected" % self.nickname,
            "%s is disconnected from the server.\n\n%s" %
            (self.nickname, reason))

    def log(self, message):
        """Write a message to the screen."""
        timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
        print '%s %s' % (timestamp, message)

    # callbacks for events

    def signedOn(self):
        """Called when bot has succesfully signed on to server."""
        self.log("Signed on to the IRC server")
        self.channelList = [
            channel for channel in self.factory.channels.split(',')
        ]
        for channelm in self.channelList:
            self.log("Joining channel %s" % channelm)
            self.join(channelm)
            if (trackednick == None):
                self.trackedpresent[channelm] = False

        self.gotwhoischannel = False
        # kthx uses: "\s*(${names})[:;,-]?\s*" to match nicks
        if (trackednick):
            self.matchNick = "(%s|%s)(:|;|,|-|\s)+(.+)" % (self.nickname,
                                                           trackednick)
            print "Querying WHOIS %s at startup" % trackednick
            self.whois(trackednick)
        else:
            self.matchNick = "(%s)(:|;|,|-|\s)+(.+)" % (self.nickname)
            print "Running in standalone mode."

    def joined(self, channel):
        """Called when the bot joins the channel."""
        self.log("[I have joined %s as '%s']" % (channel, self.nickname))
        message = "I have joined channel %s as '%s'\n" % (channel,
                                                          self.nickname)
        self.emailClient.threadsend("%s connected" % self.nickname, message)

    def userJoined(self, user, channel):
        """
        Called when I see another user joining a channel.
        """
        print "%s joined channel %s" % (user, channel)
        # TODO: Change this to verify the IP address before setting it
        if trackednick and (user
                            == trackednick) and (self.trackedpresent[channel]
                                                 == False):
            self.trackedpresent[channel] = True
            print "%s is here!" % trackednick
            self.emailClient.threadsend(
                "%s status" % self.nickname,
                "%s has joined channel %s" % (user, channel))

    def userLeft(self, user, channel):
        """
        Called when I see another user leaving a channel.
        """
        print "%s left channel %s" % (user, channel)
        if trackednick and (user
                            == trackednick) and (self.trackedpresent[channel]):
            self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend(
                "%s status" % self.nickname,
                "%s has left channel %s" % (user, channel))

    def userQuit(self, user, quitMessage):
        """
        Called when I see another user disconnect from the network.
        """
        safeQuitMessage = quitMessage.decode("utf-8")
        print "%s disconnected : %s" % (user, safeQuitMessage)
        if trackednick and (user == trackednick):
            for channel in self.channelList:
                self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend(
                "%s status" % self.nickname,
                "%s has quit: %s" % (user, quitMessage))

    def userKicked(self, kickee, channel, kicker, message):
        """
        Called when I observe someone else being kicked from a channel.
        """
        print "In %s, %s kicked %s : %s" % (channel, kicker, kickee, message)
        if trackednick and (kickee
                            == trackednick) and (self.trackedpresent[channel]):
            self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend(
                "%s status" % self.nickname,
                "%s has been kicked from %s by %s: %s" %
                (kickee, channel, kicker, message))

    def userRenamed(self, oldname, newname):
        """
        A user changed their name from oldname to newname.
        """
        print "%s renamed to %s" % (oldname, newname)
        if (trackednick == None):
            return
        if oldname == trackednick:
            for channel in self.channelList:
                self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend(
                "%s status" % self.nickname,
                "%s has been renamed to %s" % (oldname, newname))
        if newname == trackednick:
            self.whois(trackednick)
            print "%s is here!" % trackednick
            self.emailClient.threadsend(
                "%s status" % self.nickname,
                "%s has been renamed to %s--checking WHOIS" %
                (oldname, newname))

    def irc_unknown(self, prefix, command, params):
        print "Unknown command '%s' '%s' '%s'" % (prefix, command, params)
        if (command == 'RPL_NAMREPLY'):
            if (self.lurkerReplyChannel == ""):
                return
            users = params[3].split()
            for user in users:
                self.channelCount = self.channelCount + 1
                rows = self.db.seen(user)
                if len(rows) == 0:
                    self.lurkerCount = self.lurkerCount + 1
        elif (command == 'RPL_ENDOFNAMES'):
            if (self.lurkerReplyChannel == ""):
                return
            print "Got RPL_ENDOFNAMES"
            self.msg(
                self.lurkerReplyChannel,
                "%d of the %d users in %s right now have never said anything."
                % (self.lurkerCount, self.channelCount, params[1]))
            self.lurkerReplyChannel = ""

    def irc_RPL_WHOISCHANNELS(self, prefix, params):
        """This method is called when the client recieves a reply for whois.
        params[0]: requestor
        params[1]: nick requested
        params[2]: list of channels in common
        """
        print "Got WHOISCHANNELS with prefix '%s' and params '%s'" % (prefix,
                                                                      params)
        print "%s is in channels %s" % (params[1], params[2])
        self.gotwhoischannel = True
        trackedchannels = params[2].translate(None, '@').split(" ")
        for channel in self.channelList:
            if channel in trackedchannels:
                self.trackedpresent[channel] = True
                print "%s is in %s!!" % (params[1], channel)
                self.emailClient.threadsend(
                    "%s status" % self.nickname,
                    "%s is in channel %s" % (params[1], params[2]))
            else:
                self.trackedpresent[channel] = False
                print "%s is NOT in %s!!" % (params[1], channel)

    def irc_RPL_WHOISUSER(self, prefix, params):
        print "Got WHOISUSER with prefix '%s' and params '%s'" % (prefix,
                                                                  params)

    def irc_RPL_WHOISSERVER(self, prefix, params):
        print "Got WHOISSERVER with prefix '%s' and params '%s'" % (prefix,
                                                                    params)

    def irc_RPL_WHOISOPERATOR(self, prefix, params):
        print "Got WHOISOPERATOR with prefix '%s' and params '%s'" % (prefix,
                                                                      params)

    def irc_RPL_WHOISIDLE(self, prefix, params):
        print "Got WHOISIDLE with prefix '%s' and params '%s'" % (prefix,
                                                                  params)

    def irc_RPL_ENDOFWHOIS(self, prefix, params):
        print "Got ENDOFWHOIS with prefix '%s' and params '%s'" % (prefix,
                                                                   params)
        if not self.gotwhoischannel:
            if (trackednick != None):
                print "No response from %s. Must not be present." % trackednick
                for channel in self.channelList:
                    self.trackedpresent[channel] = False
                    self.emailClient.threadsend(
                        "%s status" % self.nickname,
                        "%s is not in channel %s" % (trackednick, channel))

    def getFactoidString(self, query):
        answer = self.db.getFactoid(query)
        if answer:
            for i, factoid in enumerate(answer):
                if i == 0:
                    if factoid[3].startswith(
                            "<reply>") or factoid[3].startswith("<action>"):
                        fstring = factoid[3]
                        break
                    else:
                        fstring = query
                fstring += "%s" % " are " if factoid[2] else " is "
                if i > 0:
                    fstring += "also "
                fstring += factoid[3]
                if i < len(answer) - 1:
                    fstring += " and"
            return fstring
        else:
            return None

    def moodToString(self, mood):
        if mood < -100:
            return "suicidal!"
        if mood < -50:
            return "really depressed."
        if mood < -10:
            return "depressed."
        if mood < 0:
            return "kinda bummed."
        if mood == 0:
            return "meh, okay I guess."
        if mood < 10:
            return "alright."
        if mood < 50:
            return "pretty good."
        return "great, Great, GREAT!!"

    def privmsg(self, user, channel, msg):
        """Called when the bot receives a message, both public and private."""
        user = user.split('!', 1)[0]

        # By default, don't reply to anything
        canReply = False
        private = False
        replyChannel = channel
        parseMsg = msg
        directAddress = False

        # Debug print ALL messages
        #print "Message from '%s' on '%s': '%s'" % (user, channel, msg)

        # Check to see if they're sending me a private message
        if channel == self.nickname:
            canReply = True
            private = True
            replyChannel = user
            self.log("Private message from %s: %s" % (user, msg))
            if str.lower(user) == "nickserv":
                self.log("Nickserv says: %s" % msg)
            if parseMsg.startswith("whois "):
                whoisnick = parseMsg.split(" ", 1)[1]
                print "Doing a whois '%s'" % whoisnick
                self.whois(whoisnick)

        # Update the seen database, but only if it's not a private message
        if channel in self.channelList and not private:
            self.db.updateSeen(user, channel, msg)

        # If kthx said something, mark him as here and ignore everything he says
        if user == trackednick and not private:
            if (self.trackedpresent[channel] == False):
                self.trackedpresent[channel] = True
                self.emailClient.threadsend(
                    "%s status" % self.nickname,
                    "%s spoke in %s unexpectedly and got marked as present: %s"
                    % (user, channel, msg))
            return

        # If kthx is gone, then we can always reply
        if not private and not self.trackedpresent[channel]:
            canReply = True

        # Check to see if we have a tell waiting for this user
        tells = self.db.getTell(user)
        if tells:
            for message in tells:
                print "Found tell for '%s' from '%s'" % (user,
                                                         message[Tell.author])
                author = message[Tell.author]
                timestring = timesincestring(message[Tell.timestamp])
                text = message[Tell.message]
                inTracked = message[Tell.inTracked]
                # We have 3 cases:
                # 1) kthx was around when this tell happened and is still around now.
                #    In this case, we assume kthx will relay the message and just delete it
                # 2) kthx was around when this tell happened and is not here now.
                #    In this case, we want to send the message and mention that kthx may repeat it
                # 3) kthx was not around when this tell happened and may or may not be here now
                #    Whether or not kthx is now here, we need to say the message
                # 4) gthx was specifically addressed for this tell
                #    Whether or not kthx is now here, we need to say the message
                #
                # If we can't reply, it means that kthx is present. In that
                # case, the tell has already been erased, so in both cases,
                # we're good.
                if canReply or not inTracked:
                    if inTracked:
                        self.msg(
                            replyChannel,
                            "%s: %s ago <%s> tell %s %s (%s may repeat this)" %
                            (user, timestring, author, user, text,
                             trackednick))
                    else:
                        self.msg(
                            replyChannel, "%s: %s ago <%s> tell %s %s" %
                            (user, timestring, author, user, text))

        # Check for specifically addressed messages
        m = re.match(self.matchNick, parseMsg)
        if m:
            print "Found message addressed to '%s'. My nick is '%s'." % (
                m.group(1), self.nickname)
            parseMsg = m.group(3)
            # Mark it as a direct address so we can look for a factoid
            directAddress = True
            # If it's addressed directly to me, we can reply
            if m.group(1) == self.nickname:
                canReply = True

        # Check for status query
        if canReply and parseMsg == "status?":
            if (trackednick):
                if (private):
                    reply = "%s: OK; Up for %s; " % (
                        VERSION, timesincestring(self.uptimeStart))
                    for channel in self.channelList:
                        reply += "%s %s; " % (channel, "PRESENT"
                                              if self.trackedpresent[channel]
                                              else "GONE")
                else:
                    reply = "%s: OK; Up for %s; %s is %s" % (
                        VERSION, timesincestring(
                            self.uptimeStart), trackednick,
                        "PRESENT" if self.trackedpresent[channel] else "GONE")
            else:
                reply = "%s: OK; Up for %s; standalone mode" % (
                    VERSION, timesincestring(self.uptimeStart))
            mood = self.db.mood()
            reply += " mood: %s" % self.moodToString(mood)
            self.msg(replyChannel, reply)
            return

        # Check for lurker query
        if canReply and parseMsg == "lurkers?":
            self.msg(replyChannel, "Looking for lurkers...")
            self.lurkerReplyChannel = replyChannel
            self.lurkerCount = 0
            self.channelCount = 0
            print "Sending request 'NAMES %s'" % channel
            self.sendLine("NAMES %s" % channel)
            return

        # Check for tell query
        m = self.tellQuery.match(parseMsg)
        if m and directAddress:
            print "Got tell from '%s' for  '%s' message '%s'." % (
                user, m.group(1), m.group(2))
            # The is in the tracked bot if the tracked bot is present and it was not a message
            # specifically directed to us. This is a little tricky since the only way to know
            # that a message was specifically directed to us is to see if it was a direct address
            # and we can reply
            success = self.db.addTell(
                user, m.group(1), m.group(2), not (directAddress and canReply)
                and self.trackedpresent[channel])
            if success and canReply:
                self.msg(
                    replyChannel, "%s: I'll pass that on when %s is around." %
                    (user, m.group(1)))
            return

        # Check for seen query
        if canReply:
            m = self.seenQuery.match(parseMsg)
            if m:
                queryname = m.group(1)
                print "%s asked about '%s'" % (user, queryname)
                rows = self.db.seen(queryname)
                if len(rows) == 0:
                    reply = "Sorry, I haven't seen %s." % queryname
                    self.msg(replyChannel, reply)
                for i, row in enumerate(rows):
                    reply = "%s was last seen in %s %s ago saying '%s'." % (
                        row[Seen.name], row[Seen.channel],
                        timesincestring(
                            row[Seen.timestamp]), row[Seen.message])
                    self.msg(replyChannel, reply)
                    if i >= 2:
                        # Don't reply more than 3 times to a seen query
                        break
                return

        # Check for google query
        if directAddress:
            if canReply:
                m = self.googleQuery.match(parseMsg)
                if m:
                    queryname = urllib.quote_plus(m.group(1))
                    foruser = m.group(2)
                    print "%s asked to google '%s' for %s" % (user, queryname,
                                                              foruser)
                    reply = "%s: http://lmgtfy.com/?q=%s" % (foruser,
                                                             queryname)
                    self.msg(replyChannel, reply)
                    return

        # Check for setting a factoid
        factoid = None
        if directAddress:
            factoid = self.factoidSet.match(parseMsg)
            if factoid:
                invalidwords = re.match(
                    '(here|how|it|something|that|this|what|when|where|which|who|why|you)',
                    factoid.group(1), re.IGNORECASE)
                if not invalidwords:
                    safeFactoid = factoid.group(1).decode("utf-8")
                    print "%s tried to set factoid '%s'." % (user, safeFactoid)
                    success = self.db.addFactoid(
                        user, factoid.group(1),
                        True if factoid.group(2) == 'are' else False,
                        factoid.group(4),
                        True if not factoid.group(3) else False)
                    if canReply:
                        if success:
                            self.msg(replyChannel, "%s: Okay." % user)
                        else:
                            self.msg(
                                replyChannel,
                                "I'm sorry, %s. I'm afraid I can't do that." %
                                user)

        # Check for getting a factoid
        if canReply:
            f = self.factoidQuery.match(parseMsg)
            if f:
                safeFactoid = f.group(1).decode("utf-8")
                print "factoid query from %s:%s for '%s'" % (user, channel,
                                                             safeFactoid)
                answer = self.getFactoidString(f.group(1))
                if answer:
                    # Replace !who and !channel in the reply
                    answer = re.sub("!who", user, answer)
                    answer = re.sub("!channel", channel, answer)

                    if answer.startswith("<reply>"):
                        answer = answer[7:]

                    if answer.startswith("<action>"):
                        self.describe(replyChannel, answer[8:])
                    else:
                        if (f.group(3)):
                            answer = "%s, %s" % (f.group(3), answer)
                        self.msg(replyChannel, answer)

        # Check for info request
        if canReply and parseMsg.startswith("info "):
            query = parseMsg[5:]
            if query[-1:] == "?":
                query = query[:-1]
            safeFactoid = query.decode("utf-8")
            print "info request for '%s' ReplyChannel is '%s'" % (safeFactoid,
                                                                  replyChannel)
            refcount = 0
            answer = self.db.infoFactoid(query)
            if answer:
                count = answer[0][6]
                if not count:
                    count = "0"
                print "Factoid '%s' has been referenced %s times" % (
                    safeFactoid, count)
                self.msg(
                    replyChannel, "Factoid '%s' has been referenced %s times" %
                    (query, count))
                for factoid in answer:
                    user = factoid[3]
                    value = factoid[2]
                    if not user:
                        user = "******"
                    if value:
                        print "At %s, %s set to: %s" % (factoid[4], user,
                                                        value)
                        self.msg(
                            replyChannel,
                            "At %s, %s set to: %s" % (factoid[4], user, value))
                    else:
                        print "At %s, %s deleted this item" % (factoid[4],
                                                               user)
                        self.msg(
                            replyChannel,
                            "At %s, %s deleted this item" % (factoid[4], user))
            else:
                print "No info for factoid '%s'" % safeFactoid
                self.msg(replyChannel,
                         "Sorry, I couldn't find an entry for %s" % query)

        # Check for forget request
        if directAddress and parseMsg.startswith("forget "):
            query = parseMsg[7:]
            print "forget request for '%s'" % query
            forgotten = self.db.forgetFactoid(query, user)
            if canReply:
                if forgotten:
                    self.msg(replyChannel,
                             "%s: I've forgotten about %s" % (user, query))
                else:
                    self.msg(
                        replyChannel,
                        "%s: Okay, but %s didn't exist anyway" % (user, query))

        # Check for thingiverse mention
        if canReply:
            match = self.thingMention.search(parseMsg)
            if match:
                thingId = int(match.group(2))
                print "Match for thingiverse query item %s" % thingId
                rows = self.db.addThingiverseRef(thingId)
                refs = int(rows[0][0])
                title = rows[0][1]
                if title is None:
                    print "Attemping to get title for thingiverse ID %s" % thingId
                    agent = Agent(reactor)
                    titleQuery = agent.request(
                        'GET',
                        'https://www.thingiverse.com/thing:%s' % thingId,
                        Headers({'User-Agent': ['gthx IRC bot']}), None)

                    def titleResponse(title):
                        if title:
                            title = unescape(title)
                            self.db.addThingiverseTitle(thingId, title)
                            print "The title for thing %s is: %s " % (thingId,
                                                                      title)
                            reply = 'https://www.thingiverse.com/thing:%s => %s => %s IRC mentions' % (
                                thingId, title, refs)
                            self.msg(replyChannel, reply)
                        else:
                            print "No title found for thing %s" % (thingId)
                            reply = 'https://www.thingiverse.com/thing:%s => ???? => %s IRC mentions' % (
                                thingId, refs)
                            self.msg(replyChannel, reply)

                    def queryResponse(response):
                        if response.code == 200:
                            finished = Deferred()
                            finished.addCallback(titleResponse)
                            response.deliverBody(TitleParser(finished))
                            return finished
                        print "Got error response from thingiverse query: %s" % (
                            response)
                        titleResponse(None)
                        return None

                    titleQuery.addCallback(queryResponse)
                else:
                    print "Already have a title for thing %s: %s" % (thingId,
                                                                     title)
                    reply = 'https://www.thingiverse.com/thing:%s => %s => %s IRC mentions' % (
                        thingId, title, refs)
                    self.msg(replyChannel, reply)

        # Check for youtube mention
        if canReply:
            match = self.youtubeMention.search(parseMsg)
            if match:
                youtubeId = match.group(3)
                fullLink = match.group(0)
                print "Match for youtube query item %s" % youtubeId
                rows = self.db.addYoutubeRef(youtubeId)
                refs = int(rows[0][0])
                title = rows[0][1]
                if title is None:
                    print "Attemping to get title for youtubeId %s" % youtubeId
                    agent = Agent(reactor)
                    titleQuery = agent.request(
                        'GET',
                        'https://www.youtube.com/watch?v=%s' % youtubeId,
                        Headers({'User-Agent': ['gthx IRC bot']}), None)

                    def titleResponse(title):
                        if title:
                            title = unescape(title)
                            self.db.addYoutubeTitle(youtubeId, title)
                            print "The title for video %s is: %s " % (
                                youtubeId, title)
                            reply = '%s => %s => %s IRC mentions' % (
                                fullLink, title, refs)
                            print "Reply is: %s" % reply
                            self.msg(replyChannel, reply)
                            print "Message sent."
                        else:
                            print "No title found for youtube video %s" % (
                                youtubeId)
                            reply = '%s => ???? => %s IRC mentions' % (
                                fullLink, refs)
                            self.msg(replyChannel, reply)

                    def queryResponse(response):
                        if response.code == 200:
                            finished = Deferred()
                            finished.addCallback(titleResponse)
                            response.deliverBody(TitleParser(finished))
                            return finished
                        print "Got error response from youtube query: %s:%s" % (
                            response.code, response.phrase)
                        pprint(list(response.headers.getAllRawHeaders()))
                        titleResponse(None)
                        return None

                    titleQuery.addCallback(queryResponse)
                else:
                    print "Already have a title for item %s: %s" % (youtubeId,
                                                                    title)
                    reply = '%s => %s => %s IRC mentions' % (fullLink, title,
                                                             refs)
                    self.msg(replyChannel, reply)

    def action(self, sender, channel, message):
        m = re.match(
            "([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)",
            sender)
        if m:
            sender = m.group(1)
            print "* %s %s" % (sender, message)
            self.db.updateSeen(sender, channel, "* %s %s" % (sender, message))
コード例 #14
0
ファイル: test.py プロジェクト: tfischer4765/gthx
class DbAccessTellTest(unittest.TestCase):
    missinguser = "******"

    def setUp(self):
        config = ConfigParser.ConfigParser()
        results = config.read('gthx.config.local')
        if not results:
            raise SystemExit("Failed to read config file 'gthx.config.local'")
        dbUser = config.get('MYSQL', 'GTHX_MYSQL_USER')
        dbPassword = config.get('MYSQL', 'GTHX_MYSQL_PASSWORD')
        dbName = config.get('MYSQL', 'GTHX_MYSQL_DATABASE')

        self.db = DbAccess(dbUser, dbPassword, dbName)

    def test_user_with_no_tells(self):
        user = "******"

        data = self.db.getTell(user)
        self.assertEquals(
            len(data), 0,
            "Wrong number of tells returned for a user who doesn't have any waiting"
        )

    def test_get_with_no_tells(self):
        data = self.db.getTell(DbAccessTellTest.missinguser)
        self.assertFalse(
            data, "Got a valid return for a user with no tells waiting")

    def test_add_and_get_and_verify_tell(self):
        teller = "talker"
        receiver = "randomuser"
        message = "Ping me when you can"
        kthxKnows = False

        success = self.db.addTell(teller, receiver, message, kthxKnows)
        self.assertTrue(success, "Failed to add a tell to a user")

        data = self.db.getTell(receiver)
        self.assertTrue(data, "Got no tells for a user with tells waiting")
        self.assertEquals(len(data), 1, "Got wrong number of tells for a user")

        tell = data[0]
        self.assertEquals(tell[1], teller, "Got wrong author for a tell")
        self.assertEquals(tell[2], receiver, "Got wrong recipient for a tell")
        self.assertEquals(tell[4], message, "Got wrong message for a tell")
        self.assertEquals(tell[5], kthxKnows, "Got wrong inTracked for a tell")

        delta = datetime.now() - tell[3]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a tell date set: delta is %d" %
            delta.total_seconds())

        # Now get again for the same user to make sure they've been cleared
        data = self.db.getTell(receiver)
        self.assertFalse(data, "Got tells for a user with none waiting")

    def test_add_and_get_and_verify_unicode_tell(self):
        teller = "😇talker"
        receiver = "random🚕user"
        message = "☎️ me when you can"
        kthxKnows = True

        success = self.db.addTell(teller, receiver, message, kthxKnows)
        self.assertTrue(success, "Failed to add a tell to a user")

        data = self.db.getTell(receiver)
        self.assertTrue(data, "Got no tells for a user with tells waiting")
        self.assertEquals(len(data), 1, "Got wrong number of tells for a user")

        tell = data[0]
        self.assertEquals(tell[1], teller, "Got wrong author for a tell")
        self.assertEquals(tell[2], receiver, "Got wrong recipient for a tell")
        self.assertEquals(tell[4], message, "Got wrong message for a tell")
        self.assertEquals(tell[5], kthxKnows, "Got wrong inTracked for a tell")

        delta = datetime.now() - tell[3]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a tell date set: delta is %d" %
            delta.total_seconds())

        # Now get again for the same user to make sure they've been cleared
        data = self.db.getTell(receiver)
        self.assertFalse(data, "Got tells for a user with none waiting")

    def test_multiple_tells(self):
        teller = "talker"
        teller2 = "another_talker"
        teller3 = "schminkebob"
        receiver = "randomuser"
        message = "Ping me when you can"
        message2 = "Can you give me a ring please?"
        message3 = "WAKE UP!!"
        kthxKnows = False
        kthxKnows2 = True
        kthxKnows3 = False

        success = self.db.addTell(teller, receiver, message, kthxKnows)
        self.assertTrue(success, "Failed to add a tell to a user")
        success = self.db.addTell(teller2, receiver, message2, kthxKnows2)
        self.assertTrue(success, "Failed to add a second tell to a user")
        success = self.db.addTell(teller3, receiver, message3, kthxKnows3)
        self.assertTrue(success, "Failed to add a third tell to a user")

        data = self.db.getTell(receiver)
        self.assertTrue(data, "Got no tells for a user with tells waiting")
        self.assertEquals(len(data), 3, "Got wrong number of tells for a user")

        tell = data[0]
        self.assertEquals(tell[1], teller, "Got wrong author for a tell")
        self.assertEquals(tell[2], receiver, "Got wrong recipient for a tell")
        self.assertEquals(tell[4], message, "Got wrong message for a tell")
        self.assertEquals(tell[5], kthxKnows, "Got wrong inTracked for a tell")

        delta = datetime.now() - tell[3]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a tell date set: delta is %d" %
            delta.total_seconds())

        tell = data[1]
        self.assertEquals(tell[1], teller2, "Got wrong author for a tell")
        self.assertEquals(tell[2], receiver, "Got wrong recipient for a tell")
        self.assertEquals(tell[4], message2, "Got wrong message for a tell")
        self.assertEquals(tell[5], kthxKnows2,
                          "Got wrong inTracked for a tell")

        delta = datetime.now() - tell[3]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a tell date set: delta is %d" %
            delta.total_seconds())

        tell = data[2]
        self.assertEquals(tell[1], teller3, "Got wrong author for a tell")
        self.assertEquals(tell[2], receiver, "Got wrong recipient for a tell")
        self.assertEquals(tell[4], message3, "Got wrong message for a tell")
        self.assertEquals(tell[5], kthxKnows3,
                          "Got wrong inTracked for a tell")

        delta = datetime.now() - tell[3]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a tell date set: delta is %d" %
            delta.total_seconds())

        # Now get again for the same user to make sure they've been cleared
        data = self.db.getTell(receiver)
        self.assertFalse(data, "Got tells for a user with none waiting")

    def tearDown(self):
        self.db.deleteAllTells()
コード例 #15
0
ファイル: test.py プロジェクト: tfischer4765/gthx
class DbAccessFactoidTest(unittest.TestCase):
    def setUp(self):
        config = ConfigParser.ConfigParser()
        results = config.read('gthx.config.local')
        if not results:
            raise SystemExit("Failed to read config file 'gthx.config.local'")
        dbUser = config.get('MYSQL', 'GTHX_MYSQL_USER')
        dbPassword = config.get('MYSQL', 'GTHX_MYSQL_PASSWORD')
        dbName = config.get('MYSQL', 'GTHX_MYSQL_DATABASE')

        self.db = DbAccess(dbUser, dbPassword, dbName)

    def test_get_missing_factoid(self):
        missingFactoid = "missingfactoid"
        data = self.db.getFactoid(missingFactoid)
        self.assertFalse(
            data, "Got a valid return from a factoid that shouldn't exist")

    def test_add_factoid(self):
        user = "******"
        item = "somefactoid"
        isAre = False
        definition = "a good thing to talk about"
        overwrite = False

        success = self.db.addFactoid(user, item, isAre, definition, overwrite)

        self.assertTrue(success, "Failed to add a new factoid")

        data = self.db.getFactoid(item)
        self.assertEqual(
            len(data), 1,
            "Returned wrong number of results for a factoid: %d" %
            (len(data), ))

        factoid = data[0]

        # TODO: I really need to make this data access more intuitive to use
        self.assertEquals(
            factoid[1], item,
            "Factoid failed to retrieve the item field correctly")
        self.assertEquals(
            factoid[2], isAre,
            "Factoid failed to retrieve the is/are field correctly")
        self.assertEquals(
            factoid[3], definition,
            "Factoid failed to retrieve the defintion correctly")
        self.assertEquals(factoid[4], user,
                          "Factoid failed to retrieve the user correctly")

        delta = datetime.now() - factoid[5]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a factoid date set: delta is %d" %
            delta.total_seconds())

        self.assertFalse(
            factoid[6], "Factoid failed to retrieve the locked flag correctly")

    def test_add_unicode_factoid(self):
        user = "******"
        item = "some🐶factoid"
        isAre = False
        definition = "a good thing to eat 🍕🌮🍜🎂🍧"
        overwrite = False

        success = self.db.addFactoid(user, item, isAre, definition, overwrite)

        self.assertTrue(success, "Failed to add a new factoid")

        data = self.db.getFactoid(item)
        self.assertEqual(
            len(data), 1,
            "Returned wrong number of results for a factoid: %d" %
            (len(data), ))

        factoid = data[0]

        self.assertEquals(
            factoid[1], item,
            "Factoid failed to retrieve the item field correctly")
        self.assertEquals(
            factoid[2], isAre,
            "Factoid failed to retrieve the is/are field correctly")
        self.assertEquals(
            factoid[3], definition,
            "Factoid failed to retrieve the defintion correctly")
        self.assertEquals(factoid[4], user,
                          "Factoid failed to retrieve the user correctly")

        delta = datetime.now() - factoid[5]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a factoid date set: delta is %d" %
            delta.total_seconds())

        self.assertFalse(
            factoid[6], "Factoid failed to retrieve the locked flag correctly")

    def test_add_to_factoid_then_replace(self):
        user = "******"
        user2 = "someotheruser"
        user3 = "someguy"
        item = "somefactoidToReplace"
        isAre = True
        definition = "a good thing to talk about"
        definition2 = "something people write"
        replacement = "stupid facts"

        success = self.db.addFactoid(user, item, isAre, definition, False)
        self.assertTrue(success, "Failed to add a new factoid")

        success = self.db.addFactoid(user2, item, isAre, definition2, False)
        self.assertTrue(success, "Failed to add a new factoid")

        data = self.db.getFactoid(item)
        self.assertEqual(
            len(data), 2,
            "Returned wrong number of results for a multi-factoid: %d" %
            (len(data), ))

        factoid = data[0]

        self.assertEquals(
            factoid[1], item,
            "Factoid failed to retrieve the item field correctly")
        self.assertEquals(
            factoid[2], isAre,
            "Factoid failed to retrieve the is/are field correctly")
        self.assertEquals(
            factoid[3], definition,
            "Factoid failed to retrieve the defintion correctly")
        self.assertEquals(factoid[4], user,
                          "Factoid failed to retrieve the user correctly")

        delta = datetime.now() - factoid[5]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a factoid date set: delta is %d" %
            delta.total_seconds())

        self.assertFalse(
            factoid[6], "Factoid failed to retrieve the locked flag correctly")

        factoid = data[1]

        self.assertEquals(
            factoid[1], item,
            "Factoid failed to retrieve the item field correctly")
        self.assertEquals(
            factoid[2], isAre,
            "Factoid failed to retrieve the is/are field correctly")
        self.assertEquals(
            factoid[3], definition2,
            "Factoid failed to retrieve the defintion correctly")
        self.assertEquals(factoid[4], user2,
                          "Factoid failed to retrieve the user correctly")

        delta = datetime.now() - factoid[5]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a factoid date set: delta is %d" %
            delta.total_seconds())

        self.assertFalse(
            factoid[6], "Factoid failed to retrieve the locked flag correctly")

        # Now overwrite these definitions with a totally new one
        success = self.db.addFactoid(user3, item, isAre, replacement, True)
        self.assertTrue(success, "Failed to replace a new factoid")

        data = self.db.getFactoid(item)
        self.assertEqual(
            len(data), 1,
            "Returned wrong number of results for a replacedfactoid: %d" %
            (len(data), ))

        factoid = data[0]

        self.assertEquals(
            factoid[1], item,
            "Factoid failed to retrieve the item field correctly")
        self.assertEquals(
            factoid[2], isAre,
            "Factoid failed to retrieve the is/are field correctly")
        self.assertEquals(
            factoid[3], replacement,
            "Factoid failed to retrieve the defintion correctly")
        self.assertEquals(factoid[4], user3,
                          "Factoid failed to retrieve the user correctly")

        delta = datetime.now() - factoid[5]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a factoid date set: delta is %d" %
            delta.total_seconds())

        self.assertFalse(
            factoid[6], "Factoid failed to retrieve the locked flag correctly")

    def test_forget_factoid(self):
        user = "******"
        user2 = "someotheruser"
        user3 = "someguy"
        item = "somefactoidToForget"
        isAre = True
        definition = "a good thing to talk about"
        definition2 = "something people write"

        success = self.db.addFactoid(user, item, isAre, definition, False)
        self.assertTrue(success, "Failed to add a new factoid")

        success = self.db.addFactoid(user2, item, isAre, definition2, False)
        self.assertTrue(success, "Failed to add a new factoid")

        wasDeleted = self.db.forgetFactoid(item, user3)
        self.assertTrue(wasDeleted, "Incorect return value from forgetFactoid")

        data = self.db.getFactoid(item)
        self.assertEqual(
            len(data), 0,
            "Returned wrong number of results for a forgotten factoid: %d" %
            (len(data), ))

    def test_forget_factoid_that_doesnt_exist(self):
        user = "******"
        item = "somefactoidThatIsntHere"

        wasDeleted = self.db.forgetFactoid(item, user)
        self.assertFalse(wasDeleted,
                         "Incorrect return value from forgetFactoid")

    def test_lock_and_replace_or_forget_factoid(self):
        user = "******"
        item = "lockedfactoid"
        isAre = True
        definition = "a good thing to talk about"
        overwrite = False

        success = self.db.addFactoid(user, item, isAre, definition, False)
        self.assertTrue(success, "Failed to add a new factoid")

        self.db.lockFactoid(item)

        data = self.db.getFactoid(item)
        self.assertEqual(
            len(data), 1,
            "Returned wrong number of results for a factoid: %d" %
            (len(data), ))

        factoid = data[0]

        self.assertTrue(
            factoid[6],
            "Factoid does not appear to be locked when it should be")

        wasDeleted = self.db.forgetFactoid(item, user)
        self.assertFalse(wasDeleted,
                         "Was incorrrectly able to delete a locked factoid")

        success = self.db.addFactoid(user, item, isAre, definition, True)
        self.assertFalse(success,
                         "Was incorrectly able to replace a locked factoid")

    def test_factoid_info(self):
        user = "******"
        counteditem = "countedfactoid"
        isAre = False
        definition = "something to test"
        overwrite = False

        # Verify that this factoid has no history to start
        info = self.db.infoFactoid(counteditem)
        self.assertFalse(info, "Factoid has info when it shouldn't.")

        # Add the factoid
        success = self.db.addFactoid(user, counteditem, isAre, definition,
                                     overwrite)
        self.assertTrue(success, "Failed to add a new factoid")

        # Verify that it now has some history
        info = self.db.infoFactoid(counteditem)
        self.assertTrue(info, "Factoid has no info when it should.")

        # Verify that there's just one of info
        self.assertEqual(len(info), 1,
                         "Factoid doesn't have the correct amount of info")

        # And verify that the info is correct
        history = info[0]
        self.assertEqual(history[1], counteditem,
                         "Factoid history has the wrong item name")
        self.assertEqual(history[2], definition,
                         "Factoid history has the wrong definition")
        self.assertEqual(history[3], user,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history has the wrong item name the second place: %s" %
            history[5])
        self.assertIsNone(
            history[6], "Factoid history has the wrong count: %s" % history[6])
        self.assertIsNone(
            history[7],
            "Factoid history has the wrong last referenced time: %s" %
            history[7])

        # Now do a reference...
        data = self.db.getFactoid(counteditem)

        # ...and verify that the info gets updated
        info = self.db.infoFactoid(counteditem)
        self.assertTrue(info, "Factoid has no info when it should.")

        # Verify that there's still just one of info
        self.assertEqual(len(info), 1,
                         "Factoid doesn't have the correct amount of info")

        # And verify that the info is correct
        history = info[0]
        self.assertEqual(history[1], counteditem,
                         "Factoid history has the wrong item name")
        self.assertEqual(history[2], definition,
                         "Factoid history has the wrong definition")
        self.assertEqual(history[3], user,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertEqual(
            history[5], counteditem,
            "Factoid history has the wrong item name the second place: %s" %
            history[5])
        self.assertEqual(
            history[6], 1,
            "Factoid history has the wrong count: %s" % history[6])
        delta = datetime.now() - history[7]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())

        # Finally do a few more references
        data = self.db.getFactoid(counteditem)
        data = self.db.getFactoid(counteditem)
        data = self.db.getFactoid(counteditem)
        data = self.db.getFactoid(counteditem)

        # ...and verify that the info gets updated
        info = self.db.infoFactoid(counteditem)
        self.assertTrue(info, "Factoid has no info when it should.")

        # Verify that there's still just one of info
        self.assertEqual(len(info), 1,
                         "Factoid doesn't have the correct amount of info")

        # And verify that the info is correct
        history = info[0]
        self.assertEqual(history[1], counteditem,
                         "Factoid history has the wrong item name")
        self.assertEqual(history[2], definition,
                         "Factoid history has the wrong definition")
        self.assertEqual(history[3], user,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertEqual(
            history[5], counteditem,
            "Factoid history has the wrong item name the second place: %s" %
            history[5])
        self.assertEqual(
            history[6], 5,
            "Factoid history has the wrong count: %s" % history[6])
        delta = datetime.now() - history[7]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())

    def test_get_factoid_doesnt_set_refs(self):
        user = "******"
        nonexistantitem = "not_a_factoid"

        # Verify that this factoid has no history to start
        info = self.db.infoFactoid(nonexistantitem)
        self.assertFalse(info, "Factoid has info when it shouldn't.")

        # Now do a reference...
        data = self.db.getFactoid(nonexistantitem)
        self.assertFalse(data, "Factoid exists when it shouldn't.")

        # Verify that this factoid still has no history
        info = self.db.infoFactoid(nonexistantitem)
        self.assertFalse(info, "Factoid has info when it shouldn't.")

    def test_info_for_forget_factoid(self):
        user = "******"
        userWhoDeletes = "killer"
        item = "forgottenfactoid"
        isAre = False
        definition = "something to test"

        # Add the factoid
        success = self.db.addFactoid(user, item, isAre, definition, False)
        self.assertTrue(success, "Failed to add a new factoid")

        # Verify that it now has some history
        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")

        # Verify that there's just one of info
        self.assertEqual(len(info), 1,
                         "Factoid doesn't have the correct amount of info")

        # Now forget it..
        status = self.db.forgetFactoid(item, userWhoDeletes)

        # ...and verify that the info gets updated
        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")

        # Verify that there are 2 entries now
        self.assertEqual(len(info), 2,
                         "Factoid doesn't have the correct amount of info")

        # Verify that the first entry correctly specifies the add
        history = info[0]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertEqual(
            history[2], definition,
            "Factoid history has the wrong definition: '%s'" % history[2])
        self.assertEqual(history[3], user,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

        # Verify that the second entry correctly specifies the forget
        history = info[1]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertIsNone(
            history[2],
            "Factoid history for forgotten entry has a definition when it shouldn't"
        )
        self.assertEqual(
            history[3], userWhoDeletes,
            "Factoid history for forgotten entry has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

        # Now reference this factoid and see if it gets added to the ref count
        data = self.db.getFactoid(item)

        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")
        self.assertEqual(len(info), 2,
                         "Factoid doesn't have the correct amount of info")

        # Verify that there is still no ref count
        history = info[0]
        self.assertIsNone(
            history[5],
            "Factoid history ref does not contain the correct item.")
        self.assertIsNone(
            history[6],
            "Factoid history has a ref count when it shouldn't: %s" %
            history[6])
        self.assertIsNone(
            history[7],
            "Factoid history has a reference time when it shouldn't")

    def test_ref_count_for_forget_factoid(self):
        user = "******"
        userWhoDeletes = "killer"
        item = "hereGoneBackAgain"
        isAre = False
        definition = "a factoid that keeps disappearing"

        # Add the factoid
        success = self.db.addFactoid(user, item, isAre, definition, False)
        self.assertTrue(success, "Failed to add a new factoid")

        # Verify that it now has some history
        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")
        self.assertEqual(len(info), 1,
                         "Factoid doesn't have the correct amount of info")

        # Reference it
        data = self.db.getFactoid(item)

        # Now forget it..
        status = self.db.forgetFactoid(item, userWhoDeletes)

        # ...and verify that the ref count still exists
        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")
        self.assertEqual(len(info), 2,
                         "Factoid doesn't have the correct amount of info")

        # Verify that the ref count still exists
        history = info[0]
        self.assertEquals(
            history[6], 1,
            "Factoid history ref count is incorrect: %s" % history[6])
        history = info[1]
        self.assertEquals(
            history[6], 1,
            "Factoid history ref count is incorrect: %s" % history[6])

        # Now reference again now that it's deleted...
        data = self.db.getFactoid(item)

        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")
        self.assertEqual(len(info), 2,
                         "Factoid doesn't have the correct amount of info")

        # Verify that the ref count hasn't changed
        history = info[0]
        self.assertEquals(
            history[6], 1,
            "Factoid history ref count is incorrect: %s" % history[6])
        history = info[1]
        self.assertEquals(
            history[6], 1,
            "Factoid history ref count is incorrect: %s" % history[6])

    def test_info_for_forget_factoid(self):
        user = "******"
        user2 = "otherguy"
        userWhoDeletes = "killer"
        item = "multifactoid"
        isAre = False
        definition = "something to test"
        definition2 = "something to forget"

        # Add the factoid
        success = self.db.addFactoid(user, item, isAre, definition, False)
        self.assertTrue(success, "Failed to add a new factoid")

        # Add a second entry
        success = self.db.addFactoid(user2, item, isAre, definition2, False)
        self.assertTrue(success, "Failed to add a second entry to a factoid")

        # Now forget it..
        status = self.db.forgetFactoid(item, userWhoDeletes)

        # Verify that it now has some history
        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")

        # Verify that there are 3 info entries
        self.assertEqual(len(info), 3,
                         "Factoid doesn't have the correct amount of info")

        # Verify that the first entry correctly specifies the forget
        history = info[0]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertIsNone(
            history[2],
            "Factoid history has the wrong definition: '%s'" % history[2])
        self.assertEqual(history[3], userWhoDeletes,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

        # Verify that the second entry correctly specifies the second add
        history = info[1]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertEqual(
            history[2], definition2,
            "Factoid history has the wrong definition: '%s'" % history[2])
        self.assertEqual(history[3], user2,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

        # Verify that the third entry correctly specifies the first add
        history = info[2]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertEqual(
            history[2], definition,
            "Factoid history for forgotten entry has a definition when it shouldn't"
        )
        self.assertEqual(
            history[3], user,
            "Factoid history for forgotten entry has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

    def test_overwrite_multipart_factoid(self):
        user = "******"
        user2 = "otherguy"
        user3 = "overwriter"
        item = "multiforgottenfactoid"
        isAre = True
        definition = "something to test"
        definition2 = "something to forget"
        definition3 = "the REAL definition"

        # Add the factoid
        success = self.db.addFactoid(user, item, isAre, definition, False)
        self.assertTrue(success, "Failed to add a new factoid")

        # Add a second entry
        success = self.db.addFactoid(user2, item, isAre, definition2, False)
        self.assertTrue(success, "Failed to add a second entry to a factoid")

        # Overwrite them with a new one
        success = self.db.addFactoid(user3, item, isAre, definition3, True)
        self.assertTrue(success, "Failed to overwrite a multi-part factoid")

        # Verify that it now has some history
        info = self.db.infoFactoid(item)
        self.assertTrue(info, "Factoid has no info when it should.")
        self.assertEqual(len(info), 4,
                         "Factoid doesn't have the correct amount of info")

        # Verify that the first entry correctly specifies the overwrite
        history = info[0]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertEqual(
            history[2], definition3,
            "Factoid history has wrong definition: '%s'" % history[2])
        self.assertEqual(history[3], user3,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

        # Verify that the second entry correctly specifies a forget (trigger by the overwrite)
        history = info[1]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertIsNone(
            history[2],
            "Factoid history has the definition when it shouldn't: '%s'" %
            history[2])
        self.assertEqual(history[3], user3,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

        # Verify that the third entry correctly specifies the second add
        history = info[2]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertEqual(history[2], definition2,
                         "Factoid history has a definition: %s" % history[2])
        self.assertEqual(
            history[3], user2,
            "Factoid history for forgotten entry has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

        # Verify that the fourth entry correctly specifies the first add
        history = info[3]
        self.assertEqual(history[1], item,
                         "Factoid history has the wrong item name")
        self.assertEqual(
            history[2], definition,
            "Factoid history has the wrong definition: '%s'" % history[2])
        self.assertEqual(history[3], user,
                         "Factoid history has the wrong username")
        delta = datetime.now() - history[4]
        self.assertLess(
            delta.total_seconds(), 2,
            "Factoid history has the wrong time. delta is %d" %
            delta.total_seconds())
        self.assertIsNone(
            history[5],
            "Factoid history ref count has an item name when it shouldn't.")
        self.assertIsNone(history[6],
                          "Factoid history has a count when it shouldn't")
        self.assertIsNone(
            history[7],
            "Factoid history has a last referenced time when it shouldn't.")

    def test_mood(self):
        # Testing mood here because it relies on factoids

        # Test that mood is initially 0 even with botsnack and botsmack
        # not in the DB
        mood = self.db.mood()
        self.assertEqual(mood, 0, "Empty DB returned wrong mood")

        # Add the factoids
        success = self.db.addFactoid("testuser", "botsnack", 0,
                                     "<reply>Thank you!", False)
        success = self.db.addFactoid("testuser", "botsmack", 0, "<reply>OUCH!",
                                     False)

        # Give the bot 1 snack...
        self.db.getFactoid("botsnack")

        # ...and make sure the mood is 1
        mood = self.db.mood()
        self.assertEqual(mood, 1, "After botsnack returned the wrong mood")

        # Smack it down...
        self.db.getFactoid("botsmack")

        # ...and verify we're back at 0
        mood = self.db.mood()
        self.assertEqual(mood, 0,
                         "After equal snacks and smacks, mood is not 0")

        # A couple more snacks...
        self.db.getFactoid("botsnack")
        self.db.getFactoid("botsnack")

        # Verify we're at 2
        mood = self.db.mood()
        self.assertEqual(mood, 2, "After 2 snacks, mood is not 2")

        # 4 smacks...
        self.db.getFactoid("botsmack")
        self.db.getFactoid("botsmack")
        self.db.getFactoid("botsmack")
        self.db.getFactoid("botsmack")

        # Now we should be at -2
        mood = self.db.mood()
        self.assertEqual(mood, -2, "After 4 smacks, mood is not -22")

    def tearDown(self):
        # Clear all factoids and history
        self.db.deleteAllFactoids()
コード例 #16
0
ファイル: test.py プロジェクト: tfischer4765/gthx
class DbAccessSeenTest(unittest.TestCase):
    missinguser = "******"
    seenuser = "******"
    seenuser2 = "seenuser2"
    unicodeuser = "******"
    unicodemessage = "I love 🌮s"

    def setUp(self):
        config = ConfigParser.ConfigParser()
        results = config.read('gthx.config.local')
        if not results:
            raise SystemExit("Failed to read config file 'gthx.config.local'")
        dbUser = config.get('MYSQL', 'GTHX_MYSQL_USER')
        dbPassword = config.get('MYSQL', 'GTHX_MYSQL_PASSWORD')
        dbName = config.get('MYSQL', 'GTHX_MYSQL_DATABASE')

        self.db = DbAccess(dbUser, dbPassword, dbName)

    def test_missing_seen(self):
        data = self.db.seen(DbAccessSeenTest.missinguser)
        self.assertEqual(len(data), 0,
                         "Returned data for a user that hasn't been seen")

    def test_valid_seen(self):
        user = DbAccessSeenTest.seenuser
        channel = "#test_channel"
        message = "Running unit tests..."
        self.db.updateSeen(user, channel, message)

        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a user that has been seen")

        data = rows[0]

        self.assertEqual(data[Seen.name], user,
                         "Wrong username returned for seen user")
        self.assertEqual(data[Seen.channel], channel,
                         "Wrong channel returned for a seen user")

        delta = datetime.now() - data[Seen.timestamp]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a seen user: delta is %d" %
            delta.total_seconds())
        self.assertEqual(data[Seen.message], message,
                         "Wrong message returned for a seen user")

        self.db.deleteSeen(user)

    def test_update_of_existing_seen(self):
        user = DbAccessSeenTest.seenuser2
        channel = "#test_channel"
        message = "Running unit tests..."

        self.db.updateSeen(user, channel, message)

        # First test the normal case
        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a user that has been seen")

        data = rows[0]

        delta = datetime.now() - data[Seen.timestamp]
        self.assertLess(
            delta.total_seconds(), 2,
            'Wrong time returned for a seen user: delta is %d' %
            (delta.total_seconds(), ))

        # Now wait a couple seconds and verify that the delta has changed
        time.sleep(2)

        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a user that has been seen")

        data = rows[0]

        delta = datetime.now() - data[Seen.timestamp]
        self.assertGreater(
            delta.total_seconds(), 1,
            'Wrong time returned for a seen user: delta is %d' %
            delta.total_seconds())

        # Now update the same user again, then verify that the time has been updated.
        self.db.updateSeen(user, channel, message)

        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a user that has been seen")

        data = rows[0]

        delta = datetime.now() - data[Seen.timestamp]
        self.assertLess(
            delta.total_seconds(), 2,
            'Wrong time returned for a seen user: delta is %d' %
            delta.total_seconds())

    def test_update_of_seen_with_nick_including_backslashes(self):
        # These were found to cause problems in the real system
        user = "******"
        channel = "#test_channel"
        message = "Running unit tests..."

        self.db.updateSeen(user, channel, message)

        # First test the normal case
        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a user that has been seen: %d" %
            len(rows))

        # Now update seen a few more times
        self.db.updateSeen(user, channel, message)
        self.db.updateSeen(user, channel, message)
        self.db.updateSeen(user, channel, message)
        self.db.updateSeen(user, channel, message)
        self.db.updateSeen(user, channel, message)

        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a user that has been seen")

    def test_sql_injection_through_seen(self):
        # SELECT * FROM seen WHERE name LIKE
        # blah; DROP TABLE SEEN; SELECT * FROM SEEN WHERE name LIKE blah
        # ORDER BY timestamp DESC LIMIT 3
        # These were found to cause problems in the real system
        #user = "******"
        user = "******"
        channel = "#test_channel"
        message = "Running unit tests..."

        self.db.updateSeen(user, channel, message)

        # First test the normal case
        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a user that has been seen: %d" %
            len(rows))

    def test_unicode_seen(self):
        user = DbAccessSeenTest.unicodeuser
        channel = "#test_channel"
        message = DbAccessSeenTest.unicodemessage

        self.db.updateSeen(user, channel, message)

        rows = self.db.seen(user)
        self.assertEqual(
            len(rows), 1,
            "Returned incorrect data for a unicode user that has been seen")

        data = rows[0]

        self.assertEqual(data[Seen.name], user,
                         "Wrong username returned for a unicode seen user")
        self.assertEqual(data[Seen.channel], channel,
                         "Wrong channel returned for a unicode seen user")

        delta = datetime.now() - data[Seen.timestamp]
        self.assertLess(
            delta.total_seconds(), 2,
            "Wrong time returned for a unicode seen user: delta is %d" %
            delta.total_seconds())
        self.assertEqual(data[Seen.message], message,
                         "Wrong message returned for a unicode seen message")

        self.db.deleteSeen(user)

    def tearDown(self):
        self.db.deleteSeen(DbAccessSeenTest.missinguser)
        self.db.deleteSeen(DbAccessSeenTest.seenuser)
        self.db.deleteSeen(DbAccessSeenTest.seenuser2)
コード例 #17
0
ファイル: test.py プロジェクト: tfischer4765/gthx
class DbAccessThingiverseTest(unittest.TestCase):
    def setUp(self):
        config = ConfigParser.ConfigParser()
        results = config.read('gthx.config.local')
        if not results:
            raise SystemExit("Failed to read config file 'gthx.config.local'")
        dbUser = config.get('MYSQL', 'GTHX_MYSQL_USER')
        dbPassword = config.get('MYSQL', 'GTHX_MYSQL_PASSWORD')
        dbName = config.get('MYSQL', 'GTHX_MYSQL_DATABASE')

        self.db = DbAccess(dbUser, dbPassword, dbName)

    def test_thingiverse_refs(self):
        testItem = 1234
        testTitle = "The most wonderful thing in the world"

        rows = self.db.addThingiverseRef(testItem)
        self.assertEquals(
            len(rows), 1,
            "First thingiverse ref returned the wrong number of rows.")
        data = rows[0]
        self.assertEquals(
            data[0], 1,
            "First thingiverse ref returned wrong number of references.")
        self.assertIsNone(
            data[1],
            "First thingiverse ref returned a title when it shouldn't have.")

        rows = self.db.addThingiverseRef(testItem)
        self.assertEquals(
            len(rows), 1,
            "Second thingiverse ref returned the wrong number of rows.")
        data = rows[0]
        self.assertEquals(
            data[0], 2,
            "Second thingiverse ref returned wrong number of references.")
        self.assertIsNone(
            data[1],
            "Second thingiverse ref returned a title when it shouldn't have.")

        rows = self.db.addThingiverseRef(testItem)
        self.assertEquals(
            len(rows), 1,
            "Third thingiverse ref returned the wrong number of rows.")
        data = rows[0]
        self.assertEquals(
            data[0], 3,
            "Third thingiverse ref returned wrong number of references.")
        self.assertIsNone(
            data[1],
            "Third thingiverse ref returned a title when it shouldn't have.")

        self.db.addThingiverseTitle(testItem, testTitle)

        rows = self.db.addThingiverseRef(testItem)
        self.assertEquals(
            len(rows), 1,
            "Fourth thingiverse ref returned the wrong number of rows.")
        data = rows[0]
        self.assertEquals(
            data[0], 4,
            "Fourth thingiverse ref returned wrong number of references.")
        self.assertEquals(data[1], testTitle,
                          "Fourth thingiverse ref returned the wrong title.")

    def tearDown(self):
        self.db.deleteAllThingiverseRefs()
コード例 #18
0
ファイル: gthx.py プロジェクト: quillford/gthx
class Gthx(irc.IRCClient):
    """An IRC bot for #reprap."""
    
    restring = ""

    def __init__(self):
        self.db = DbAccess()
        self.trackedpresent = dict()
        self.gotwhoischannel = False
        self.seenQuery = re.compile("\s*seen\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)[\s\?]*")
        self.tellQuery = re.compile("\s*tell\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)\s*(.+)")
        self.factoidQuery = re.compile("(.+)[?!](\s*$|\s*\|\s*([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)$)")
        self.factoidSet = re.compile("(.+?)\s(is|are)(\salso)?\s(.+)")
        self.googleQuery = re.compile("\s*google\s+(.*?)\s+for\s+([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)")
        self.uptimeStart = datetime.datetime.now()
        self.lurkerReplyChannel = ""
        
    def connectionMade(self):
        self.log("IRC Connection made")
        irc.IRCClient.connectionMade(self)

    def connectionLost(self, reason):
        irc.IRCClient.connectionLost(self, reason)
        self.log("[disconnected at %s]" % time.asctime(time.localtime(time.time())))
        self.emailClient.send("%s disconnected" % self.nickname, "%s is disconnected from the server.\n\n%s" % (self.nickname, reason))

    def log(self, message):
        """Write a message to the screen."""
        timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
        print '%s %s' % (timestamp, message)

    # callbacks for events

    def signedOn(self):
        """Called when bot has succesfully signed on to server."""
        self.log("Signed on to the IRC server")
        # Seems like a good time to also register with the nickserv
        nickservPassword = os.getenv("GTHX_NICKSERV_PASSWORD")
        if (nickservPassword):
            print "Identifying with the nickserv"
            self.msg("nickserv", "IDENTIFY %s" % nickservPassword)
        self.channelList = [channel for channel in self.factory.channels.split(',')]
        for channelm in self.channelList:
            self.log("Joining channel %s" % channelm)
            self.join(channelm)
            if (trackednick == None):
                self.trackedpresent[channelm] = False

        self.gotwhoischannel = False
        # kthx uses: "\s*(${names})[:;,-]?\s*" to match nicks
        if (trackednick):
            self.matchNick = "(%s|%s)(:|;|,|-|\s)+(.+)" % (self.nickname, trackednick)
            print "Querying WHOIS %s at startup" % trackednick
            self.whois(trackednick)
        else:
            self.matchNick = "(%s)(:|;|,|-|\s)+(.+)" % (self.nickname)
            print "Running in standalone mode."
            message += "Running in standalone mode."

    def joined(self, channel):
        """Called when the bot joins the channel."""
        self.log("[I have joined %s as '%s']" % (channel, self.nickname))
        message = "I have joined channel %s as '%s'\n" % (channel, self.nickname)
        self.emailClient.threadsend("%s connected" % self.nickname, message)
        
    def userJoined(self, user, channel):
        """
        Called when I see another user joining a channel.
        """
        print "%s joined channel %s" % (user, channel)
        # TODO: Change this to verify the IP address before setting it
        if trackednick and (user == trackednick) and (self.trackedpresent[channel] == False):
            self.trackedpresent[channel] = True
            print "%s is here!" % trackednick
            self.emailClient.threadsend("%s status" % self.nickname, "%s has joined channel %s" % (user, channel))
                
            
    def userLeft(self, user, channel):
        """
        Called when I see another user leaving a channel.
        """
        print "%s left channel %s" % (user, channel)
        if trackednick and (user == trackednick) and (self.trackedpresent[channel]):
            self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend("%s status" % self.nickname, "%s has left channel %s" % (user, channel))

    def userQuit(self, user, quitMessage):
        """
        Called when I see another user disconnect from the network.
        """
        print "%s disconnected : %s" % (user, quitMessage)
        if trackednick and (user == trackednick):
            for channel in self.channelList:
                self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend("%s status" % self.nickname, "%s has quit: %s" % (user, quitMessage))

    def userKicked(self, kickee, channel, kicker, message):
        """
        Called when I observe someone else being kicked from a channel.
        """
        print "In %s, %s kicked %s : %s" % (channel, kicker, kickee, message)
        if trackednick and (kickee == trackednick) and (self.trackedpresent[channel]):
            self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend("%s status" % self.nickname, "%s has been kicked from %s by %s: %s" % (kickee, channel, kicker, message))

    def userRenamed(self, oldname, newname):
        """
        A user changed their name from oldname to newname.
        """
        print "%s renamed to %s" % (oldname, newname)
        if (trackednick == None):
            return
        if oldname == trackednick:
            for channel in self.channelList:
                self.trackedpresent[channel] = False
            print "%s is gone." % trackednick
            self.emailClient.threadsend("%s status" % self.nickname, "%s has been renamed to %s" % (oldname, newname))
        if newname == trackednick:
            self.whois(trackednick)
            print "%s is here!" % trackednick
            self.emailClient.threadsend("%s status" % self.nickname, "%s has been renamed to %s--checking WHOIS" % (oldname, newname))

    def irc_unknown(self, prefix, command, params):
        #print "Unknown command '%s' '%s' '%s'" % (prefix, command, params)
        if (command == 'RPL_NAMREPLY'):
            if (self.lurkerReplyChannel == ""):
                return
            users = params[3].split()
            for user in users:
                self.channelCount = self.channelCount + 1
                rows = self.db.seen(user)
                if len(rows) == 0:
                       self.lurkerCount = self.lurkerCount + 1
        elif (command == 'RPL_ENDOFNAMES'):
            if (self.lurkerReplyChannel == ""):
                return
            print "Got RPL_ENDOFNAMES"
            self.msg(self.lurkerReplyChannel,"%d of the %d users in %s right now have never said anything." % (self.lurkerCount, self.channelCount, params[1]))
            self.lurkerReplyChannel = ""
    
    def irc_RPL_WHOISCHANNELS(self, prefix, params):
        """This method is called when the client recieves a reply for whois.
        params[0]: requestor
        params[1]: nick requested
        params[2]: list of channels in common
        """
        print "Got WHOISCHANNELS with prefix '%s' and params '%s'" % (prefix, params)
        print "%s is in channels %s" % (params[1], params[2])
        self.gotwhoischannel = True
        trackedchannels = params[2].split(" ")
        for channel in self.channelList:
            if channel in trackedchannels:
                self.trackedpresent[channel] = True
                print "%s is in %s!!" %  (params[1], channel)
                self.emailClient.threadsend("%s status" % self.nickname, "%s is in channel %s" % (params[1], params[2]))
            else:
                self.trackedpresent[channel] = False
                print "%s is NOT in %s!!" %  (params[1], channel)

    def irc_RPL_WHOISUSER(self, prefix, params):
        print "Got WHOISUSER with prefix '%s' and params '%s'" % (prefix, params)

    def irc_RPL_WHOISSERVER(self, prefix, params):
        print "Got WHOISSERVER with prefix '%s' and params '%s'" % (prefix, params)

    def irc_RPL_WHOISOPERATOR(self, prefix, params):
        print "Got WHOISOPERATOR with prefix '%s' and params '%s'" % (prefix, params)

    def irc_RPL_WHOISIDLE(self, prefix, params):
        print "Got WHOISIDLE with prefix '%s' and params '%s'" % (prefix, params)

    def irc_RPL_ENDOFWHOIS(self, prefix, params):
        print "Got ENDOFWHOIS with prefix '%s' and params '%s'" % (prefix, params)
        if not self.gotwhoischannel:
            if (trackednick != None):
                print "No response from %s. Must not be present." % trackednick
                for channel in self.channelList:
                    self.trackedpresent[channel] = False
                    self.emailClient.threadsend("%s status" % self.nickname, "%s is not in channel %s" % (trackednick, channel))

    def getFactoidString(self, query):
        answer = self.db.getFactoid(query)
        if answer:
            for i, factoid in enumerate(answer):
                if i == 0:
                    if factoid[3].startswith("<reply>") or factoid[3].startswith("<action>"):
                        fstring = factoid[3]
                        break
                    else:
                        fstring = query
                fstring += "%s" % " are " if factoid[2] else " is "
                if i > 0:
                    fstring += "also "
                fstring += factoid[3]
                if i < len(answer) - 1:
                    fstring += " and"
            return fstring
        else:
            return None
        
    def privmsg(self, user, channel, msg):
        """Called when the bot receives a message, both public and private."""
        user = user.split('!', 1)[0]

        # By default, don't reply to anything
        canReply = False
        private = False
        replyChannel = channel
        parseMsg = msg
        directAddress = False

        # Debug print ALL messages
        #print "Message from '%s' on '%s': '%s'" % (user, channel, msg)
        
        # Check to see if they're sending me a private message
        if channel == self.nickname:
            canReply = True
            private = True
            replyChannel = user
            self.log("Private message from %s: %s" % (user, msg))
            if str.lower(user) == "nickserv":
                self.log("Nickserv says: %s" % msg)
            if parseMsg.startswith("whois "):
                whoisnick = parseMsg.split(" ",1)[1]
                print "Doing a whois '%s'" % whoisnick
                self.whois(whoisnick)

        # Update the seen database, but only if it's not a private message
        if channel in self.channelList and not private:
            self.db.updateSeen(user,channel,msg)

        # If kthx said something, mark him as here and ignore everything he says
        if user == trackednick and not private:
            if (self.trackedpresent[channel] == False):
                self.trackedpresent[channel] = True
                self.emailClient.threadsend("%s status" % self.nickname, "%s spoke in %s unexpectedly and got marked as present: %s" % (user, channel,msg))
            return
        
        # If kthx is gone, then we can always reply
        if not private and not self.trackedpresent[channel]:
            canReply = True

        # Check to see if we have a tell waiting for this user
        tells = self.db.getTell(user)
        if tells:
            for message in tells:
                print "Found tell for '%s' from '%s'" % (user, message[Tell.author])
                author = message[Tell.author]
                timestring = timesincestring(message[Tell.timestamp])
                text = message[Tell.message]
                inTracked = message[Tell.inTracked]
                # We have 3 cases:
                # 1) kthx was around when this tell happened and is still around now.
                #    In this case, we assume kthx will relay the message and just delete it
                # 2) kthx was around when this tell happened and is not here now.
                #    In this case, we want to send the message and mention that kthx may repeat it
                # 3) kthx was not around when this tell happened and may or may not be here now
                #    Whether or not kthx is now here, we need to say the message
                # 4) gthx was specifically addressed for this tell
                #    Whether or not kthx is now here, we need to say the message
                #
                # If we can't reply, it means that kthx is present. In that
                # case, the tell has already been erased, so in both cases,
                # we're good.
                if canReply or not inTracked:
                    if inTracked:
                        self.msg(replyChannel,"%s: %s ago <%s> tell %s %s (%s may repeat this)" % (user, timestring, author, user, text, trackednick))
                    else:
                        self.msg(replyChannel,"%s: %s ago <%s> tell %s %s" % (user, timestring, author, user, text))

        # Check for specifically addressed messages
        m = re.match(self.matchNick, parseMsg)
        if m:
            print "Found message addressed to '%s'. My nick is '%s'." % (m.group(1), self.nickname)
            parseMsg = m.group(3)
            # Mark it as a direct address so we can look for a factoid
            directAddress = True
            # If it's addressed directly to me, we can reply
            if m.group(1) == self.nickname:
                canReply = True
            
        # Check for status query
        if canReply and parseMsg == "status?":
            if (trackednick):
                if (private):
                    reply = "%s: OK; Up for %s; " % (VERSION, timesincestring(self.uptimeStart))
                    for channel in self.channelList:
                        reply += "%s %s; " % (channel, "PRESENT" if self.trackedpresent[channel] else "GONE")
                else:
                    reply = "%s: OK; Up for %s; %s is %s" % (VERSION, timesincestring(self.uptimeStart), trackednick, "PRESENT" if self.trackedpresent[channel] else "GONE")
            else:
                reply = "%s: OK; Up for %s; standalone mode" % (VERSION, timesincestring(self.uptimeStart))
            self.msg(replyChannel, reply)
            return
        
        # Check for lurker query
        if canReply and parseMsg == "lurkers?":
            self.msg(replyChannel, "Looking for lurkers...")
            self.lurkerReplyChannel = replyChannel
            self.lurkerCount = 0
            self.channelCount = 0
            print "Sending request 'NAMES %s'" % channel
            self.sendLine("NAMES %s" % channel)
            return
        
        # Check for tell query
        m = self.tellQuery.match(parseMsg)
        if m and directAddress:
            print "Got tell from '%s' for  '%s' message '%s'." % (user, m.group(1), m.group(2))
            # The is in the tracked bot if the tracked bot is present and it was not a message 
            # specifically directed to us. This is a little tricky since the only way to know
            # that a message was specifically directed to us is to see if it was a direct address
            # and we can reply
            success = self.db.addTell(user, m.group(1), m.group(2), not (directAddress and canReply) and self.trackedpresent[channel])
            if success and canReply:
                self.msg(replyChannel, "%s: I'll pass that on when %s is around." % (user, m.group(1)))
            return
        
        # Check for seen query
        if canReply:
            m = self.seenQuery.match(parseMsg)
            if m:
                queryname = m.group(1)
                print "%s asked about '%s'" % (user, queryname)
                rows = self.db.seen(queryname)
                if len(rows) == 0:
                    reply = "Sorry, I haven't seen %s." % queryname
                    self.msg(replyChannel, reply)
                for i,row in enumerate(rows):
                    reply = "%s was last seen in %s %s ago saying '%s'." % (row[Seen.name], row[Seen.channel], timesincestring(row[Seen.timestamp]), row[Seen.message])
                    self.msg(replyChannel, reply)
                    if i >= 2:
                        # Don't reply more than 3 times to a seen query
                        break
                return
        
        # Check for google query
        if canReply:
            m = self.googleQuery.match(parseMsg)
            if m:
                queryname = urllib.quote_plus(m.group(1))
                foruser = m.group(2)
                print "%s asked to google '%s' for %s" % (user, queryname, foruser)
                reply = "%s: http://lmgtfy.com/?q=%s" % (foruser, queryname)
                self.msg(replyChannel, reply)
                return
        
        # Check for setting a factoid
        factoid = None
        if directAddress:
            factoid = self.factoidSet.match(parseMsg)
            if factoid:
                invalidwords = re.match('(here|how|it|something|that|this|what|when|where|which|who|why|you)', factoid.group(1), re.IGNORECASE)
                if not invalidwords:
                    print "%s tried to set factoid '%s'." % (user, factoid.group(1))
                    success = self.db.addFactoid(user, factoid.group(1), True if factoid.group(2) == 'are' else False, factoid.group(4), True if not factoid.group(3) else False)
                    if canReply:
                        if success:
                            self.msg(replyChannel, "%s: Okay." % user)
                        else:
                            self.msg(replyChannel, "I'm sorry, %s. I'm afraid I can't do that." % user)

        # Check for getting a factoid
        if canReply:
            f = self.factoidQuery.match(parseMsg)
            if f:
                print "factoid query from %s:%s for '%s'" % (user, channel, f.group(1))
                answer = self.getFactoidString(f.group(1))
                if answer:
                    # Replace !who and !channel in the reply
                    answer = re.sub("!who", user, answer)
                    answer = re.sub("!channel", channel, answer)
                
                    if answer.startswith("<reply>"):
                        answer = answer[7:]

                    if answer.startswith("<action>"):
                        self.describe(replyChannel, answer[8:])
                    else:
                        if (f.group(3)):
                            answer = "%s, %s" % (f.group(3), answer)
                        self.msg(replyChannel, answer)

        # Check for info request
        if canReply and parseMsg.startswith("info "):
            query = parseMsg[5:]
            if query[-1:] == "?":
                query = query[:-1]
            print "info request for '%s' ReplyChannel is '%s'" % (query, replyChannel)
            refcount = 0
            answer = self.db.infoFactoid(query)
            if answer:
                for factoid in answer:
                    user = factoid[3]
                    value = factoid[2]
                    if not user:
                        user = "******"
                    if value:
                        print "At %s, %s set to: %s" % (factoid[4], user, value)
                        self.msg(replyChannel, "At %s, %s set to: %s" % (factoid[4], user, value))
                    else:
                        print "At %s, %s deleted this item" % (factoid[4], user)
                        self.msg(replyChannel, "At %s, %s deleted this item" % (factoid[4], user))
            else:
                print "No info for factoid '%s'" % query
                self.msg(replyChannel, "Sorry, I couldn't find an entry for %s" % query)

        # Check for forget request
        if directAddress and parseMsg.startswith("forget "):
            query = parseMsg[7:]
            print "forget request for '%s'" % query
            forgotten = self.db.forgetFactoid(query, user)
            if canReply:
                if forgotten:
                    self.msg(replyChannel, "%s: I've forgotten about %s" % (user, query))
                else:
                    self.msg(replyChannel, "%s: Okay, but %s didn't exist anyway" % (user, query))
        
    def action(self, sender, channel, message):
        m = re.match("([a-zA-Z\*_\\\[\]\{\}^`|\*][a-zA-Z0-9\*_\\\[\]\{\}^`|-]*)", sender)
        if m:
            sender = m.group(1)
            print "* %s %s" % (sender, message)
            self.db.updateSeen(sender, channel, "* %s %s" % (sender, message))
コード例 #19
0
ファイル: fetch_all.py プロジェクト: deaps/Python-Scripts
from RESTClient import RESTClient, Services
from DbAccess import DbAccess

# Get last/todays rates
client = RESTClient(Services.ALL_RATES)
data = client.call_service()
db = DbAccess()

list = data.find('nsp:Cube', client.namespaces)

# Insert entries in DB
for entry in list:
    entry_date = entry.attrib['time']
    entry_date_id = db.insert_entry(entry_date)

    if entry_date_id == -1:
        entry_date_id = db.entry_get_id(entry_date)[0]

    # Insert rates in DB
    for rate in entry:
        db.insert_exchangeRate(
            entry_date_id, rate.attrib['currency'], 
            rate.attrib['rate']
        )