Changeset 35:74abd9c22b92
Added holiday feature
author | unexist |
---|---|
date | Thu, 17 Dec 2015 16:09:16 +0100 |
parents | f3e8803133cb |
children | 915b21f01115 |
files | contextbot/layer.py |
diffstat | 1 files changed, 157 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/contextbot/layer.py Tue Dec 08 13:45:27 2015 +0100 +++ b/contextbot/layer.py Thu Dec 17 16:09:16 2015 +0100 @@ -40,30 +40,37 @@ HANDLER = [] #< Handler list class ContextLayer(YowInterfaceLayer): + # Flags FLAG_UPLOAD_IMAGES = (1 << 0) #< Whether to upload images FLAG_REPOST_IMAGES = (1 << 1) #< Automatically repost images inline FLAG_YOUTUBE = (1 << 2) #< Scrape youtube video infos FLAG_SPOTIFY = (1 << 3) #< Scrape spotify track infos - nick = "ContextBot" #< Name of the bot - path_images = "images" #< Name of images folder + nick = "ContextBot" #< Name of the bot + path_images = "images" #< Name of images folder - conn = None #< Connection to sqlite3 database - proto = None #< Content of the protolol.txt file - apikeys = None #< Bot API keys - flags = 0 #< Bot flags + conn = None #< Connection to sqlite3 database + proto = None #< Content of the protolol.txt file + apikeys = None #< Bot API keys + flags = 0 #< Bot flags - spot = None #< Spotipy instance + spot = None #< Spotipy instance # Regexp - re_aliases = re.compile(r"(\${?([a-z0-9\*?]+)(-?)(?::([a-z]*))?}?)") #< Regexp for aliases expasion - re_img = re.compile(r"(https?:(?:[\/|.|\w|\s])*\.(?:jpg|gif|png))") #< Regexp to check for images - re_wurstball = re.compile(r"<img src=\"([^\"]*)\">") #< Regexp to extract image from wurstball page - re_commit = re.compile(r"<p>([^<]*)</p>") #< Regexp to fetch commit messages - re_youtube = re.compile(r"^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?" \ + RE_ALIASES = re.compile(r"(\${?([a-z0-9\*?]+)(-?)(?::([a-z]*))?}?)") #< Regexp for aliases expasion + RE_IMG = re.compile(r"(https?:(?:[\/|.|\w|\s])*\.(?:jpg|gif|png))") #< Regexp to check for images + RE_WURSTBALL = re.compile(r"<img src=\"([^\"]*)\">") #< Regexp to extract image from wurstball page + RE_COMMIT = re.compile(r"<p>([^<]*)</p>") #< Regexp to fetch commit messages + RE_YOUTUBE = re.compile(r"^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?" \ "(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)" \ - "?=|(?:embed|v|vi|user)\/))([^\?&\"'>]+)") #< Regexp to match youtube vids - re_spotify = re.compile(r"^https:\/\/open\.spotify\.com\/track\/(.*)") #< Regexp to match spotify tracks + "?=|(?:embed|v|vi|user)\/))([^\?&\"'>]+)") #< Regexp to match youtube vids + RE_SPOTIFY = re.compile(r"^https:\/\/open\.spotify\.com\/track\/(.*)") #< Regexp to match spotify tracks + RE_HOLIDAY = re.compile(r"([0-9]{4})\/([0-9]{1,2})\/([0-9]{1,2}) " \ + "([0-9]{1,2}):([0-9]{1,2})") #< Regexp to match holiday dates + RE_JID = re.compile(r"^([0-9]+)[@-]") #< Regexp to match JIDs + + # Formatting + FORMAT_HOLIDAY = "%d/%02d/%02d %02d:%02d" ## ContextBotMatch {{{ # Decorator to make the syntax a bit nicer @@ -262,10 +269,10 @@ print("handleURLMessage: captures=(" + ", ".join(captures) + "), jid=" + jid) # Do stuff with urls - if self.isFlagSet(self.FLAG_REPOST_IMAGES) and self.re_img.match(captures[0]): + if self.isFlagSet(self.FLAG_REPOST_IMAGES) and self.RE_IMG.match(captures[0]): self.uploadImage(captures[0], jid) elif self.isFlagSet(self.FLAG_SPOTIFY): - match = self.re_spotify.match(captures[0]) + match = self.RE_SPOTIFY.match(captures[0]) if None != match: if None == self.spot: @@ -293,7 +300,7 @@ self.sendReply(info, jid) elif self.isFlagSet(self.FLAG_YOUTUBE): - match = self.re_youtube.match(captures[0]) + match = self.RE_YOUTUBE.match(captures[0]) if None != match: videourl = "https://www.googleapis.com/youtube/v3" \ @@ -349,6 +356,94 @@ self.handlePhraseMessage(( "", "!", rem, "" ), jid) # }}} + ## handleHolidaySet {{{ + # Handle holidaySet message + # @param {Object} self This.. + # @param {List} captures Message captures + # @param {String} jid Message jid + ## + + @ContextBotMatch(r"^!holiday " + RE_HOLIDAY.pattern + " " + RE_HOLIDAY.pattern + "$") + def handleHolidaySet(self, captures, jid): + print("handleHolidaySet: captures=(" + ", ".join(captures) + "), jid=" + jid) + + try: + cur = self.conn.cursor() + njid = self.normalizeJid(jid) + + # Check whether we have to create a new row or update an old + stmnt = "SELECT id FROM holidays WHERE nick = ?" + cur.execute(stmnt, ( njid, )) + + row = cur.fetchone() + + # Assemble dates - stupid, eh? + date_start = self.FORMAT_HOLIDAY % self.makeIntTuple(captures[0:5]) + date_end = self.FORMAT_HOLIDAY % self.makeIntTuple(captures[5:]) + + # Either insert or update + if None == row: + stmnt = "INSERT INTO holidays(nick, start, end, created_at) VALUES(?, ?, ?, ?)" + cur.execute(stmnt, ( njid, date_start, date_end, int(time.time()), )) + else: + stmt = "UPDATE holidays SET start = ?, end = ? WHERE id = ?" + cur.execute(stmt, ( date_start, date_end, row[0], )) + + self.conn.commit() + + self.sendReply("As you command, Mistress/Master.", jid) + except sqlite3.Error, e: + print("Error %s" % e.args[0]) + # }}} + + ## handleHoliday {{{ + # Handle holiday message + # @param {Object} self This.. + # @param {List} captures Message captures + # @param {String} jid Message jid + ## + + @ContextBotMatch(r"^(\!|\?)holiday$") + def handleHoliday(self, captures, jid): + print("handleHoliday: captures=(" + ", ".join(captures) + "), jid=" + jid) + + try: + op = captures[0] + cur = self.conn.cursor() + njid = self.normalizeJid(jid) + + # Check whether we have to create a new row or update an old + stmnt = "SELECT start, end FROM holidays WHERE nick = ?" + cur.execute(stmnt, ( njid, )) + + row = cur.fetchone() + + if None == row: + self.sendReply("I am afraid you haven't set any date yet, Mistress/Master.", jid) + else: + # Too lazy here to do it properly, just regexp matching stuff + match_start = self.RE_HOLIDAY.match(row[0]) + match_end = self.RE_HOLIDAY.match(row[1]) + + if "?" == op: + self.sendReply("Mistress/Master, you've told me your holiday starts " + + self.FORMAT_HOLIDAY % self.makeIntTuple(match_start.groups()) + + " and lasts until " + self.FORMAT_HOLIDAY % self.makeIntTuple(match_end.groups()), jid) + elif "!" == op: + date_now = datetime.datetime.today() + date_start = datetime.datetime(*self.makeIntTuple(match_start.groups())) + date_end = datetime.datetime(*self.makeIntTuple(match_end.groups())) + + rem = "holiday_no" + + if(date_start < date_now < date_end): + rem = "holiday_yes" + + self.handlePhraseMessage(( "", "!", rem, "" ), jid) + except sqlite3.Error, e: + print("Error %s" % e.args[0]) + # }}} + ## handleHttpcatMessage {{{ # Handle httpcat message # @param {Object} self This.. @@ -377,7 +472,7 @@ # Fetch random image html = urllib.urlopen("http://wurstball.de/random/").read() - match = re_wurstball.findall(html) + match = RE_WURSTBALL.findall(html) if 1 <= len(match) and self.isFlagSet(self.FLAG_UPLOAD_IMAGES): self.uploadImage(match[0], jid) @@ -396,7 +491,7 @@ # Fetch random image html = urllib.urlopen("http://whatthecommit.com/").read() - match = self.re_commit.findall(html) + match = self.RE_COMMIT.findall(html) if 1 <= len(match): self.sendReply(match[0], jid) @@ -445,7 +540,7 @@ except sqlite3.Error, e: print("Error %s" % e.args[0]) - # }}} + # }}} ## handleScoreMessage {{{ # Handle score message @@ -644,7 +739,7 @@ mesg = self.replaceArgs(value[0], args) #< Might be random in this phrase # Check whether this is an uri to an image - if self.isFlagSet(self.FLAG_UPLOAD_IMAGES) and self.re_img.match(mesg): + if self.isFlagSet(self.FLAG_UPLOAD_IMAGES) and self.RE_IMG.match(mesg): self.uploadImage(mesg, jid, "%s%s" % ( op, key )) else: self.sendReply(mesg, jid) @@ -729,7 +824,7 @@ path = os.path.join(self.path_images, filename) # Handle spotify and youtube carefully - if not self.re_img.match(path): #< Spotify images have no file ext; we are direly in need of one + if not self.RE_IMG.match(path): #< Spotify images have no file ext; we are direly in need of one path = "%s.jpg" % path urllib.urlretrieve(uri, path) @@ -884,7 +979,7 @@ def replaceArgs(self, strng, args): value = strng - for(match, key, dash, meth) in self.re_aliases.findall(strng): + for(match, key, dash, meth) in self.RE_ALIASES.findall(strng): arg = key # Get index @@ -922,6 +1017,7 @@ ## isFlagSet {{{ # Check whether flag is set + # @param {Object} self This.. # @param {Integer} flag Flag to check # @return Returns either true when flag is set; otherweise false ## @@ -932,6 +1028,7 @@ ## toggleFlag {{{ # Toggle given flag + # @param {Object} self This.. # @param {Integer} flag Flag to check ## @@ -942,6 +1039,43 @@ self.flags = (self.flags | flag) # }}} + # Int helper + + ## makeIntTuple {{{ + # Stupid helper to convert a list of whatever to a tuple of int + # @param {Object} self This.. + # @param {List} list List to convert + # @return Returns a tuple of converted int + ## + + def makeIntTuple(self, list): + return tuple([ int(n) for n in list ]) + # }}} + + ## parseInt {{{ + # Parse a string like other languages.. (eg Ruby, JS) + # @param {Object} self This.. + # @param {String} str String to convert + # @return Returns a converted int + ## + + def parseInt(self, str): + return int("".join([ n for n in str if n.isdigit() ])) + # }}} + + ## normalizeJid {{{ + # Normalize Jid (strip server/group) + # @param {Object} self This.. + # @param {String} jid Jid to normalize + # @return Returns a normalized jid + ## + + def normalizeJid(self, jid): + match = self.RE_JID.match(jid) + + return match.groups()[0] + # }}} + #@ContextBotMatch(r"^([0-9]*)?\!give ([^ ]+) ([^ ]+)((?:\s(?:[^ ]*))*)") # Debug