From 5c43cf3a2fca03baf002e9bc6a3ed930d6cf8589 Mon Sep 17 00:00:00 2001 From: Vishwas Mittal Date: Mon, 25 Jun 2018 07:43:43 +0530 Subject: [PATCH 1/3] minor changes --- new_app/action.py | 130 ++++++++++++++++++------------------- new_app/bot.py | 2 +- new_app/brain.py | 32 ++++++++- new_app/context_manager.py | 5 +- 4 files changed, 100 insertions(+), 69 deletions(-) diff --git a/new_app/action.py b/new_app/action.py index e71f05c..f623fad 100644 --- a/new_app/action.py +++ b/new_app/action.py @@ -13,7 +13,7 @@ def __init__(self, trigger, kind, callback=None): self.trigger = trigger # self.complex_trigger = complex_trigger self.kind = kind.upper() - self.next_action_ids = set() + # self.next_action_ids = set() self.next_actions = set() self.callback = callback or self.none_callback @@ -38,73 +38,73 @@ def add_actions(self, actions): for act in _actions: self.next_actions.add(act) - self.next_action_ids.add(act.id) + # self.next_action_ids.add(act.id) @staticmethod def none_callback(*args, **kwargs): return None # def export_action(self): - # # self.handler = json.dumps - # # action_dict = dict() - # # # print(self.next_actions) - # # print(self) - # # for a in self.next_actions: - # # print(a) - # # print(a.next_actions) - # action_dict = { - # 'text': self.trigger, - # 'kind': self.kind, - # 'handler': { - # 'module': self.callback.__module__, - # 'name': self.callback.__name__ - # }, - # 'next_actions': [next_action.export_action() for next_action in self.next_actions] - # } - # return action_dict - # - # @staticmethod - # def is_next_actions_correct(next_actions): - # if type(next_actions) == list: - # for action in next_actions: - # # if isinstance(action, Action): - # if not type(action) == Action: - # return False - # return True - # else: - # return False - # - # @staticmethod - # def import_action(action_dict): - # if type(action_dict) is not dict: - # raise TypeError("'action_dict' must be a dict") - # else: - # next_actions = [Action.import_action(action) for action in action_dict.get('next_actions', [])] - # action = Action(action_dict['trigger'], - # action_dict.get('type') or 'M', - # handler=Action.get_handler(action_dict.get('handler', None))) - # action.add_actions(next_actions) - # return action - # - # @staticmethod - # def get_handler(handler): - # """ - # To obtain proper handler for the action - # :param None/function/dict handler: - # Returns handler if it is None or a function. - # If dict is provided, it loads the function from the `module` and `name` of function provided - # :return: None or function - # """ - # if handler is None or type(handler) == function: - # func = handler - # elif type(handler) == dict: - # try: - # module = __import__(handler['module']) - # func = getattr(module, handler['name']) - # except Exception as e: - # print(e) - # func = None - # else: - # func = None - # - # return func + # # self.handler = json.dumps + # # action_dict = dict() + # # # print(self.next_actions) + # # print(self) + # # for a in self.next_actions: + # # print(a) + # # print(a.next_actions) + # action_dict = { + # 'text': self.trigger, + # 'kind': self.kind, + # 'handler': { + # 'module': self.callback.__module__, + # 'name': self.callback.__name__ + # }, + # 'next_actions': [next_action.export_action() for next_action in self.next_actions] + # } + # return action_dict + # + # @staticmethod + # def is_next_actions_correct(next_actions): + # if type(next_actions) == list: + # for action in next_actions: + # # if isinstance(action, Action): + # if not type(action) == Action: + # return False + # return True + # else: + # return False + # + # @staticmethod + # def import_action(action_dict): + # if type(action_dict) is not dict: + # raise TypeError("'action_dict' must be a dict") + # else: + # next_actions = [Action.import_action(action) for action in action_dict.get('next_actions', [])] + # action = Action(action_dict['trigger'], + # action_dict.get('type') or 'M', + # handler=Action.get_handler(action_dict.get('handler', None))) + # action.add_actions(next_actions) + # return action + # + # @staticmethod + # def get_handler(handler): + # """ + # To obtain proper handler for the action + # :param None/function/dict handler: + # Returns handler if it is None or a function. + # If dict is provided, it loads the function from the `module` and `name` of function provided + # :return: None or function + # """ + # if handler is None or type(handler) == function: + # func = handler + # elif type(handler) == dict: + # try: + # module = __import__(handler['module']) + # func = getattr(module, handler['name']) + # except Exception as e: + # print(e) + # func = None + # else: + # func = None + # + # return func diff --git a/new_app/bot.py b/new_app/bot.py index 41d1ed9..9bdd1f8 100644 --- a/new_app/bot.py +++ b/new_app/bot.py @@ -95,7 +95,7 @@ def send_message(self, chat_id, message, keyboard=None): return self.bot.send_message(chat_id=chat_id, text=message, reply_markup=keyboard) def message_handler(self, bot, update): - respond(update) + chat_id, message, keyboard = respond(update) def start_app(self): # if start_action: diff --git a/new_app/brain.py b/new_app/brain.py index 6e61fd9..82dc510 100644 --- a/new_app/brain.py +++ b/new_app/brain.py @@ -1,5 +1,6 @@ from .context_manager import ContextManager -from .bot import BotApp +from .bot import BotApp, keyboard_layout +from telegram.replykeyboardmarkup import ReplyKeyboardMarkup def strip_command(command): @@ -32,11 +33,38 @@ def get_action(context, message): return current_action +def get_keyboard_for_actions(actions): + _actions = [] + if not isinstance(actions, (list, tuple)): + _actions.append(actions) + else: + _actions = actions + triggers = [] + for action in _actions: + # TODO: change the name from handler to callback in Action + kind = action.kind + if kind == 'C': + trigger = '/' + action.trigger + triggers.append(trigger) + if len(triggers) > 0: + keyboard = ReplyKeyboardMarkup(keyboard_layout(triggers)) + return keyboard + return None + + def respond(update): + """ + :param update: + :return: (chat_id, response_message, keyboard) + """ context = ContextManager.resolve(update) message = update.message.text current_action = get_action(context, message) # TODO: handle the case of None instead of an Action instance context['last_action'] = current_action.id + + chat_id = context['chat_id'] response = current_action.callback(message) - return BotApp.sendMessage(context.chat_id, response) + next_actions = current_action.get_next_actions() + keyboard = get_keyboard_for_actions(next_actions) + return chat_id, response, keyboard diff --git a/new_app/context_manager.py b/new_app/context_manager.py index 345733e..657bc8f 100644 --- a/new_app/context_manager.py +++ b/new_app/context_manager.py @@ -28,12 +28,15 @@ def resolve(self, update): } return self.context[key] - def add_actions(self, action): if not isinstance(action, Action): raise TypeError('`action` must be an instance of class:Action') self.actions[action.id] = action + def add_parent_action(self, action): + """ Add `action` as a child of Start Action """ + self.start_action.add_actions(action) + ContextManager = ContextManager() # ContextManager is a singleton # contextManager = ContextManager # synonyms for ContextManager From 2ceda651a9395109fbc6988914a134a39485b6b0 Mon Sep 17 00:00:00 2001 From: Vishwas Mittal Date: Mon, 25 Jun 2018 12:15:26 +0530 Subject: [PATCH 2/3] Fixed: circular imports --- news_poller/rss_fetcher_async.py | 33 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/news_poller/rss_fetcher_async.py b/news_poller/rss_fetcher_async.py index d765ccd..c62a4ee 100644 --- a/news_poller/rss_fetcher_async.py +++ b/news_poller/rss_fetcher_async.py @@ -1,8 +1,9 @@ import asyncio -from aiohttp import ClientSession + import feedparser +from aiohttp import ClientSession -from news_poller.models import RSSSchema +from new_app.news_poller.models import RSSSchema list_sources = [ 'https://timesofindia.indiatimes.com/rssfeedstopstories.cms?x=1', @@ -44,19 +45,19 @@ def print_responses(result): print(result) -async def runner(): - # while True: +async def runner(callback): + while True: feeds = await run() # TODO: process the RSS objects like logging them - print(type(feeds[0])) - print("fetched new feed, feed count: {} \n\n\n".format(len(feeds))) - # await asyncio.sleep(10) - -if __name__ == "__main__": - loop = asyncio.get_event_loop() - future = asyncio.ensure_future(runner()) - try: - # loop.run_forever() - loop.run_until_complete(future) - finally: - loop.close() + callback(feeds[0].items[0].link) + await asyncio.sleep(10) + +# if __name__ == "__main__": +# +# loop = asyncio.get_event_loop() +# future = asyncio.ensure_future(runner()) +# try: +# # loop.run_forever() +# loop.run_until_complete(future) +# finally: +# loop.close() From 18683589576cdf420b1ba46d529a31576ac6c218 Mon Sep 17 00:00:00 2001 From: Vishwas Mittal Date: Mon, 25 Jun 2018 16:47:26 +0530 Subject: [PATCH 3/3] restructured. TODO: make actions for subscribings, unsubscribing and trading --- new_app/action.py | 30 +++++++--- new_app/bot.py | 23 +++----- new_app/brain.py | 70 ++++++++++++++++------- new_app/context_manager.py | 43 -------------- new_app/ignition.py | 29 ++++++++++ new_app/initial_actions.py | 83 ++++++++++++++++++++++++++++ new_app/publisher.py | 5 ++ new_app/publishers/__init__.py | 0 new_app/publishers/base.py | 28 ++++++++++ new_app/publishers/news_publisher.py | 12 ++++ new_app/sessions.py | 52 +++++++++++++++++ new_app/storage.py | 41 ++++++++++++++ news_poller/rss_fetcher_async.py | 7 +-- 13 files changed, 334 insertions(+), 89 deletions(-) delete mode 100644 new_app/context_manager.py create mode 100644 new_app/ignition.py create mode 100644 new_app/initial_actions.py create mode 100644 new_app/publisher.py create mode 100644 new_app/publishers/__init__.py create mode 100644 new_app/publishers/base.py create mode 100644 new_app/publishers/news_publisher.py create mode 100644 new_app/sessions.py create mode 100644 new_app/storage.py diff --git a/new_app/action.py b/new_app/action.py index f623fad..c254825 100644 --- a/new_app/action.py +++ b/new_app/action.py @@ -1,6 +1,6 @@ import uuid -from .context_manager import ContextManager +from new_app.storage import StorageManager class Action(object): @@ -17,7 +17,9 @@ def __init__(self, trigger, kind, callback=None): self.next_actions = set() self.callback = callback or self.none_callback - ContextManager.add_actions(self) + if 'actions' not in StorageManager.store: + StorageManager.store['actions'] = set() + StorageManager.store['actions'].add(self) def __repr__(self): return "Action(id={}, trigger={}, kind={})".format(self.id, self.trigger, self.kind) @@ -32,11 +34,12 @@ def get_next_actions(self): return self.next_actions def add_actions(self, actions): - _actions = [] - if not isinstance(actions, (list, tuple)): - _actions.append(actions) + # _actions = [] + if not isinstance(actions, (list, tuple, set)): + # _actions.append(actions) + actions = [actions] - for act in _actions: + for act in actions: self.next_actions.add(act) # self.next_action_ids.add(act.id) @@ -44,7 +47,15 @@ def add_actions(self, actions): def none_callback(*args, **kwargs): return None - # def export_action(self): + @staticmethod + def start_callback(*args, **kwargs): + return "Welcome to my humble home :)" + + @staticmethod + def unknown_callback(*args, **kwargs): + return "Unknown action" + + # def export_action(self): # # self.handler = json.dumps # # action_dict = dict() # # # print(self.next_actions) @@ -108,3 +119,8 @@ def none_callback(*args, **kwargs): # func = None # # return func + + +StartAction = Action('start', 'C', Action.start_callback) +UnknownAction = Action('unknown', 'M', callback=Action.unknown_callback) +UnknownAction.add_actions(StartAction) diff --git a/new_app/bot.py b/new_app/bot.py index 9bdd1f8..c19d23a 100644 --- a/new_app/bot.py +++ b/new_app/bot.py @@ -5,26 +5,12 @@ from bot_action import Action from database_handler import store_doc from app.schema.telegram.message import MessageSchema -from .brain import respond +from new_app.brain import respond logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) TOKEN = '617361775:AAHS0S6aUQ_gLFmnfOKv72xQj5EBlhBUfos' -def keyboard_layout(triggers, row_size=3): - """ - Returns the layout for the keyboard - - :param actions: list of actions that each key represent - :param row_size: no. of keys in a single row - Layout: list of lists specifying the position of each key (with given action) on the keyboard - """ - layout = [] - for i in range(0, len(triggers), row_size): - layout.append([triggers for triggers in triggers[i:i + row_size]]) - return layout - - class BotApp(object): def __init__(self, start_action=None): self._updater = Updater(token=TOKEN) @@ -95,7 +81,10 @@ def send_message(self, chat_id, message, keyboard=None): return self.bot.send_message(chat_id=chat_id, text=message, reply_markup=keyboard) def message_handler(self, bot, update): + from .publishers.news_publisher import NewsPublisher + NewsPublisher.subscribers.add(update.message.chat_id) chat_id, message, keyboard = respond(update) + self.send_message(chat_id, message, keyboard) def start_app(self): # if start_action: @@ -107,9 +96,11 @@ def start_app(self): command_handler = MessageHandler(Filters.all, self.message_handler) # message_handler = MessageHandler(Filters.text, self.parent_msg_handler) self.dispatcher.add_handler(command_handler) - # self.dispatcher.add_handler(message_handler) self._updater.start_polling() + def stop_app(self): + self._updater.stop() + BotApp = BotApp() diff --git a/new_app/brain.py b/new_app/brain.py index 82dc510..d9fc0c5 100644 --- a/new_app/brain.py +++ b/new_app/brain.py @@ -1,6 +1,21 @@ -from .context_manager import ContextManager -from .bot import BotApp, keyboard_layout +from new_app.storage import StorageManager +# from new_app.bot import keyboard_layout from telegram.replykeyboardmarkup import ReplyKeyboardMarkup +from new_app.action import StartAction, UnknownAction + + +def keyboard_layout(triggers, row_size=3): + """ + Returns the layout for the keyboard + + :param actions: list of actions that each key represent + :param row_size: no. of keys in a single row + Layout: list of lists specifying the position of each key (with given action) on the keyboard + """ + layout = [] + for i in range(0, len(triggers), row_size): + layout.append([triggers for triggers in triggers[i:i + row_size]]) + return layout def strip_command(command): @@ -20,22 +35,17 @@ def action_resolver(actions, message): :returns: class:Action instance or None """ message = strip_command(message) + if message == 'start': + return StartAction for action in actions: if action.trigger == message: return action - return None - - -def get_action(context, message): - last_action = ContextManager.actions[context['last_action']] - next_actions = last_action.get_next_actions() - current_action = action_resolver(next_actions, message) - return current_action + return UnknownAction def get_keyboard_for_actions(actions): _actions = [] - if not isinstance(actions, (list, tuple)): + if not isinstance(actions, (list, tuple, set)): _actions.append(actions) else: _actions = actions @@ -52,19 +62,41 @@ def get_keyboard_for_actions(actions): return None +from new_app.sessions import SessionManager + + +# from telegram.update import Update + + def respond(update): """ :param update: :return: (chat_id, response_message, keyboard) """ - context = ContextManager.resolve(update) - message = update.message.text - current_action = get_action(context, message) - # TODO: handle the case of None instead of an Action instance - context['last_action'] = current_action.id - - chat_id = context['chat_id'] - response = current_action.callback(message) + # context = ContextManager.resolve(update) + # message = update.message.text + # current_action = get_action(context, message) + # + # context['last_action'] = current_action.id + # + # chat_id = context['chat_id'] + # response = current_action.callback(message) + # next_actions = current_action.get_next_actions() + # keyboard = get_keyboard_for_actions(next_actions) + # return chat_id, response, keyboard + user = update.effective_user + session = SessionManager.get_or_create(chat_id=update.message.chat_id, user_id=user.id) + received_message = update.message.text + session_data = session.data + last_action = session_data['action']['last_action'] + current_action = action_resolver(last_action.next_actions, received_message) + session_data['action']['action'] = current_action + + response = current_action.callback(received_message, session_data) or "No handler was assigned to this action =_=" next_actions = current_action.get_next_actions() + chat_id = update.message.chat_id keyboard = get_keyboard_for_actions(next_actions) + + # print(current_action) + # print(next_actions) return chat_id, response, keyboard diff --git a/new_app/context_manager.py b/new_app/context_manager.py deleted file mode 100644 index 657bc8f..0000000 --- a/new_app/context_manager.py +++ /dev/null @@ -1,43 +0,0 @@ -# from telegram.update import Update -from .action import Action - - -class ContextManager: - """ - The store house for the application data. - Data for a particular session (user:chat) is stored in self.contxt - All the subscribers can store their data for a particular session here. - This can be used to model the interactions with the database when the application scales. - """ - - def __init__(self): - self.context = {} - self.actions = {} - self.start_action = Action('start', 'C') - - def resolve(self, update): - user_id = update.message.message_from.id - chat_id = update.message.chat_id - key = '{}:{}'.format(user_id, chat_id) - if key not in self.context: - self.context[key] = { - 'user_id': user_id, - 'chat_id': chat_id, - 'subscriptions': {}, - 'last_action': self.start_action.id - } - return self.context[key] - - def add_actions(self, action): - if not isinstance(action, Action): - raise TypeError('`action` must be an instance of class:Action') - self.actions[action.id] = action - - def add_parent_action(self, action): - """ Add `action` as a child of Start Action """ - self.start_action.add_actions(action) - - -ContextManager = ContextManager() # ContextManager is a singleton -# contextManager = ContextManager # synonyms for ContextManager -# context_manager = ContextManager diff --git a/new_app/ignition.py b/new_app/ignition.py new file mode 100644 index 0000000..60f3eb3 --- /dev/null +++ b/new_app/ignition.py @@ -0,0 +1,29 @@ +import asyncio + +from news_poller.rss_fetcher_async import runner +from new_app.bot import BotApp +from new_app.publishers.news_publisher import NewsPublisher +from new_app.action import Action, StartAction + +NewsPublisher.publisher_callback = BotApp.send_message +loop = asyncio.get_event_loop() +future = asyncio.ensure_future(runner(NewsPublisher.publish)) + +# trade = Action('trade', 'C') +# subscriptions = Action('subscriptions', 'C') +# leave = Action('leave', 'C') +# +# StartAction.add_actions([trade, subscriptions, leave]) + + + + +try: + # loop.run_forever() + BotApp.start_app() + loop.run_until_complete(future) +except Exception as e: + print(e) + BotApp.stop_app() +finally: + loop.close() diff --git a/new_app/initial_actions.py b/new_app/initial_actions.py new file mode 100644 index 0000000..a10cc38 --- /dev/null +++ b/new_app/initial_actions.py @@ -0,0 +1,83 @@ +from new_app.action import Action, UnknownAction, StartAction +from new_app.storage import StorageManager +from new_app.brain import strip_command + +""" +Actions: + - subscriptions + - add more + - confirm + - unsubscribe + - confirm + - trade + - list of companies + - quantity + - comfirm +""" + + +def subscriptions_callback(message, session_data): + response = "You are subscribed to following notifications:\n" + publishers = session_data['subscriptions'].keys() + for pub in publishers: + response = response + '/' + str(pub) + '\n' + return response + + +subscriptions = Action('subscriptions', 'C') + + +def confirm_subscription_add_callback(message, session_data): + temp_subs = session_data['action']['data']['temp_subs'] + for sub in temp_subs: + # StorageManager.store['subscriptions'][sub]['subscripbers'] + pass + + +confirm_add = Action('confirm', 'C') + + +def subscription_item_callback(message, session_data): + pub = strip_command(message) + if pub in session_data['action']['data']['unsubs_temp']: + if 'temp_subs' not in session_data['action']['data']: + session_data['action']['data']['temp_subs'] = set() + session_data['action']['data']['temp_subs'].add(pub) + response = "choose more or click confirm" + session_data['action']['data']['unsubs_temp'].remove(pub) + else: + response = 'Unknown Publisher' + + last_action = session_data['action']['last_action'] + publishers = session_data['action']['data']['unsubs_temp'] + for pub in publishers: + if pub not in session_data['subscriptions']: + last_action.add_actions(Action(str(pub), 'C', subscription_item_callback)) + + last_action.add_actions(confirm_add) + return response + + +def add_subscriptions_callback(message, session_data): + session_data['action']['data']['unsubs_temp'] = set() + publishers = StorageManager.store['publishers'].keys() + last_action = session_data['action']['last_action'] + response = "Choose the publishers you want to subscribe to:\n" + for pub in publishers: + if pub not in session_data['subscriptions']: + response = response + '/' + str(pub) + '\n' + session_data['action']['data']['unsubs_temp'].add(str(pub)) + last_action.add_actions(Action(str(pub), 'C', subscription_item_callback)) + + return response + + +add_subs = Action('add more', 'C') + +unsubscribe = Action('unsubscribe', 'C') +confirm_unsubscribe = Action('confirm', 'C') + +trade = Action('trade', 'C') +choose_company = Action('Choose Company', 'M') +quantity = Action('Quantity?', 'M') +confirm_trade = Action('Confrim', 'C') diff --git a/new_app/publisher.py b/new_app/publisher.py new file mode 100644 index 0000000..25619e3 --- /dev/null +++ b/new_app/publisher.py @@ -0,0 +1,5 @@ +from new_app.publishers import * + + +class PublisherManager: + pass diff --git a/new_app/publishers/__init__.py b/new_app/publishers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/new_app/publishers/base.py b/new_app/publishers/base.py new file mode 100644 index 0000000..5ddc543 --- /dev/null +++ b/new_app/publishers/base.py @@ -0,0 +1,28 @@ +class PublisherBase: + def __init__(self, name, subscribers=None, publisher_callback=None): + self.name = name + # self.registered = False + + if subscribers is None: + self.subscribers = set() + else: + self.subscribers = set(subscribers) + + self.publisher_callback = publisher_callback + + def add_subscribers(self, subscribers): + if not isinstance(subscribers, (list, tuple, set)): + subscribers = [subscribers] + # self.subscribers += subscribers + for sub in subscribers: + self.subscribers.add(sub) + + def publish(self, content): + message, args, kwargs = self.process_content(content) + for subs in self.subscribers: + self.publisher_callback(subs, message, *args, **kwargs) + + def process_content(self, content): + print("called base process_content") + return content, (), {} + diff --git a/new_app/publishers/news_publisher.py b/new_app/publishers/news_publisher.py new file mode 100644 index 0000000..8359334 --- /dev/null +++ b/new_app/publishers/news_publisher.py @@ -0,0 +1,12 @@ +from new_app.publishers.base import PublisherBase + + +class NewsPublisher(PublisherBase): + def __init__(self, subscribers=None, publisher_callback=None): + super().__init__(name="News-Room", subscribers=subscribers, publisher_callback=publisher_callback) + + def process_content(self, content): + return str(content[0].items[0].link), (), {} + + +NewsPublisher = NewsPublisher() # singleton class diff --git a/new_app/sessions.py b/new_app/sessions.py new file mode 100644 index 0000000..75a6daf --- /dev/null +++ b/new_app/sessions.py @@ -0,0 +1,52 @@ +from new_app.storage import StorageManager +from new_app.action import Action, UnknownAction + + +class Session: + def __init__(self, chat_id, user_id): + self.user_id = user_id + self.chat_id = chat_id + self.data = Session.get_empty_data(chat_id=chat_id, user_id=user_id) + + @property + def key(self): + return Session.get_key(self.chat_id, self.user_id) + + @staticmethod + def get_key(chat_id, user_id): + return '{}:{}'.format(chat_id, user_id) + + @staticmethod + def get_empty_data(chat_id, user_id): + return { + 'user_id': user_id, + 'chat_id': chat_id, + 'action': { + 'last_action': UnknownAction, + 'data': {} + }, # user will start interacting with the `start` command + 'subscriptions': set() + } + + +class SessionManager: + def __init__(self): + if 'sessions' not in StorageManager.store: + StorageManager.store['sessions'] = {} + self.session_store = StorageManager.store['sessions'] + + def add_session(self, chat_id, user_id): + session = Session(chat_id=chat_id, user_id=user_id) + self.session_store[session.key] = session + return session + + def get_or_create(self, chat_id, user_id): + """ Return the session instance for these params """ + key = Session.get_key(chat_id=chat_id, user_id=user_id) + if key in self.session_store: + return self.session_store[key] + else: + return self.add_session(chat_id=chat_id, user_id=user_id) + + +SessionManager = SessionManager() # session manager is Singleton diff --git a/new_app/storage.py b/new_app/storage.py new file mode 100644 index 0000000..5c12f4a --- /dev/null +++ b/new_app/storage.py @@ -0,0 +1,41 @@ +class StorageManager: + """ + The store house for the application data. + Data for a particular session (user:chat) is stored in self.context + All the subscribers can store their data for a particular session here. + This can be used to model the interactions with the database when the application scales. + """ + + def __init__(self): + self.store = {} + # self.context = {} + + # self.actions = {} + # self.start_action = None # Action('start', 'C') + + # def resolve(self, update): + # user_id = update.message.message_from.id + # chat_id = update.message.chat_id + # key = '{}:{}'.format(user_id, chat_id) + # if key not in self.store: + # self.store[key] = { + # 'user_id': user_id, + # 'chat_id': chat_id, + # 'subscriptions': {}, + # 'last_action': None + # } + # return self.store[key] + + # def add_actions(self, action): + # # if not isinstance(action, Action): + # # raise TypeError('`action` must be an instance of class:Action') + # self.actions[action.id] = action + # + # def add_parent_action(self, action): + # """ Add `action` as a child of Start Action """ + # self.start_action.add_actions(action) + + +StorageManager = StorageManager() # ContextManager is a singleton +# contextManager = ContextManager # synonyms for ContextManager +# context_manager = ContextManager diff --git a/news_poller/rss_fetcher_async.py b/news_poller/rss_fetcher_async.py index c62a4ee..abcab8d 100644 --- a/news_poller/rss_fetcher_async.py +++ b/news_poller/rss_fetcher_async.py @@ -1,9 +1,8 @@ import asyncio - -import feedparser from aiohttp import ClientSession +import feedparser -from new_app.news_poller.models import RSSSchema +from news_poller.models import RSSSchema list_sources = [ 'https://timesofindia.indiatimes.com/rssfeedstopstories.cms?x=1', @@ -49,7 +48,7 @@ async def runner(callback): while True: feeds = await run() # TODO: process the RSS objects like logging them - callback(feeds[0].items[0].link) + callback(feeds) await asyncio.sleep(10) # if __name__ == "__main__":