def __ignored(self, content: Content, sender: ID, msg: ReliableMessage) -> bool: # check robot if sender.type in [NetworkType.ROBOT, NetworkType.STATION]: Log.info('Dialog > ignore message from another robot: %s' % sender) return True # check time now = int(time.time()) dt = now - msg.time if dt > 600: # Old message, ignore it return True # check group message if content.group is None: # not a group message return False text = content.text if text is None: raise ValueError('text content error: %s' % content) # checking '@nickname' receiver = msg.receiver at = '@%s' % self.facebook.name(identifier=receiver) if text.find(at) < 0: Log.info('ignore group message that not querying me: %s' % text) return True # TODO: remove all '@nickname' text = text.replace(at, '') content.text = text
def create_server(identifier: str, host: str, port: int = 9394) -> Station: """ Create Local Server """ identifier = ID.parse(identifier=identifier) server = Station(identifier=identifier, host=host, port=port) g_facebook.cache_user(user=server) Log.info('local station created: %s' % server) return server
def process_command(self, cmd: Command, source: tuple) -> bool: Log.info('received cmd: %s' % cmd) # noinspection PyBroadException try: return super().process_command(cmd=cmd, source=source) except Exception: traceback.print_exc() return False
def load_station(identifier: Union[ID, str], facebook: CommonFacebook) -> Station: """ Load station info from 'etc' directory :param identifier - station ID :param facebook - social network data source :return station with info from 'dims/etc/{address}/*' """ identifier = ID.parse(identifier=identifier) # check meta meta = facebook.meta(identifier=identifier) if meta is None: # load from 'etc' directory meta = Meta.parse(meta=load_station_info(identifier=identifier, filename='meta.js')) if meta is None: raise LookupError('failed to get meta for station: %s' % identifier) elif not facebook.save_meta(meta=meta, identifier=identifier): raise ValueError('meta error: %s' % meta) # check private key private_key = facebook.private_key_for_signature(identifier=identifier) if private_key is None: # load from 'etc' directory private_key = PrivateKey.parse(key=load_station_info(identifier=identifier, filename='secret.js')) if private_key is None: pass elif not facebook.save_private_key(key=private_key, identifier=identifier): raise AssertionError('failed to save private key for ID: %s, %s' % (identifier, private_key)) # check profile profile = load_station_info(identifier=identifier, filename='profile.js') if profile is None: raise LookupError('failed to get profile for station: %s' % identifier) Log.info('station profile: %s' % profile) name = profile.get('name') host = profile.get('host') port = profile.get('port') # create station if private_key is None: # remote station station = Station(identifier=identifier, host=host, port=port) else: # create profile profile = Document.create(doc_type=Document.PROFILE, identifier=identifier) profile.set_property('name', name) profile.set_property('host', host) profile.set_property('port', port) profile.sign(private_key=private_key) if not facebook.save_document(document=profile): raise AssertionError('failed to save profile: %s' % profile) # local station station = Station(identifier=identifier, host=host, port=port) facebook.cache_user(user=station) Log.info('station loaded: %s' % station) return station
def load_freshmen() -> List[ID]: freshmen = [] text = Storage.read_text(path=freshmen_file) if text is None: return freshmen array = text.splitlines() for item in array: identifier = ID.parse(identifier=item) if identifier is None: Log.error('ID error: %s' % item) elif identifier.type == NetworkType.MAIN: freshmen.append(identifier) else: # Log.error('Not a user ID: %s' % identifier) pass return freshmen
def message(self, signature: str) -> Optional[dict]: msg = self.msg_table.load(signature=signature) if msg is None: Log.error('failed to load message: %s' % signature) return None # message content content = msg.get('content') if content is None: data = msg['data'] content = Content.parse(content=json.loads(data)) assert isinstance(content, TextContent), 'content error: %s' % data msg['content'] = content.dictionary # message url link = msg.get('link') if link is None: link = msg_url(signature=signature) msg['link'] = link return msg.dictionary
def process(self, content: Content, msg: ReliableMessage) -> Optional[Content]: assert isinstance(content, TextContent), 'text content error: %s' % content sender = msg.sender nickname = self.facebook.name(identifier=sender) if self.__ignored(content=content, sender=sender, msg=msg): return None Log.debug('Received text message from %s: %s' % (nickname, content)) response = self.__query(content=content, sender=sender) if response is not None: assert isinstance(response, TextContent) question = content.text answer = response.text group = content.group if group is None: # personal message Log.debug('Dialog > %s(%s): "%s" -> "%s"' % (nickname, sender, question, answer)) else: # group message Log.debug('Group Dialog > %s(%s)@%s: "%s" -> "%s"' % (nickname, sender, group.name, question, answer)) if self.messenger.send_content(sender=None, receiver=group, content=response): text = 'Group message responded' return ReceiptCommand(message=text) else: text = 'Group message respond failed' return ReceiptCommand(message=text) return response
def load_user(identifier: str, facebook: CommonFacebook) -> User: identifier = ID.parse(identifier=identifier) # check meta try: meta = facebook.meta(identifier=identifier) except AssertionError: meta = None if meta is None: # load from 'etc' directory meta = Meta.parse(meta=load_robot_info(identifier=identifier, filename='meta.js')) if meta is None: raise LookupError('failed to get meta for robot: %s' % identifier) elif not facebook.save_meta(meta=meta, identifier=identifier): raise ValueError('meta error: %s' % meta) # check private key private_key = facebook.private_key_for_signature(identifier=identifier) if private_key is None: # load from 'etc' directory private_key = PrivateKey.parse(key=load_robot_info(identifier=identifier, filename='secret.js')) if private_key is None: raise AssertionError('private key not found for ID: %s' % identifier) elif not facebook.save_private_key(key=private_key, identifier=identifier): raise AssertionError('failed to save private key for ID: %s, %s' % (identifier, private_key)) # check profile profile = load_robot_info(identifier=identifier, filename='profile.js') if profile is None: raise LookupError('failed to get profile for robot: %s' % identifier) Log.info('robot profile: %s' % profile) name = profile.get('name') avatar = profile.get('avatar') # create profile profile = Document.create(doc_type=Document.VISA, identifier=identifier) profile.set_property('name', name) profile.set_property('avatar', avatar) profile.sign(private_key=private_key) if not facebook.save_document(document=profile): raise AssertionError('failed to save profile: %s' % profile) # create local user return facebook.user(identifier=identifier)
def process_message(self, msg: Message, source: tuple) -> bool: Log.info('received msg from %s:\n\t%s' % (source, json.dumps(msg, cls=FieldValueEncoder))) # return super().process_message(msg=msg, source=source) return True
# # Configurations # from etc.cfg_apns import apns_credentials, apns_use_sandbox, apns_topic from etc.cfg_db import base_dir, ans_reserved_records from etc.cfg_admins import administrators from etc.cfg_gsp import all_stations, local_servers from etc.cfg_gsp import station_id, station_host, station_port, station_name from etc.cfg_bots import group_assistants from etc.cfg_loader import load_station from .receptionist import Receptionist from .monitor import Monitor Log.info("local storage directory: %s" % base_dir) Storage.root = base_dir g_database = Database() """ Address Name Service ~~~~~~~~~~~~~~~~~~~~ A map for short name to ID, just like DNS """ g_ans = AddressNameServer() """ Facebook ~~~~~~~~ Barrack for cache entities
def error(self, msg: str): Log.error('%s >\t%s' % (self.__class__.__name__, msg))
def info(self, msg: str): Log.info('%s >\t%s' % (self.__class__.__name__, msg))
def warning(self, msg: str): Log.warning('Storage::%s >\t%s' % (self.__class__.__name__, msg))
def debug(self, msg: str): Log.debug('Storage::%s >\t%s' % (self.__class__.__name__, msg))
rootPath = os.path.split(curPath)[0] sys.path.append(rootPath) from libs.utils import Log from libs.utils.mtp import Server as UDPServer from station.handler import RequestHandler from station.config import g_receptionist, g_dispatcher, current_station if __name__ == '__main__': g_receptionist.start() g_dispatcher.start() # start UDP Server Log.info('>>> UDP server (%s:%d) starting ...' % (current_station.host, current_station.port)) g_udp_server = UDPServer(host=current_station.host, port=current_station.port) g_udp_server.start() # start TCP Server try: TCPServer.allow_reuse_address = True server = ThreadingTCPServer(server_address=(current_station.host, current_station.port), RequestHandlerClass=RequestHandler) Log.info('server (%s:%s) is listening...' % (current_station.host, current_station.port)) server.serve_forever() except KeyboardInterrupt as ex: Log.info('~~~~~~~~ %s' % ex)
def __query(self, content: Content, sender: ID) -> TextContent: dialog = self.dialog try: return dialog.query(content=content, sender=sender) except URLError as error: Log.error('%s' % error)
def load_naruto(): gid = ID.parse(identifier=group_naruto) Log.info('naruto group: %s' % gid) meta = Meta.parse(meta=load_robot_info(gid, 'meta.js')) g_facebook.save_meta(identifier=gid, meta=meta)
def send_command(self, cmd: Command, destination: tuple) -> Departure: Log.info('sending cmd to %s:\n\t%s' % (destination, cmd)) return super().send_command(cmd=cmd, destination=destination)
def suspend_message(self, msg: Union[InstantMessage, ReliableMessage]) -> bool: Log.info('TODO: suspending message') return True
def save_message(self, msg: InstantMessage) -> bool: Log.info('TODO: saving message') return True
def send_message(self, msg: Message, destination: tuple) -> Departure: Log.info('sending msg to %s:\n\t%s' % (destination, json.dumps(msg, cls=FieldValueEncoder))) return super().send_message(msg=msg, destination=destination)
from libs.client import Server, Terminal, ClientMessenger, ClientFacebook # # Configurations # from etc.cfg_db import base_dir, ans_reserved_records from etc.cfg_gsp import station_id, all_stations from etc.cfg_bots import group_assistants from etc.cfg_bots import group_naruto from etc.cfg_bots import lingling_id, xiaoxiao_id, chatroom_id, tokentalkteam_id from etc.cfg_loader import load_robot_info, load_station g_released = True Log.info("local storage directory: %s" % base_dir) Storage.root = base_dir """ Current Station ~~~~~~~~~~~~~~~ """ station_id = ID.parse(identifier=station_id) station_host = '127.0.0.1' # station_host = '134.175.87.98' # dimchat-gz # station_host = '124.156.108.150' # dimchat-hk station_port = 9394 g_station = Server(identifier=station_id, host=station_host, port=station_port)