diff options
-rw-r--r-- | .gitconfig | 1 | ||||
-rw-r--r-- | chat_iface.py | 71 | ||||
-rw-r--r-- | irc_iface.py | 43 | ||||
-rw-r--r-- | rschat.ini | 10 | ||||
-rwxr-xr-x | rschat.py | 72 |
5 files changed, 197 insertions, 0 deletions
diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..6c30242 --- /dev/null +++ b/.gitconfig @@ -0,0 +1 @@ +/rschat.ini diff --git a/chat_iface.py b/chat_iface.py new file mode 100644 index 0000000..c1fbc29 --- /dev/null +++ b/chat_iface.py @@ -0,0 +1,71 @@ +from __future__ import unicode_literals +import logging +import selenium.webdriver + +# set WebElement hash to default to use set(x) +selenium.webdriver.remote.webelement.WebElement.__hash__ = lambda self: hash(self.id) + +def diff(a, b): + b = set(b) + return [aa for aa in a if aa not in b] + +logger = logging.getLogger('rschat.' + __name__) + +class ChatInterface(): + def __init__(self, chat_type, username, password): + self.chat_type = chat_type + self.username = username + self.password = password + self.browser = None + + def __enter__(self): + logger.info('Starting webdriver') + options = selenium.webdriver.ChromeOptions() + options.add_argument('--disable-file-system') + + self.browser = selenium.webdriver.Chrome('/usr/lib64/chromium-browser/chromedriver', chrome_options=options) + + self.browser.implicitly_wait(30) + + logger.debug('Navigating to companion app') + self.browser.get('http://www.runescape.com/companion/comapp.ws') + + logger.debug('Switching to iframe') + self.browser.switch_to_frame(self.browser.find_element_by_tag_name('iframe')) + +# login + logger.debug('Logging in as %s' % self.username) + self.browser.find_element_by_id('username').send_keys(self.username) + self.browser.find_element_by_id('password').send_keys(self.password) + self.browser.find_element_by_tag_name('form').submit() + +# decline remember login + logger.debug('Declining remember login') + self.browser.find_element_by_partial_link_text('No').click() + + logger.debug('Switching to %s chat' % self.chat_type) + self.browser.find_element_by_css_selector('.chat-nav .icon-%schat' % self.chat_type).click() + + self.browser.implicitly_wait(0) + + return self + + lastmsgs = [] + + def send(self, line): + self.browser.find_element_by_id('message').send_keys(line) + self.browser.find_element_by_tag_name('form').submit() + + def poll(self): + try: + allmsgs = self.browser.find_elements_by_css_selector('#content-%s-chat .message:not(.my-message) .message-content' % self.chat_type) + newmsgs = diff(allmsgs, self.lastmsgs) + + self.lastmsgs = allmsgs + + return [(e.find_element_by_class_name('author').text.replace(' -', ''), e.find_element_by_tag_name('p').text) for e in newmsgs] + except selenium.webdriver.common.exceptions.NoSuchElementException: + pass + + def __exit__(self, *_): + self.browser.quit() diff --git a/irc_iface.py b/irc_iface.py new file mode 100644 index 0000000..c70866c --- /dev/null +++ b/irc_iface.py @@ -0,0 +1,43 @@ +from __future__ import unicode_literals +import irc.client +import logging + +logger = logging.getLogger('rschat.' + __name__) + +class IRCInterface(irc.client.SimpleIRCClient): + def __init__(self, server, port, nick, channel): + logger.debug("Initializing IRCInterface") + super(self.__class__, self).__init__() + self.server = server + self.port = port + self.nick = nick + self.channel = channel + self.queue = [] + + def __enter__(self): + logger.info("Connecting to %s:%s as %s" % (self.server, self.port, self.nick)) + self.connect(self.server, self.port, self.nick) + return self + + def on_welcome(self, connection, _): + logger.info("Connected, joining %s" % self.channel) + connection.join(self.channel) + + def send(self, line): + self.connection.privmsg(self.channel, line) + + def on_pubmsg(self, _, event): + source = event.source + self.queue.append((source[:source.index('!')], event.arguments[0])) + + def poll(self): + self.ircobj.process_once() + queue = self.queue + self.queue = [] + return queue + + def send_raw(self, *args, **kwargs): + return self.connection.send_raw(*args, **kwargs) + + def __exit__(self, *_): + self.connection.quit() diff --git a/rschat.ini b/rschat.ini new file mode 100644 index 0000000..53737fc --- /dev/null +++ b/rschat.ini @@ -0,0 +1,10 @@ +[IRC] +#server = irc.freenode.net +#port = 6667 +#nick = RSChat +#channel = #rswiki-cc + +[Chat] +#type = clan +user = +pass = diff --git a/rschat.py b/rschat.py new file mode 100755 index 0000000..b63fc48 --- /dev/null +++ b/rschat.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 + +from __future__ import unicode_literals, with_statement + +VERSION=(0, 1, 0) + +from chat_iface import ChatInterface +from irc_iface import IRCInterface +try: + from configparser import SafeConfigParser +except ImportError: + from ConfigParser import SafeConfigParser +import logging +import os +import select +import sys +import time + +logger = logging.getLogger('rschat') +logger.setLevel(logging.DEBUG) +ch = logging.StreamHandler() +ch.setLevel(logging.DEBUG) +formatter = logging.Formatter('<%(levelno)s>[%(asctime)s] %(name)s:%(funcName)s: %(message)s') +ch.setFormatter(formatter) +logger.addHandler(ch) + +logger.debug("Starting rschat version %d.%d.%d" % VERSION) + +try: + xdg_config_home = os.environ['XDG_CONFIG_HOME'] +except KeyError: + xdg_config_home = os.path.expanduser('~/.config') + +try: + xdg_config_dirs = os.environ['XDG_CONFIG_DIRS'].split(':') +except KeyError: + xdg_config_dirs = ['/etc/xdg'] + +cfg = SafeConfigParser({ + 'server': 'chat.freenode.net', + 'port': 6667, + 'nick': 'RSWBot', + 'channel': '#rswiki-cc', + 'chat': 'clan', +}) + +cfg.read([fldr + '/rschat.ini' for fldr in [xdg_config_home] + xdg_config_dirs + ['.']]) + +with IRCInterface(cfg.get('IRC', 'server'), cfg.get('IRC', 'port', raw=True), cfg.get('IRC', 'nick'), cfg.get('IRC', 'channel')) as irc, \ + ChatInterface(cfg.get('Chat', 'Chat'), cfg.get('Chat', 'user'), cfg.get('Chat', 'pass')) as chat: + + logger.debug('Primary initialization complete, processing IRC input') + + irc.poll() + + # poll for new messages + logger.info('Initialization seems complete, starting main loop') + + def poll(recv, send): + msgs = recv.poll() + if msgs: + list(map(send.send, ['%s: %s' % msg for msg in msgs])) + + while True: + time.sleep(0.1) + + # raw IRC commands + if select.select([sys.stdin], [], [], 0)[0]: + irc.send_raw(sys.stdin.readline()) + + poll(irc, chat) + poll(chat, irc) |