# this is a python script for use with xchat v2.x. # INSTALL: put into ~/.xchat2/ and it should load on restart # or you can type '/py load grubdate-xchat.py' into xchat # AUTHOR: Moses Moore # If you care, pretend this was released under the GPL license # http://www.gnu.org/copyleft/gpl.html # TODO: move the config section out to a *.cfg file that can be reloaded # -- config, stuff the user will want to mess with # what channels to listen for triggers; blank for all (probably bad idea) channels = ('#farts','#test') # sites to check. # 'name','flair' : "(name) updated Xd Xh ago(flair)" # 'command' : /command and /command_emote # 'host','path' : used for the http HEAD request to get last-modified # 'checkpause' : delay between http HEAD requests to get # 'trigger' : what to listen for in the aforementioned channels # 'askpause' : delay between out-loud responses to triggers sites = { 'mspa': { 'name': 'MSPA rss feed' ,'command': 'grubdate' ,'host': 'mspaintadventures.com' ,'path': '/rss/rss.xml' ,'checkpause': 120 ,'trigger': '.update' ,'askpause': 600 } ,'sbahj': { 'name': 'Sweet Bro & Hella Jeff' ,'command': 'sbahjdate' ,'flair': ', dunkass' ,'host': 'mspaintadventures.com' ,'path': None ,'checkpause': 120 ,'trigger': '.sbahj' ,'askpause': 600 } } # -- init, stuff we do only once import xchat # import commands import httplib, time, rfc822 __module_name__ = "grubdate" # it's a Homestuck joke __module_version__ = "20120910" __module_description__ = "website update check" __module_author__ = "Mozai " for n in sites.keys() : sites[n]['lastasked'] = 0 sites[n]['lastchecked'] = 0 sites[n]['lastmodified'] = 0 def _latestSBaHJpath (): # special case. Gotta find the most recent image and THEN its last-modified c = httplib.HTTPConnection('mspaintadventures.com',timeout=1) c.request('GET','/sweetbroandhellajeff/') t = c.getresponse().read() r = t.find('"> 0): return "%dd %dh" % (d,h) elif (h > 0): return "%dh %dm" % (h,m) elif (m > 0): return "%dm %ds" % (m,s) else: return "less than a minute" def _getLastModified(site): # given a key for the sites[] dict, returns age in seconds # if request is less than sites[]['checkpause'] ago, returns cached answer global sites now = time.mktime(time.gmtime()) if (now >= (sites[site]['lastchecked']+sites[site]['checkpause'])): host = sites[site]['host'] if (site == 'sbahj'): # special case sites[site]['path'] = _latestSBaHJpath() path = sites[site]['path'] c = httplib.HTTPConnection(host,timeout=3) c.request("HEAD",path) r = c.getresponse() lastModified = r.getheader('Last-Modified') if lastModified: timetuple = rfc822.parsedate(lastModified) sites[site]['lastmodified'] = time.mktime(timetuple) sites[site]['lastchecked'] = now return sites[site]['lastmodified'] def checkCommand(word,word_eol,userdata): # respond to "/(sites[]['command'])" messages # prints to local client window global sites flair = '' site = '' for s in sites: if (sites[s].has_key('command') and word[0] == sites[s]['command']): site = s if (site == ''): print "huh? no site with matching command:",word[0] return xchat.EAT_NONE if sites[site].has_key('flair'): flair = sites[site]['flair'] now = time.mktime(time.gmtime()) modtime = _getLastModified(site) if (modtime): print "%s updated \002%s\002 ago%s" % (sites[site]['name'],_secsToPretty(now-modtime),flair) else: print "%s couldn't get a decent update; try again later?" % sites[site]['name'] return xchat.EAT_ALL def checkCommandEmote(word,word_eol,userdata): # respond to "/(sites[]['command'])_emote" messages # emotes to current context global sites flair = '' site = '' for s in sites: if (sites[s].has_key('command') and word[0] == sites[s]['command']+'_emote'): site = s if (site == ''): print "huh? no site with matching command:",word[0] return xchat.EAT_NONE if sites[site].has_key('flair'): flair = sites[site]['flair'] now = time.mktime(time.gmtime()) modtime = _getLastModified(site) if (modtime): xchat.command("me is certain %s updated \002%s\002 ago%s" % (sites[site]['name'],_secsToPretty(now-modtime),flair) ) sites[site]['lastasked'] = now else: print "%s couldn't get a decent update; try again later?" % sites[site]['name'] return xchat.EAT_ALL def trigger(word,word_eol,userdata): # listens for messages in channels[] # if it matches sites[]['trigger'], # if it's been sites[]['askpause'] since last, respond with an emote. # if it's less than that since last, respond with a privmsg. context = xchat.get_context() chan = context.get_info('channel') if ((len(channels) > 0) and (chan not in channels)): return None cmd = word[1].split(' ')[0] if (len(cmd) == 0): return None flair = '' site = '' for s in sites: if (sites[s].has_key('trigger') and cmd == sites[s]['trigger']): site = s if (site == ''): return None if sites[site].has_key('flair'): flair = sites[site]['flair'] print "...\002 Triggered by\002",word now = time.mktime(time.gmtime()) modtime = _getLastModified(site) message = '' if (modtime): message = "%s updated \002%s\002 ago%s" % (sites[site]['name'],_secsToPretty(now-modtime),flair) else: message = "%s update wasn't found; try again later." % sites[site]['name'] xchat.command('msg %s %s' % (word[0],message)) return xchat.EAT_PLUGIN if (now < sites[site]['lastasked']+sites[site]['askpause']): xchat.command('msg %s %s' % (word[0],message)) else: context.command("me is certain %s" % message) sites[site]['lastasked'] = now return xchat.EAT_PLUGIN # -- main for s in sites: if sites[s].has_key('command'): xchat.hook_command(sites[s]['command'] ,checkCommand ,help='show you %s age' % sites[s]['name'] ) for s in sites: if sites[s].has_key('command'): xchat.hook_command(sites[s]['command']+'_emote' ,checkCommandEmote ,help='announces %s age' % sites[s]['name'] ) xchat.hook_print('Channel Message', trigger) xchat.hook_print('Your Message', trigger) print "\002Loaded %s v%s\002" % (__module_name__,__module_version__) print "\002commands:\002", (' '.join(map((lambda x: sites[x].has_key('command') and "/"+sites[x]['command']+" /"+sites[x]['command']+"_emote"),sites))) print "\002triggers:\002", (' '.join(map((lambda x: sites[x].has_key('trigger') and sites[x]['trigger']),sites))), "in channels",channels