Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import json
- from channels.channel import Group
- from . import __version__
- from .exceptions import *
- from .signals import user_connect, user_disconnect, keepalive
- from .utils import serializable
- class Msg:
- def __init__(self, entity=None, data={}, action=None, status='success', msg='', cmd_id=None):
- self.entity = entity
- self.data = data
- self.action = action
- self.status = status
- self.msg = msg
- self.cmd_id = cmd_id
- def json(self):
- return json.dumps(serializable({'entity': self.entity, 'data': self.data, 'action': self.action,
- 'status': self.status, 'msg': self.msg, 'cmd_id': self.cmd_id}))
- class RegisterEngine(type):
- def __init__(cls, name, bases, attrs):
- if not getattr(cls, 'ACTIONS', None):
- setattr(cls, 'ACTIONS', {})
- for key, val in attrs.items():
- action = getattr(val, 'action', None)
- if action is not None:
- cls.ACTIONS[key] = action
- if not name == 'Engine' and len(cls.ACTIONS.keys()):
- cls.ACTIONS_CLASSES.append(cls)
- def action(*args):
- def decorator(f):
- f.action = tuple(args)
- return f
- return decorator
- class Engine(metaclass=RegisterEngine):
- ACTIONS_CLASSES = []
- def __init__(self, *args, **kwargs):
- self.message = args[0]
- super().__init__()
- @classmethod
- def get_actions(cls):
- actions = {}
- for c in cls.ACTIONS_CLASSES:
- actions.update(c.ACTIONS)
- return actions
- @classmethod
- def get_actions_json(cls):
- actions = {}
- for c in cls.ACTIONS_CLASSES:
- actions.update(c.ACTIONS)
- return json.dumps(actions)
- @classmethod
- def connect(cls, message):
- # send ACK
- msg = Msg(entity='--SERVICE--', action='init',
- data={'version': __version__, 'actions': cls.get_actions()}).json()
- message.reply_channel.send({'text': msg})
- user_connect.send(sender=message, user=message.user)
- @classmethod
- def disconnect(cls, message):
- user_disconnect.send(sender=message, user=message.user)
- @classmethod
- def keepalive(cls, message):
- keepalive.send(sender=message)
- @classmethod
- def dispatch(cls, message):
- try:
- msg_content = json.loads(message.content['text'])
- action = msg_content.get('action', None)
- if not action:
- raise BadMessage('Action not specified.')
- engine = None
- for c in cls.ACTIONS_CLASSES:
- if action in c.ACTIONS:
- engine = c(message)
- if not engine:
- raise BadMessage('Action method "{}" not found in registry.'.format(action))
- _method = engine.ACTIONS.get(action, None)
- if _method is None:
- raise BadMessage('Action method "{}" not implemented.'.format(action))
- args = ()
- for a in _method:
- arg = msg_content.get(a, None)
- if not arg:
- raise BadMessage('Argument "{}" of method "{}" not specified.'.format(a, action))
- args += (arg,)
- method = getattr(engine, action)
- return method(*args)
- except Exception as e:
- print(e)
- message.reply_channel.send({'text': e.__repr__()})
- def add(self, group):
- Group(group).add(self.message.reply_channel)
- def discard(self, group):
- Group(group).discard(self.message.reply_channel)
- def send(self, msg, to=None):
- if not to:
- to = self.message.reply_channel
- to.send({'text': msg.json() if isinstance(msg, Msg) else msg})
- def send_to_group(self, group, msg):
- self.send(msg, to=Group(group))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement