unexist.dev

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