diff options
Diffstat (limited to 'pycrctrl.py')
| -rw-r--r-- | pycrctrl.py | 155 |
1 files changed, 139 insertions, 16 deletions
diff --git a/pycrctrl.py b/pycrctrl.py index 06dcb92..0b2f731 100644 --- a/pycrctrl.py +++ b/pycrctrl.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # -*- coding:utf-8 -*- #Copyright (c) 2017, George Tokmaji @@ -14,9 +15,10 @@ #ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF #OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -import sys import os +sys = os.sys +import socket import subprocess import queue from _thread import start_new_thread @@ -29,7 +31,23 @@ from io import BytesIO import logging import urllib.request -import supybot.ircmsgs as ircmsgs + +class _ircmsgs(object): + @staticmethod + def msg(cmd, msg, encoding : str = "utf-8"): + return b"%b %b" % tuple((i.encode(encoding) if hasattr(i, "encode") else i) for i in [cmd, msg]) + + @staticmethod + def topic(channel : str, text : str, encoding : str = "utf-8"): + return _ircmsgs.msg(b"TOPIC", "{} {}".format(channel, text, encoding)) + + @staticmethod + def privmsg(to : str, text : str, encoding : str = "utf-8"): + return _ircmsgs.msg(b"PRIVMSG", "{} {}".format(to, text, encoding)) +try: + import supybot.ircmsgs as ircmsgs +except ImportError: + ircmsgs = _ircmsgs import random @@ -116,10 +134,10 @@ class Updater(object): break if not x: - self.parent.log.error("Updater: Update regular expression doesn't match!") + self.parent.log.error("Updater.checkForUpdates: Regular expression doesn't match!") except Exception as e: - cerr << str(e) << endl + self.parent.log.exception(str(e)) finally: sleep(10) @@ -252,29 +270,35 @@ class PyCRCtrl(object): elif not os.path.exists(conf): c = """[General] -UseLogfile=true Prefix=@ [Clonk] Engine=clonk Encoding=utf-8 -Commandline=/fullscreen /lobby:300 /config:config.txt /record /faircrew +Commandline=/fullscreen /lobby:300 /record /faircrew Autohost=false [IRC] -Ingamechat=true - - [Channels] - Parent="#clonk-SGGP" - Ingame="#clonk-SGGP-ingame" +Ingamechat=false + +[Channels] +Parent= +Ingame= [Updater] Enabled=false - [Addresses] - snapshotList=http://openclonk.org/nightly-builds - snapshotDownload=http://openclonk.org/builds/nightly/snapshots/{} - autobuildList=https://autobuild.openclonk.org/api/v1/jobs - autobuildAddress=https://autobuild.openclonk.org/static/binaries/{} +BinaryName= +SplitString= + +[Addresses] +snapshotList=http://openclonk.org/nightly-builds +snapshotDownload=http://openclonk.org/builds/nightly/snapshots/{} +autobuildList=https://autobuild.openclonk.org/api/v1/jobs +autobuildAddress=https://autobuild.openclonk.org/static/binaries/{} + +[Logging] +File=pycrctrl.log +Level=INFO [RegExps] LobbyStart=((?:Los geht's!|Action go!)\\s*) @@ -591,3 +615,102 @@ Snapshot=openclonk-snapshot-(.*)-(.*)-{}-{}-.""" self.setTopic("Kein laufendes Spiel.") logging.shutdown() self.shutdowned = True + +class PyCRCtrlIRC(object): + parent = PyCRCtrl = None + irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + encoding = "utf-8" + + def setParent(parent): + self.parent = parent + self.encoding = parent.config["Clonk"]["Encoding"] + + def sendMsg(self, msg : bytes): + if type(msg) != bytes: + msg = str(msg).encode(self.encoding, "replace") + try: + self.irc.send(msg + b"\r") + except (socket.error, socket.timeout, OSError): + self.reconnect() + self.sendMsg(msg) + + def connect(self): + try: + self.irc.connect((self.parent.config["IRC"]["Server"], self.parent.config["IRC"]["Port"])) + except (socket.error, socket.timeout, OSError): + self.reconnect() + return + + nick = self.parent.config["IRC"]["Nick"] + self.sendMsg(ircmsgs.msg("USER", "{nick} {nick} {nick} :PyCRCtrl".format(nick=nick), self.encoding)) + self.sendMsg(ircmsgs.msg("NICK", "{}".format(nick), self.encoding)) # security + + try: + self.irc.sendMsg(ircmsgs.msg("PASSWORD", "{}".format(self.parent.config["IRC"]["Password"]), self.encoding)) + except KeyError: + pass + + self.parent.log.info("Successfully connected to {}".format(self.parent.config["IRC"]["Server"])) + + start_new_thread(self.checkForMessages, ()) + + def reconnect(self): + sleep(10) + start_new_thread(self.connect, ()) + try: + self.irc.close() + except Exception: + pass + del self.irc + self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + start_new_thread(self.connect, ()) + + def checkForMessages(self): + while True: + try: + text = self.irc.recv(512).decode(self.encoding, "replace") + except (socket.error, socket.timeout, OSError): + self.reconnect() + return + + x = re.match(r"^(?:[:](\S+) )?(\S+)(?: (?!:)(.+?))?(?: [:](.+))?$") + if not x: + continue + + nick, command, channel, msg = x.group(1), x.group(2), x.group(3), x.group(4) + + if command == "PING": + self.sendMsg(ircmsgs.msg("PONG", msg)) + + elif command == "PRIVMSG": + y = re.match(r"{}(\w+) (.*)".format(self.parent.config["General"]["Prefix"])) + if not y: + continue + + func, args = y.group(1), y.group(2) + if func in self.parent.commands: + self.parent.log.info("{} called by {}".format(func, nick)) + try: + self.sendMsg(ircmsgs.privmsg(self.parent.commands[func](args))) + except Exception as e: + self.parent.log.exception(e.args[0]) + +if __name__ == "__main__": + ircmsgs = _ircmsgs + + irc = PyCRCtrlIRC() + ctrl = PyCRCtrl(irc, sys.argv[1]) + ctrl.addCommand(ctrl.start, "start") + ctrl.addCommand(ctrl.stop, "stop") + ctrl.addCommand(ctrl.host, "host") + ctrl.addCommand(ctrl.displayQueue, "queue") + ctrl.addCommand(ctrl.help, "help") + ctrl.addCommand(ctrl.list, "list") + ctrl.addCommand(ctrl.ircCommands, "irc") + irc.setParent(ctrl) + irc.connect() + while True: + try: + sleep(600) + except KeyboardInterrupt: + sys.exit(0) |
