Skip to content

Instantly share code, notes, and snippets.

@ItsMeooooooo
Forked from b1naryth1ef/q3manager.py
Created July 22, 2013 17:25
Show Gist options
  • Save ItsMeooooooo/6055784 to your computer and use it in GitHub Desktop.
Save ItsMeooooooo/6055784 to your computer and use it in GitHub Desktop.
import os, subprocess, redis, thread, json, time, daemon, re
red = redis.Redis("localhost", password=os.getenv("REDISPASS"))
class InterCom(object):
def __init__(self, id):
self.id = id
self.prefix = "server-%s-" % self.id
def getCvar(self, i):
def conf(i):
res = re.findall('".*?" is:"(.*?)\^7"', i)
if len(res):
return True
return False
i = self.get(i, need=conf)
if not i: return None
res = re.findall('".*?" is:"(.*?)\^7"', i[0]['msg'])
if len(res):
return res[0]
def get(self, cmd, lines=1, end=None, need=None):
"""
This is complicated as dicks, and probablly not perfect.
It's entirely Quake3's fault for not offering decent support for a tool
like rcon. I'm gonna fucking make sure UrTHD has decent rcon/socket support.
GODDAMNIT!
"""
i = 0 # Thread Retries
value = [] # We need an object so it can be set globally, list/dict works
running = []
def resp(a): # Function to pass to readLoop
if need:
if need(a['msg']):
value.append(a)
running.append(False)
return False
return True
value.append(a)
if len(value) >= lines:
running.append(False)
return False
if end(a['msg']):
running.append(False)
return False
return True
thread.start_new_thread(self.readLoop, (resp,))
self.cmd(cmd)
while not len(running):
time.sleep(0.05)
i += 1
if i > 25: return None
return value
def readLoop(self, f, *args):
sub = red.pubsub()
sub.subscribe(self.prefix+"read")
looping = True
for l in sub.listen():
if l['type'] == "message":
msg = json.loads(l['data'])
looping = (f(msg, *args) != False)
if not looping:
sub.unsubscribe(self.prefix+"read")
return True
def quit(self):
red.rpush(self.prefix+"write", json.dumps({"action": "quit"}))
def restart(self):
red.rpush(self.prefix+"write", json.dumps({"action": "restart"}))
def cmd(self, cmd):
red.rpush(self.prefix+"write", json.dumps({
"action": "write",
"content": cmd
}))
class Process(object):
def __init__(self, id, exe, config="server.cfg", port=27960):
self.id = id
self.exe = exe
self.config = config
self.port = port
self.running = False
self.proc = None
self.prefix = "server-%s-" % self.id
def start(self):
if self.running: return
cmd = "%s +set net_port %s +exec %s +set dedicated 2" % (self.exe, self.port, self.config)
self.proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
self.running = True
thread.start_new_thread(self.writeToThread, ())
thread.start_new_thread(self.readFromThread, ())
self.proc.wait()
self.running = False
return
def stop(self, new=False):
if not self.running: return
self.proc.kill()
def push(self, t, m):
red.publish(self.prefix+"read", json.dumps({
"type": t,
"time": time.time(),
"sid": self.id,
"msg": m}))
# Write stuff into our process
def writeToThread(self):
while self.running:
msg = red.blpop(self.prefix+"write")
try:
msg = json.loads(msg[1])
if msg['action'] == "write":
self.proc.stdin.write(msg['content']+"\n")
elif msg['action'] == "quit":
self.stop()
elif msg['action'] == "restart":
self.stop(new=True)
except Exception, e:
print "Error loading message %s (%s)" % (str(msg), e)
continue
# Read stuff from our process
def readFromThread(self):
while self.running:
line = self.proc.stdout.readline().rstrip()
print line
self.push("raw", line)
self.push("action", "exit")
if __name__ == "__main__":
# with daemon.DaemonContext():
p = Process(1, "~/Downloads/UrbanTerror42/Quake3-UrT-Ded.x86_64")
p.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment