NDOJ/judge/event_poster_ws.py

87 lines
2.3 KiB
Python
Raw Permalink Normal View History

2020-01-21 06:35:58 +00:00
import json
import socket
import threading
from django.conf import settings
from websocket import WebSocketException, create_connection
2022-05-14 17:57:27 +00:00
__all__ = ["EventPostingError", "EventPoster", "post", "last"]
2020-01-21 06:35:58 +00:00
_local = threading.local()
class EventPostingError(RuntimeError):
pass
class EventPoster(object):
def __init__(self):
self._connect()
def _connect(self):
self._conn = create_connection(settings.EVENT_DAEMON_POST)
if settings.EVENT_DAEMON_KEY is not None:
2022-05-14 17:57:27 +00:00
self._conn.send(
json.dumps({"command": "auth", "key": settings.EVENT_DAEMON_KEY})
)
2020-01-21 06:35:58 +00:00
resp = json.loads(self._conn.recv())
2022-05-14 17:57:27 +00:00
if resp["status"] == "error":
raise EventPostingError(resp["code"])
2020-01-21 06:35:58 +00:00
def post(self, channel, message, tries=0):
try:
2022-05-14 17:57:27 +00:00
self._conn.send(
json.dumps({"command": "post", "channel": channel, "message": message})
)
2020-01-21 06:35:58 +00:00
resp = json.loads(self._conn.recv())
2022-05-14 17:57:27 +00:00
if resp["status"] == "error":
raise EventPostingError(resp["code"])
2020-01-21 06:35:58 +00:00
else:
2022-05-14 17:57:27 +00:00
return resp["id"]
2020-01-21 06:35:58 +00:00
except WebSocketException:
if tries > 10:
raise
self._connect()
return self.post(channel, message, tries + 1)
def last(self, tries=0):
try:
self._conn.send('{"command": "last-msg"}')
resp = json.loads(self._conn.recv())
2022-05-14 17:57:27 +00:00
if resp["status"] == "error":
raise EventPostingError(resp["code"])
2020-01-21 06:35:58 +00:00
else:
2022-05-14 17:57:27 +00:00
return resp["id"]
2020-01-21 06:35:58 +00:00
except WebSocketException:
if tries > 10:
raise
self._connect()
return self.last(tries + 1)
def _get_poster():
2022-05-14 17:57:27 +00:00
if "poster" not in _local.__dict__:
2020-01-21 06:35:58 +00:00
_local.poster = EventPoster()
return _local.poster
def post(channel, message):
try:
return _get_poster().post(channel, message)
except (WebSocketException, socket.error):
try:
del _local.poster
except AttributeError:
pass
return 0
def last():
try:
return _get_poster().last()
except (WebSocketException, socket.error):
try:
del _local.poster
except AttributeError:
pass
return 0