#!/usr/bin/env python import config, logging, requests, sys, time from lxml import etree from gi.repository import Notify def init_logging(): global logger logger = logging.getLogger(__name__) logger.setLevel(config.LOGLEVEL) # create console handler and set level to debug ch = logging.StreamHandler() ch.setLevel(config.LOGLEVEL) # create formatter formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') # add formatter to ch ch.setFormatter(formatter) # add ch to logger logger.addHandler(ch) init_logging() def login(): global s s = requests.Session() logger.info('Logging in as %s' % config.USERNAME) r = s.post('https://secure.runescape.com/m=weblogin/login.ws', data={ 'username': config.USERNAME, 'password': config.PASSWORD, 'mod': 'www', 'dest': '' }) if 'recaptcha' in r.text: raise Error("Login encountered reCAPTCHA. Log in with a browser and try again.") logger.info("'Authorising' toolbar") s.post('http://services.runescape.com/m=toolbar/authorise.ws', data='remember=remember&submit=login') s.cookies['toolbar_activity_filter'] = 'AQAOACkAAAAqAAAAGAAAAAoAAAAXAAAAAAAAABYAAAABAAAAKAAAAAsAAAACAAAAAwAAAAwAAAAUAAA=' login() checks = [ { 'name': 'D&D', 'url': 'http://services.runescape.com/m=toolbar/activities.ws', 'last': [], }, { 'name': 'GE', 'url': 'http://services.runescape.com/m=toolbar/geupdate.ws', 'last': [], }, ] def load(toload, tryrelog=True): logger.info("Loading %s (%s)" % (toload['name'], toload['url'])) r = s.get(toload['url']) try: xml = etree.fromstring(r.content) except etree.XMLSyntaxError as e: logger.info("Parse error (%s)" % e.args) if tryrelog: login() return load(toload, tryrelog=False) else: raise e items = xml.xpath('//MENU_ITEM') toload['last'] = [next(item.iter('CAPTION')).text for item in items] logger.debug('Loaded "%s"' % toload['last']) def check(tocheck): thislast = tocheck['last'] load(tocheck) for caption in tocheck['last']: if ' 0%' in caption: logger.debug('Skipping "%s", contains 0%%' % caption) else: logger.debug('Checking for "%s" in last' % caption) if caption not in thislast: notify('RuneScape %s notification' % tocheck['name'], caption) else: logger.debug('"%s" found in last, skipping notification' % caption) Notify.init('RuneScape Notifier') def notify(summary, body): logger.info("Sending %s: %s" % (summary, body)) n = Notify.Notification.new(summary, body, config.ICON) n.show() logger.info("Preloading checks") list(map(load, checks)) while True: logger.info("Sleeping for %d seconds" % config.SLEEP) time.sleep(config.SLEEP) try: list(map(check, checks)) except requests.exceptions.ConnectionError: logger.warning("Could not connect, trying again later.")