aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFulgen301 <tokmajigeorge@gmailc.om>2017-03-07 21:00:19 +0100
committerFulgen301 <tokmajigeorge@gmailc.om>2017-03-07 21:00:19 +0100
commit70b936e279154bc802ae05f4eb265ef1f4e22528 (patch)
treee324885daf8704ea8f8e78ece2cdba8cf4774ff6
parentcdafcb978b3a9047379ab4ebe5cbc31b972dbab9 (diff)
downloadpycrctrl-70b936e279154bc802ae05f4eb265ef1f4e22528.tar.gz
pycrctrl-70b936e279154bc802ae05f4eb265ef1f4e22528.zip
Rights and Updater class
-rw-r--r--pycrctrl.py181
1 files changed, 130 insertions, 51 deletions
diff --git a/pycrctrl.py b/pycrctrl.py
index e53a722..6935512 100644
--- a/pycrctrl.py
+++ b/pycrctrl.py
@@ -15,29 +15,30 @@
import sys
-if sys.version_info < (3,6):
- class ModuleNotFoundError(ImportError):
- pass
-
-import socket
+#import socket
import subprocess
import urllib.request
import urllib.error
import urllib.parse
from _thread import start_new_thread
-import inspect
+#import inspect
import queue
-import traceback
import os
import re
-import signal
+#import signal
import json
import base64
+import supybot.log
import supybot.ircmsgs as ircmsgs
from pickle import Pickler, Unpickler
from PyQt5.QtCore import *
+from time import sleep
+from platform import architecture
+from io import BytesIO
+#iostream import
+
try:
from iostream import *
except ModuleNotFoundError:
@@ -47,6 +48,8 @@ except ModuleNotFoundError:
from iostream import *
import random
+import tarfile
+from gzip import GzipFile
from time import sleep
from enum import IntEnum
@@ -57,38 +60,44 @@ from enum import IntEnum
class QString(str):
pass
-class QStringList(QObject):
+class QList(QObject):
""" QStringList """
- typeclass = str
- strlist = list()
+ list = list()
+ typeclass = None
def __init__(self, *args):
QObject.__init__(self)
- self.strlist = list(args)
+ self.list = list(args)
def __getitem__(self, name):
if type(name) != int:
raise ValueError("Wrong datatype for name!")
else:
- return self.strlist[name]
+ return self.list[name]
def __lshift__(self, other):
- if type(other) != self.typeclass:
+ if self.typeclass and not isinstance(other, self.typeclass):
raise ValueError("Wrong datatype")
else:
- self.strlist.append(other)
+ self.list.append(other)
def __call__(self):
- return self.strlist
+ return self.list
def __len__(self):
- return len(self.strlist)
+ return len(self.list)
+
+ def __repr__(self):
+ return "{}({})".format(self.__name__, self.list)
# Methods
def isEmpty(self):
- return len(self.strlist) == 0
+ return len(self.list) == 0
+
+class QStringList(QList):
+ typeclass = str
class CmdResult(IntEnum):
UnknownCommand = -1
@@ -103,6 +112,96 @@ class Capability(IntEnum):
Admin = 1
Moderator = 2
+class Updater(object):
+ parent = None
+ __current_revision = ""
+ lookuptable = {"64bit" : "amd64", "32bit" : "i386"}
+
+ def __init__(self, parent):
+ self.parent = parent
+ with open(os.path.join(self.parent.path, "snapshot.id"), "rb") as fobj:
+ self.__current_revision = fobj.read().decode("utf-8")
+ start_new_thread(self.checkForUpdates, ())
+
+ @property
+ def current_revision(self):
+ return self.__current_revision
+
+ @current_revision.setter
+ def current_revision(self, other):
+ self.__current_revision = other
+ if type(other) in [QString, str]:
+ try:
+ other = other.encode("utf-8")
+ except Exception:
+ raise TypeError("Wrong datatype!") from None
+
+ with open(os.path.join(self.parent.path, "snapshot.id"), "wb") as fobj:
+ fobj.write(other)
+
+ def checkForUpdates(self):
+ while True:
+ try:
+ site = urllib.request.urlopen("http://openclonk.org/nightly-builds").read().decode("utf-8").split("<a href='/builds/nightly/snapshots/")
+ site.remove(site[0])
+ site = [i.split("' title")[0] for i in site]
+
+ x = None
+ for i in site:
+ x = re.match(r"openclonk-snapshot-(.*)-(.*)-{}-{}-.*".format(sys.platform, self.lookuptable[architecture()[0]]), i)
+ if x:
+ rev = x.group(2)
+
+ if self.current_revision != rev:
+ self.current_revision = rev
+ self.loadNewSnapshot(x)
+
+ break
+ if not x:
+ cout << "Regex didn't match" << endl
+
+ except Exception as e:
+ supybot.log.exception(str(e))
+ finally:
+ sleep(10)
+
+ def loadNewSnapshot(self, reg):
+ supybot.log.info("Downloading snapshot...")
+ with open(os.path.join(self.parent.path, "snapshot"), "wb") as fobj:
+ fobj.write(urllib.request.urlopen("http://openclonk.org/builds/nightly/snapshots/{}".format(reg.group(0).split("' title")[0])).read())
+
+ #extract the snapshot
+ tar = tarfile.open(os.path.join(self.parent.path, "snapshot"), mode="r:bz2")
+ tar.extractall(path=self.parent.path)
+ supybot.log.info("New snapshot has been extracted.")
+
+ #get the openclonk-server autobuild
+ site = json.loads(urllib.request.urlopen("https://autobuild.openclonk.org/api/v1/jobs").read().decode("utf-8"))
+
+ for commit in site:
+ for build in commit["builds"]:
+ if re.match(r"{}-{}-.*".format(sys.platform, self.lookuptable[architecture()[0]]), build["platform"]["triplet"]):
+ for b in build["components"]:
+ reg = re.match(r".*/openclonk-server-(.*)-(.*)-(.*)-.*", str(b["path"])) #skip the engine check as the only useful one is openclonk-server
+ #if reg:
+ # cout << str(reg) << " "
+ # cout << reg.group(1) << " " << reg.group(2) << " " << reg.group(3) << " " << " :: "
+ # cout << self.current_revision << sys.platform << self.lookuptable[architecture()[0]] << endl
+ # cout << endl
+ if reg and (reg.group(1), reg.group(2), reg.group(3)) == (self.current_revision[:-3], sys.platform, self.lookuptable[architecture()[0]]):
+ supybot.log.info("Downloading openclonk-server build...")
+ buffer = BytesIO()
+ buffer.write(urllib.request.urlopen("https://autobuild.openclonk.org/static/binaries/{}".format(b["path"])).read())
+ buffer.seek(0)
+ with open(os.path.join(self.parent.path, "openclonk-server"), "wb") as fobj:
+ fobj.write(GzipFile(fileobj=buffer).read())
+
+ supybot.log.info("New openclonk-server build has been extracted.")
+ os.chmod(os.path.join(self.parent.path, "openclonk-server"), os.stat(os.path.join(self.parent.path, "openclonk-server")).st_mode | 64)
+ return True
+
+
+
class PyCRCtrl(object):
"""Server control"""
@@ -112,45 +211,37 @@ class PyCRCtrl(object):
config = {}
scenario = ""
- #prefix = "@"
commands = {}
- #engine = "clonk"
codec = None
- #commandline = "/fullscreen /lobby:300 /config:config.txt /record /faircrew"
- #path = QString()
+ path = QString()
scenlist = QStringList()
league_scenlist = QStringList()
- #channels = {}
topic = "Kein laufendes Spiel."
league = True
__state = "Lobby"
__ingamechat = "aktiviert"
- #RegExps = {
- # "lobbyStartExp" : "((?:Los geht's!|Action go!)\s*)",
- # "startExp" : r"^Start!\s*$",
- # "joinExp" : r"^Client (.+) (?:verbunden|connected)\.\s*$",
- # "leaveExp" : "^Client (.+) (?:entfernt|removed)(.*)",
- # "shutdownExp" : r"^Internetspiel ausgewertet(.*)"
- # }
-
capabilities = {}
_capa_old = {}
+ updater = None
+
def __init__(self, irc=None, path=None, config="pycrctrl.conf"):
if sys.platform == "win32":
- raise NotImplementedError("{} wird nicht unterstützt!".format(sys.platform))
+ raise NotImplementedError("{} wird nicht unterstützt!".format(sys.platform))
self.irc = irc
self.path = path
self.loadConfigFile(config)
self.loadCapabilities()
self.loadScenarioList()
- self.codec = codec = QTextCodec.codecForName(self.config.get("encoding"))
+ self.codec = QTextCodec.codecForName(self.config.get("encoding"))
self.queue = queue.Queue(5)
+ if self.config.get("engine") == "openclonk-server":
+ self.updater = Updater(self)
def __ostream__(self, ostream):
return "PyCRCtrl: commandline: {}, channel: {}, scenario: {}".format(self.commandline, self.channels["ingame"], (self.scenario if self.scenario != "" else "None"))
@@ -181,10 +272,10 @@ class PyCRCtrl(object):
return False
with open(os.path.join(self.path,"scenlist"), "rb") as fobj:
- self.scenlist.strlist = Unpickler(fobj).load()
+ self.scenlist.list = Unpickler(fobj).load()
with open(os.path.join(self.path, "scenlist.league"), "rb") as fobj:
- self.league_scenlist.strlist = Unpickler(fobj).load()
+ self.league_scenlist.list = Unpickler(fobj).load()
return True
@@ -192,7 +283,7 @@ class PyCRCtrl(object):
if self.path == None:
return False
- _capa_old = json.load(open(os.path.join(self.path, "capabilities.conf"), "r"))
+ self._capa_old = json.load(open(os.path.join(self.path, "capabilities.conf"), "r"))
return True
@@ -241,7 +332,7 @@ class PyCRCtrl(object):
if self.queue.full() == False:
self.queue.put(scenario)
- return (CmdResult.Success, 'Szenario "{}" wurde der Warteschlange hinzugefügt.'.format(scenario))
+ return (CmdResult.Success, 'Szenario "{}" wurde der Warteschlange hinzugefügt.'.format(scenario))
else:
return (CmdResult.RuntimeError, "Die Warteschlange ist voll!")
@@ -256,7 +347,7 @@ class PyCRCtrl(object):
self.capabilities = self._capa_old
self.clonk = subprocess.Popen(
- './{} {} "{}"'.format(self.config.get("engine"), self.config.get("commandline") + (" --" if type(self).__name__ == "PyOCCtrl" else " /") + ("league" if self.scenario in self.league_scenlist() else "noleague"),self.scenario),
+ './{} {} "{}"'.format(self.config.get("engine"), self.config.get("commandline") + (" --" if self.config.get("engine") == "openclonk-server" else " /") + ("league" if self.scenario in self.league_scenlist() else "noleague"),self.scenario),
0,
None,
subprocess.PIPE,
@@ -345,19 +436,7 @@ class PyCRCtrl(object):
self.clonk.stdin.close()
except Exception as e:
-#ifdef DEBUG
- if self.clonk and __debug__ and not self.clonk.stdin.closed:
- self.writeToServer(b"Fehler:")
-#endif
- tb = traceback.format_exc()
- for line in tb.splitlines():
-#ifdef DEBUG
- self.writeToServer(line)
-#endif
- try:
- cerr << line << endl
- except:
- pass
+ cerr << str(e) << endl
continue
return (CmdResult.Success, "")