User:WindPower/RCNotify.py
About this script
This is a Python script that:
- Fetches the recent changes log every User:WindPower/Template:RCNotifyRefreshRate seconds
- Fetches the TF2 blog to look for updates
- Sends the results back to the IRC bot (#tfwiki on irc.freenode.net), and the bot notifies everyone in the channel about it.
Running this script
- First way: Download Python and run the script as is.
- Download Python and install it if you haven't got it yet.
- Copy the code in the Source section below, and save it in a text file. Give it a .py extension, preferably.
- Open a command prompt or terminal window, and run Python with the script's path as argument.
- On Windows:
C:\Python26\python.exe C:\path\to\script.py
- On Windows: Double-click the file
- You can also rename it to .pyw and double-click it if you don't want the command prompt window to appear.
- On Unix (Mac/Linux):
python /path/to/script.pt
- On Unix (Mac/Linux), you can also type simply
/path/to/script.py
if you set the executable bit on the script file beforehand (chmod +x /path/to/script.py
).
- On Windows:
- Second way (Windows only): Download the exe.
- Coming soon if there is demand.
Source
#!/usr/bin/env python # -*- coding: utf-8 -*- # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import time #, Dr. Freeman? import urllib, urllib2 # Series of tubes import hashlib # Yummy import pprint # prettyPrint import traceback # Print error stack traces import wikitools # Wiki bindings # Constants: wiki = wikitools.wiki.Wiki('http://wiki.teamfortress.com/w/api.php') refreshRatePage = 'User:WindPower/Template:RCNotifyRefreshRate' notifyUrl = 'http://irc.biringa.com/tfwikirc.php?shapass=f1ece0751b2d520c2038c121d91db7a2689f74b9' tf2Blog = 'http://www.teamfortress.com/' # Globals: refreshRate = 180 # 3 minutes by default tf2BlogHash = None # Will be populated later lastRC = -1 # Will be populated later def u(s): if type(s) is type(u''): return s if type(s) is type(''): try: return unicode(s) except: try: return unicode(s.decode('utf8')) except: try: return unicode(s.decode('windows-1252')) except: return unicode(s, errors='ignore') try: return unicode(s) except: try: return u(str(s)) except: return s def urlEncode(s): return urllib2.quote(urllib2.unquote(eval(u(s).encode('utf8').__repr__().replace('\\x', '%')))) def getNotifyResponse(params): global notifyUrl if type(params) in (type(''), type(u'')): params = u(params) else: params = u(urllib.urlencode(params)) return urllib2.urlopen(notifyUrl, params).read(-1) def updateRefreshRate(): global wiki, refreshRate, refreshRatePage try: refreshRate = int(wikitools.page.Page(wiki, refreshRatePage).getWikiText()) except: print 'Error while grabbing refresh rate; defaulting to 180s.' refreshRate = 180 def updateLastRC(last=None): global lastRC try: if last is None: lastRC = int(getNotifyResponse('requestrcid=1')) else: lastRC = int(last) except: lastRC = -1 def updateTf2Blog(): global tf2Blog, tf2BlogHash newHash = hashlib.md5() for i in urllib2.urlopen(tf2Blog): newHash.update(i) newHash = newHash.hexdigest().lower() print 'Old hash is', tf2BlogHash, '; New one is', newHash if tf2BlogHash is None: tf2BlogHash = newHash elif tf2BlogHash != newHash: tf2BlogHash = newHash print 'TF2 hash response:', getNotifyResponse('newblog=' + tf2BlogHash) updateLastRC() updateTf2Blog() print 'Started with last RCID =', lastRC print 'TF2 blog hash =', tf2BlogHash def reviewRC(rc): global lastRC if rc['rcid'] <= lastRC: return None pprint.PrettyPrinter(indent=4).pprint(rc) flag = '' if 'redirect' in rc: flag += 'R' if rc['type'] == u'new': flag += 'N' elif rc['type'] == u'log': flag += 'L' if 'minor' in rc: flag += 'm' if 'bot' in rc: flag += 'b' if not flag: flag = '-' params = { 'rcid': rc['rcid'], 'user': rc['user'], 'title': rc['title'], 'pageid': rc['pageid'], 'namespace': rc['ns'], 'newrevid': rc['revid'], 'oldrevid': rc['old_revid'], 'newsize': rc['newlen'], 'oldsize': rc['oldlen'], 'flags': flag, 'comment': rc['comment'] } return params def multiUrlEncode(allParams): s = [] c = 0 for p in allParams: for k in p.keys(): s.append(urlEncode(k) + u'_' + u(c) + u'=' + urlEncode(p[k])) c += 1 return u'&'.join(s) def checkForRCs(): rcs = wikitools.api.APIRequest(wiki, { 'action': 'query', 'list': 'recentchanges', 'rclimit': '100', 'rcprop': 'user|comment|title|ids|sizes|redirect|flags' }).query(querycontinue=False)['query']['recentchanges'] rcs.reverse() # Chronological order allParams = [] for rc in rcs: rc = reviewRC(rc) if rc is not None: allParams.append(rc) response = getNotifyResponse(multiUrlEncode(allParams)) updateLastRC(response) def main(): global refreshRate while True: try: try: print 'Checking for RCs.' checkForRCs() except: print 'Error while checking for RCs.' traceback.print_exc() try: print 'Checking for updates to TF2\'s blog.' updateTf2Blog() except KeyboardInterrupt: raise KeyboardInterrupt except: print 'Error while checking for updates to TF2\'s blog.' traceback.print_exc() print 'Sleeping for', refreshRate, 'seconds.' time.sleep(refreshRate) except KeyboardInterrupt: print 'End.' break main()