summaryrefslogtreecommitdiffstats
path: root/Reaktor/IRC/asybot.py
diff options
context:
space:
mode:
authorlassulus <lassulus@googlemail.com>2014-01-13 16:44:19 +0100
committerlassulus <lassulus@googlemail.com>2014-01-13 16:44:19 +0100
commit6373abda0862359ddad91336040cfde5a252a64c (patch)
treef2a115a124e48dbc7d10281510e21c044c8cb179 /Reaktor/IRC/asybot.py
parent58ad8773eb26ca7378d4fda7689e59145868bb21 (diff)
reaktor: refactor code for moar abstraction
Diffstat (limited to 'Reaktor/IRC/asybot.py')
-rwxr-xr-xReaktor/IRC/asybot.py180
1 files changed, 0 insertions, 180 deletions
diff --git a/Reaktor/IRC/asybot.py b/Reaktor/IRC/asybot.py
deleted file mode 100755
index 8367b190..00000000
--- a/Reaktor/IRC/asybot.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#! /usr/bin/env python
-#
-# //Reaktor/IRC/asybot.py
-#
-import os
-from translate_colors import translate_colors
-def is_executable(x):
- import os
- return os.path.exists(x) and os.access(x, os.X_OK)
-
-from asynchat import async_chat as asychat
-from asyncore import loop
-from socket import AF_INET, SOCK_STREAM,gethostname
-from signal import SIGALRM, signal, alarm
-from datetime import datetime as date, timedelta
-import shlex
-from time import sleep
-from sys import exit
-from re import split, search, match
-from textwrap import TextWrapper
-import logging,logging.handlers
-import shlex
-
-config_filename = './config.py'
-
-from getconf import make_getconf
-getconf = make_getconf(config_filename)
-log = logging.getLogger('asybot')
-hdlr = logging.handlers.SysLogHandler(facility=logging.handlers.SysLogHandler.LOG_DAEMON)
-formatter = logging.Formatter( '%(filename)s: %(levelname)s: %(message)s')
-hdlr.setFormatter(formatter)
-log.addHandler(hdlr)
-logging.basicConfig(level = logging.DEBUG if getconf('debug') else logging.INFO)
-
-# s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g -- removes color codes
-
-
-class asybot(asychat):
- def __init__(self):
- asychat.__init__(self)
- self.server = getconf('irc_server')
- self.port = getconf('irc_port')
- self.channels = getconf('irc_channels')
- self.realname = getconf('irc_nickname')
- self.nickname = getconf('irc_nickname')
- self.username = getconf('irc_nickname')
- self.hostname = getconf('irc_nickname')
- self.ircname = getconf('irc_nickname')
- self.data = ''
- self.myterminator = '\r\n'
- self.set_terminator(self.myterminator.encode())
- self.create_socket(AF_INET, SOCK_STREAM)
- self.connect((self.server, self.port))
- self.wrapper = TextWrapper(subsequent_indent=" ",width=400)
-
- log.info('=> irc://%s@%s:%s/%s' % (self.nickname, self.server, self.port, self.channels))
-
- # When we don't receive data for alarm_timeout seconds then issue a
- # PING every hammer_interval seconds until kill_timeout seconds have
- # passed without a message. Any incoming message will reset alarm.
- self.alarm_timeout = getconf('irc_alarm_timeout')
- self.hammer_interval = getconf('irc_hammer_interval')
- self.kill_timeout = getconf('irc_kill_timeout')
- signal(SIGALRM, lambda signum, frame: self.alarm_handler())
- self.reset_alarm()
-
-
- def reset_alarm(self):
- self.last_activity = date.now()
- alarm(self.alarm_timeout)
-
- def alarm_handler(self):
- delta = date.now() - self.last_activity
- if delta > timedelta(seconds=self.kill_timeout):
- log.error('No data for %s. Giving up...' % delta)
- exit(2)
- else:
- log.error('No data for %s. PINGing server...' % delta)
- self.push('PING :%s' % self.nickname)
- alarm(self.hammer_interval)
-
- def collect_incoming_data(self, data):
- self.data += data.decode(encoding='UTF-8')
-
- def found_terminator(self):
- log.debug('<< %s' % self.data)
-
- message = self.data
- self.data = ''
-
- _, prefix, command, params, rest, _ = \
- split('^(?::(\S+)\s)?(\S+)((?:\s[^:]\S*)*)(?:\s:(.*))?$', message)
- params = params.split(' ')[1:]
-
- if command == 'PING':
- self.push('PONG :%s' % rest)
- log.debug("Replying to servers PING with PONG :%s" %rest)
-
- elif command == 'PRIVMSG':
- self.on_privmsg(prefix, command, params, rest)
-
- elif command == '433':
- # ERR_NICKNAMEINUSE, retry with another name
- _, nickname, int, _ = split('^.*[^0-9]([0-9]+)$', self.nickname) \
- if search('[0-9]$', self.nickname) \
- else ['', self.nickname, 0, '']
- self.nickname = nickname + str(int + 1)
- self.handle_connect()
-
- self.reset_alarm()
-
- def push(self, message):
- log.debug('>> %s' % message)
- msg = (message + self.myterminator).encode()
- log.debug('>> %s' % msg)
- asychat.push(self, msg)
-
- def handle_connect(self):
- self.push('NICK %s' % self.nickname)
- self.push('USER %s %s %s :%s' %
- (self.username, self.hostname, self.server, self.realname))
- self.push('JOIN %s' % ','.join(self.channels))
-
- def on_privmsg(self, prefix, command, params, rest):
- def PRIVMSG(text):
- for line in self.wrapper.wrap(text):
- msg = 'PRIVMSG %s :%s' % (','.join(params), line)
- log.info(msg)
- self.push(msg)
- sleep(1)
-
- def ME(text):
- PRIVMSG(('ACTION ' + text + ''))
-
- for command in getconf('commands'):
- y = match(command['pattern'], rest)
- if y:
- self.execute_command(command, y, prefix, PRIVMSG, ME)
- break
-
- def execute_command(self, command, match, prefix, PRIVMSG, ME):
- from os.path import realpath, dirname, join
- from subprocess import Popen as popen, PIPE
- from time import time
-
- #TODO: allow only commands below ./commands/
- exe = join(dirname(realpath(dirname(__file__))), command['argv'][0])
- myargv = [exe] + command['argv'][1:]
- if match.groupdict().get('args',None):
- myargv += shlex.split(match.groupdict()['args'])
-
- env = {}
- env['_from'] = prefix.split('!', 1)[0]
- env['config_filename'] = os.path.abspath(config_filename)
- start = time()
- try:
- p = popen(myargv, bufsize=1, stdout=PIPE, stderr=PIPE, env=env)
- except (OSError, Exception) as error:
- ME('brain damaged')
- log.error('OSError@%s: %s' % (myargv, error))
- return
- pid = p.pid
- for line in iter(p.stdout.readline, ''.encode()):
- try:
- PRIVMSG(translate_colors(line.decode()))
- except Exception as error:
- log.error('no send: %s' % error)
- log.debug('%s stdout: %s' % (pid, line))
- p.wait()
- elapsed = time() - start
- code = p.returncode
- log.info('command: %s -> %s in %d seconds' % (myargv, code, elapsed))
- [log.debug('%s stderr: %s' % (pid, x)) for x in p.stderr.readlines()]
-
- if code != 0:
- ME('mimimi')
-
-if __name__ == "__main__":
- asybot()
- loop()