Skip to content

Commit

Permalink
refactor message
Browse files Browse the repository at this point in the history
  • Loading branch information
swordfeng committed Nov 15, 2017
1 parent 8a67c12 commit 58832f5
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 74 deletions.
2 changes: 1 addition & 1 deletion core.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from framework import Channel, Message, User
from framework import Channel, Message, User, BaseMessageType
from ns import _, query_object, register_root, unregister_root, cacheable
from util import *
from par import *
Expand Down
62 changes: 57 additions & 5 deletions framework.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
from util import *
from ns import *
from ns import _
import plugin_manager
from uuid import uuid1
import db
Expand Down Expand Up @@ -58,19 +59,47 @@ def send_message(self, msg: 'Message', chan: 'Channel'):
def info(self):
return yamldump(self.config)

class BaseMessageType:
def ident():
raise NotImplementedError
def origin(self):
return self['origin']
def reply_to(self):
if 'reply_to' in self and type(self['reply_to']) is str:
return self['reply_to']
return None
def user(self):
if 'user' in self and type(self['user']) is str:
return self['user']
return None
def content(self):
return self['content']
def is_control(self): # override
return False
def text(self): # override
return None
class GeneralTextMessageType(BaseMessageType):
def ident():
return 'message_type_general_text'
def text(self):
if 'text' not in self.content:
return None
return self.content['text']
register_root(GeneralTextMessageType)

@cacheable
class Message(dict):
'''
Message is a json object with some helper functions.
There are some important json properties that decides
the content of the message.
content: content of the message
.text: text content
type: ident of message type
content: content of the message -- based on message type
.text: text content -- this is the default of base message type
origin: ident of origin channel
user: ident of user
reply_to: ident of user the message is replying to
'''
Cacheable = True
def query(ids):
uuid = ids[0]
data = db.get_json(join_ident(['message', uuid]))
Expand All @@ -81,12 +110,35 @@ def ident(self=None):
return 'message'
return join_ident(['message', self.uuid])

def new(origin, reply_to=None, user=None, message_type=GeneralTextMessageType, **content):
assert_ident(origin)
if 'content' in content:
content = content['content']
data = {
'type': message_type.ident(),
'origin': origin,
'content': content
}
if reply_to is not None:
assert_ident(reply_to)
data['reply_to'] = reply_to
if user is not None:
assert_ident(user)
data['user'] = user
msg = Message(data)
msg.persist()
return msg

def __init__(self, data={}, uuid=None):
super().__init__(data)
if uuid == None:
if uuid is None:
uuid = str(uuid1())
self.uuid = uuid
self.persist()
self.message_type = _(self['type'])
def __getattr__(self, name):
if hasattr(self.message_type, name):
return getattr(self.message_type, name)(self)
raise AttributeError
def on_uncache(self):
self.persist()
def persist(self):
Expand Down
4 changes: 2 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import secret

stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setLevel(logging.WARN)
logging.basicConfig(level=logging.INFO, handlers=[stdout_handler])
stdout_handler.setLevel(logging.DEBUG)
logging.basicConfig(level=logging.DEBUG, handlers=[stdout_handler])

logger = logging.getLogger('main')

Expand Down
12 changes: 2 additions & 10 deletions plugins/echo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,9 @@ class Echo(Channel):
def ident(self):
return 'echo'
def send_message(self, msg, chan):
if 'content' not in msg:
if msg.text is None:
return
if msg['origin'] == self.ident():
return
if msg['origin'] != chan.ident():
return
rep = Message({
'content': msg['content'],
'origin': self.ident(),
'reply_to': msg.ident()
})
rep = Message.new(self.ident(), reply_to=msg.ident(), text=msg.text)
chan.send_message(rep, self)

def initialize():
Expand Down
5 changes: 1 addition & 4 deletions plugins/log/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ def ident(self):
def kill(self):
logging.getLogger().removeHandler(self.handler)
def on_log(self, log):
log_msg = Message({
'content': {'text': log},
'origin': self.ident()
})
log_msg = Message.new(text=log, origin=self.ident())
self.on_receive(log_msg)
def send_message(self, msg, chan):
return
Expand Down
11 changes: 3 additions & 8 deletions plugins/repeater/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ def __init__(self):
def ident(self):
return 'repeater'
def send_message(self, msg, chan):
if 'content' not in msg or 'text' not in msg['content'] or msg['origin'] != chan.ident():
if msg.text is None or msg.origin != chan.ident():
return
ident = chan.ident()
text = msg['content']['text']
text = msg.text
if ident not in self.last_msgs:
self.last_msgs[ident] = {'last': '', 'count': 0}
item = self.last_msgs[ident]
Expand All @@ -21,12 +21,7 @@ def send_message(self, msg, chan):
else:
item['count'] += 1
if item['count'] == 3:
resp = Message({
'content': {
'text': text
},
'origin': self.ident()
})
resp = Message.new(self.ident(), text=text)
chan.send_message(resp, self)

def initialize():
Expand Down
10 changes: 5 additions & 5 deletions plugins/simple_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ def info(cmds, msg, chan):
if len(cmds) == 0:
item = msg.ident()
elif cmds[0] == '$me':
item = msg['user']
item = msg.user
elif cmds[0] == '$chan':
item = chan.ident()
elif cmds[0] == '$rep':
item = msg['reply_to']
item = msg.reply_to
else:
item = cmds[0]
obj = query_object(item)
Expand All @@ -37,7 +37,7 @@ def info(cmds, msg, chan):
return get_info(obj)

def plugin(cmds, msg, chan):
_('permission:SuperUser').assertion(msg['user'])
_('permission:SuperUser').assertion(msg.user)
if cmds[0] == 'load':
_('pm').load(cmds[1])
return 'loaded'
Expand All @@ -57,7 +57,7 @@ def plugin(cmds, msg, chan):
return 'unknown'

def listener(cmds, msg, chan):
_('permission:SuperUser').assertion(msg['user']) # todo: ChannelAdmin
_('permission:SuperUser').assertion(msg.user) # todo: ChannelAdmin
listenee = _(cmds[1])
if cmds[0] == 'add':
chan.add_listener(listenee)
Expand All @@ -69,7 +69,7 @@ def listener(cmds, msg, chan):
return 'unknown'

def listen_to(cmds, msg, chan):
_('permission:SuperUser').assertion(msg['user'])
_('permission:SuperUser').assertion(msg.user)
target = _(cmds[1])
if cmds[0] == 'add':
target.add_listener(chan)
Expand Down
14 changes: 4 additions & 10 deletions plugins/simple_manager/general_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ def __init__(self):
def ident(self):
return self.name
def send_message(self, msg, chan):
if 'content' not in msg or 'text' not in msg['content'] or msg['origin'] != chan.ident():
if msg.text is None or msg.origin != chan.ident():
return
cmd = msg['content']['text']
cmd = msg.text
if not cmd.startswith(self.prompt):
return
cmds = cmd[len(self.prompt):].strip().split(' ')
Expand All @@ -32,14 +32,8 @@ def send_message(self, msg, chan):
except:
self.logger.warning(f'Unhandled command: {cmd}', exc_info=True)
result = 'Error happened when processing the command'
rep = Message({
'content': {
'text': result
},
'reply_to': msg.ident(),
'origin': self.ident()
})
chan.send_message(rep, self)
resp = Message.new(self.ident(), reply_to=msg.ident(), text=result)
chan.send_message(resp, self)
def on_register_root(self):
query_object('global_hook').add_listener(self)
def on_unregister_root(self):
Expand Down
9 changes: 4 additions & 5 deletions plugins/simple_manager/perm.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,22 +280,22 @@ def exec(self, cmd: str):
return False

def addrole(cmds, msg, chan):
_('permission:SuperUser').assertion(msg['user'])
_('permission:SuperUser').assertion(msg.user)
cmd = 'addrole ' + ' '.join(cmds)
return str(PermissionNS.instance().exec(cmd))

def delrole(cmds, msg, chan):
_('permission:SuperUser').assertion(msg['user'])
_('permission:SuperUser').assertion(msg.user)
cmd = 'delrole ' + ' '.join(cmds)
return str(PermissionNS.instance().exec(cmd))

def assign(cmds, msg, chan):
_('permission:SuperUser').assertion(msg['user'])
_('permission:SuperUser').assertion(msg.user)
cmd = 'assign ' + ' '.join(cmds)
return str(PermissionNS.instance().exec(cmd))

def revoke(cmds, msg, chan):
_('permission:SuperUser').assertion(msg['user'])
_('permission:SuperUser').assertion(msg.user)
cmd = 'revoke ' + ' '.join(cmds)
return str(PermissionNS.instance().exec(cmd))

Expand All @@ -305,4 +305,3 @@ def test(cmds, msg, chan):

def info(cmds, msg, chan):
return _(f'permission:{cmds[0]}').info()

35 changes: 12 additions & 23 deletions plugins/telegram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ async def worker(self):
msg = telegram2message(update, self)
logger.debug(f'receive: {msg}')
if msg is not None:
chan = query_object(msg['origin'])
chan = _(msg.origin)
chan.on_receive(msg)
except telegram.error.TimedOut:
logger.debug('poll timeout')
Expand All @@ -98,21 +98,16 @@ def ident(self):
return f'{self.bot.ident()}:chan:{self.chat_id}'
def send_message(self, msg: Message, chan: Channel):
logger.debug(f'{self.ident()} send: {msg}')
if 'content' not in msg:
# non-chat message
if msg.is_control:
return
if 'file' in msg['content']:
pass # todo: senddocuemnt
elif 'image' in msg['content']:
pass # todo: sendphoto
elif 'text' in msg['content']:
if len(msg['content']['text']) == 0:
if msg.text is not None:
if len(msg.text) == 0:
return
kw = {'chat_id': self.chat_id, 'text': msg['content']['text']}
if 'user' in msg:
kw['text'] = f'[{msg["user"]}] {kw["text"]}'
if 'reply_to' in msg:
rep_msg = query_object(msg['reply_to'])
kw = {'chat_id': self.chat_id, 'text': msg.text}
if msg.user:
kw['text'] = f'[{_(msg.user).display_name()}] {kw["text"]}'
if msg.reply_to:
rep_msg = query_object(msg.reply_to)
ident = rep_msg.get_alias(f'telegram:{self.bot.bot_id}:message')
if ident is not None:
kw['reply_to_message_id'] = int(split_ident(ident)[3])
Expand Down Expand Up @@ -167,20 +162,14 @@ def update(u: telegram.User):
def telegram2message(update: telegram.Update, bot: TelegramBot):
if update.message:
tm = update.message
print(tm.to_json())
user = TelegramUser.update(tm.from_user)
# todo: non-text
if not tm.text:
return None
msg = Message({
'content': {
'text': tm.text
},
'origin': f'{bot.ident()}:chan:{tm.chat.id}',
'user': user.ident()
})
reply_to = None
if tm.reply_to_message:
msg['reply_to'] = Message.query_alias(f'telegram:{bot.bot_id}:message:{tm.reply_to_message.message_id}')
reply_to = Message.query_alias(f'telegram:{bot.bot_id}:message:{tm.reply_to_message.message_id}')
msg = Message.new(f'{bot.ident()}:chan:{tm.chat.id}', user=user.ident(), text=tm.text, reply_to=reply_to)
msg.add_alias(f'telegram:{bot.bot_id}:message:{tm.message_id}')
return msg
return None
2 changes: 1 addition & 1 deletion util.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ def head_ident(ident: str):
return ident[:sep]

def yamldump(obj):
return yaml.dump(obj, default_flow_style=False, allow_unicode=True)
return yaml.dump(obj, default_flow_style=False, allow_unicode=True).strip()

0 comments on commit 58832f5

Please sign in to comment.