User:WindPower/RCNotify.py

From Team Fortress Wiki
< User:WindPower
Revision as of 23:44, 30 August 2010 by WindPower (talk | contribs) (Running this script: Handy tip @ Pilk)
Jump to: navigation, search

About this script

This is a Python script that:

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).
  • 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()