aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pycrctrl.py155
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)