new menu for more granular control over the single stocks

This commit is contained in:
cupcakearmy 2019-12-19 16:28:37 +01:00
parent 6f0930a0cc
commit e1c93963d9
9 changed files with 341 additions and 193 deletions

View File

@ -1,37 +0,0 @@
import asyncio
import threading
def interval(every: float or int, autorun=False, iterations=-1, isolated=False, *args_root, **kwargs_root):
def wrapper(fn):
async def decorator(*args, **kwargs):
it = 0
first = True
while iterations == -1 or it < iterations:
it += 1
if first:
first = False
else:
await asyncio.sleep(every)
await fn(*args, **kwargs)
def capsule(*args, **kwargs):
def loop_in_thread(l):
asyncio.set_event_loop(l)
l.run_until_complete(decorator(*args, **kwargs))
loop = asyncio.get_event_loop()
threading.Thread(target=loop_in_thread, args=(loop,)).start()
if autorun:
if isolated:
capsule(*args_root, **kwargs_root)
else:
asyncio.run(decorator(*args_root, **kwargs_root))
else:
return capsule if isolated else decorator
return wrapper

View File

@ -1,23 +1,35 @@
from enum import Enum
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardRemove, ParseMode from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardRemove, ParseMode
from telegram.ext import CommandHandler, MessageHandler, Filters, ConversationHandler, CallbackQueryHandler, CallbackContext from telegram.ext import CommandHandler, MessageHandler, Filters, ConversationHandler, CallbackQueryHandler, CallbackContext
from utils import Section MENU, API_KEY, ENABLED = range(3)
MENU, API_KEY, FREQUENCY, ENABLED = range(4)
class Section(Enum):
Watchlist = 'watchlist' # The list of Stocks/ETF to watch
Code = 'code' # Market code for a given stock, etf, etc.
API_Key = 'api_key' # Alpha Vantage API Key
Running = 'running' # Currently sending updates. Avoid overloading the API
Enabled = 'enabled' # Whether the bot should send automatic updates
Interval = 'interval' # Time axis of the graph
Frequency = 'frequency' # How ofter updates should be sent
LastRun = 'last_run' # Last time an update was sent to the user
CurrentToEdit = 'current_to_edit' # Current element to edit in the conversation handler
def show_menu(update: Update, context: CallbackContext): def show_menu(update: Update, context: CallbackContext):
keyboard = [ keyboard = [
[InlineKeyboardButton('API Key', callback_data=API_KEY)], [InlineKeyboardButton('API Key', callback_data=API_KEY)],
[InlineKeyboardButton('Auto Updates', callback_data=ENABLED)], [InlineKeyboardButton(
[InlineKeyboardButton('Frequency', callback_data=FREQUENCY)], f'Turn {"off" if context.user_data.setdefault(Section.Enabled.value, True) else "on"} global auto updates',
callback_data=ENABLED)],
[InlineKeyboardButton('Done', callback_data=ConversationHandler.END)], [InlineKeyboardButton('Done', callback_data=ConversationHandler.END)],
] ]
update.effective_user.send_message( update.effective_user.send_message(
'_Current settings:_\n' '_Current settings:_\n'
f'API Key: *{context.user_data[Section.API_Key.value]}*\n' f'API Key: *{context.user_data.get(Section.API_Key.value, "No Api key set")}*\n'
f'Auto Updates: *{context.user_data[Section.Enabled.value]}*\n' f'Global auto updates: *{context.user_data[Section.Enabled.value]}*\n'
f'Frequency: *{context.user_data[Section.Frequency.value]}*\n'
'\nWhat settings do you want to configure?', '\nWhat settings do you want to configure?',
parse_mode=ParseMode.MARKDOWN, parse_mode=ParseMode.MARKDOWN,
reply_markup=InlineKeyboardMarkup(keyboard, one_time_keyboard=True) reply_markup=InlineKeyboardMarkup(keyboard, one_time_keyboard=True)
@ -35,27 +47,7 @@ def show_menu_api_key(update: Update, context: CallbackContext):
return API_KEY return API_KEY
def show_menu_frequency(update: Update, context: CallbackContext): def init(update: Update, context: CallbackContext):
keyboard = [
[InlineKeyboardButton('2 minutes', callback_data='2m'), InlineKeyboardButton(
'30 minutes', callback_data='30m')],
[InlineKeyboardButton('hour', callback_data='1h'), InlineKeyboardButton(
'4 hours', callback_data='4h')],
[InlineKeyboardButton('12 hours', callback_data='12h'), InlineKeyboardButton(
'day', callback_data='1d')],
[InlineKeyboardButton('3 days', callback_data='3d'), InlineKeyboardButton(
'week', callback_data='1w')],
[InlineKeyboardButton('Cancel', callback_data='cancel')],
]
update.effective_user.send_message(
'Send me updates every: ⬇',
reply_markup=InlineKeyboardMarkup(keyboard)
)
return FREQUENCY
def config(update: Update, context: CallbackContext):
context.bot.delete_message( context.bot.delete_message(
chat_id=update.message.chat_id, chat_id=update.message.chat_id,
message_id=update.message.message_id, message_id=update.message.message_id,
@ -73,8 +65,6 @@ def menu(update: Update, context: CallbackContext):
if selected == API_KEY: if selected == API_KEY:
return show_menu_api_key(update, context) return show_menu_api_key(update, context)
elif selected == FREQUENCY:
return show_menu_frequency(update, context)
elif selected == ENABLED: elif selected == ENABLED:
toggle_enabled(update, context) toggle_enabled(update, context)
else: else:
@ -89,25 +79,8 @@ def set_api_key(update, context):
return show_menu(update, context) return show_menu(update, context)
def set_frequency(update: Update, context: CallbackContext):
selected = update.callback_query.data
if selected != 'cancel':
update.callback_query.edit_message_text(f'Saved {selected} 💪')
context.user_data[Section.Frequency.value] = selected
else:
context.bot.delete_message(
chat_id=update.callback_query.message.chat_id,
message_id=update.callback_query.message.message_id,
)
return show_menu(update, context)
def toggle_enabled(update: Update, context: CallbackContext): def toggle_enabled(update: Update, context: CallbackContext):
new = not context.user_data.setdefault(Section.Enabled.value, True) context.user_data[Section.Enabled.value] = not context.user_data[Section.Enabled.value]
context.user_data[Section.Enabled.value] = new
update.effective_user.send_message('Auto updates enabled' if new else 'Auto updates disabled')
return show_menu(update, context) return show_menu(update, context)
@ -118,16 +91,13 @@ def cancel(update: Update, context: CallbackContext):
config_handler = ConversationHandler( config_handler = ConversationHandler(
entry_points=[CommandHandler('config', config)], entry_points=[CommandHandler('settings', init)],
states={ states={
MENU: [CallbackQueryHandler(menu)], MENU: [CallbackQueryHandler(menu)],
API_KEY: [ API_KEY: [
CommandHandler('cancel', cancel), CommandHandler('cancel', cancel),
MessageHandler(Filters.all, set_api_key), MessageHandler(Filters.all, set_api_key),
], ],
FREQUENCY: [CallbackQueryHandler(set_frequency)],
}, },
fallbacks=[CommandHandler('cancel', cancel)] fallbacks=[CommandHandler('cancel', cancel)]
) )

View File

@ -1,57 +1,77 @@
from asyncio import sleep, run from asyncio import sleep, run
from datetime import datetime from datetime import datetime
from threading import Timer
from pytimeparse import parse from pytimeparse import parse
from telegram import Update, ParseMode from telegram import Update, ParseMode, ReplyKeyboardRemove
from telegram.ext import CallbackContext from telegram.ext import CallbackContext, ConversationHandler
from telegram.ext.dispatcher import run_async from telegram.ext.dispatcher import run_async
from commands.config import Section
from market import Market from market import Market
from text import INTRO_TEXT from text import INTRO_TEXT
from utils import Section, persistence, updater, current_timestamp, delta_timestamp from utils import persistence, updater, current_timestamp, delta_timestamp
SENDING = False SENDING = False
def error(update: Update, context: CallbackContext): def error_handler(update: Update, context: CallbackContext):
print(context.error) print('Error: ', context.error)
def start(update: Update, context: CallbackContext): def start_handler(update: Update, context: CallbackContext):
update.message.reply_markdown(INTRO_TEXT) update.message.reply_markdown(INTRO_TEXT)
def help_handler(update: Update, context: CallbackContext):
update.message.reply_markdown(INTRO_TEXT)
def stop_handler(update: Update, context: CallbackContext):
context.user_data.clear()
update.message.reply_text('You and your data were deleted 🗑')
@run_async @run_async
def data(update: Update, context: CallbackContext): def data(update: Update, context: CallbackContext):
delta = current_timestamp() - context.user_data.setdefault(Section.Interval.value, delta_timestamp(days=365)) send_update_to_user(update.effective_user['id'], False)
send_update_to_user(user=update.effective_user['id'], delta=delta)
def send_update_to_user(user: str, delta: int): def send_update_to_user(user: str, auto, codes=None):
user_data = None user_data = None
try: try:
user_data = persistence.user_data[user] user_data = persistence.user_data[user]
running = user_data.setdefault(Section.Running.value, False) running = user_data.setdefault(Section.Running.value, False)
print(f'Running {user} - {user_data}')
if Section.API_Key.value not in user_data: if Section.API_Key.value not in user_data:
updater.bot.send_message(user, text='API Key not set ⛔️') updater.bot.send_message(user, text='API Key not set ⛔️\nSet in /settings')
return return
if running: if running:
updater.bot.send_message(user, text='Already running 🏃') updater.bot.send_message(user, text='Already running 🏃')
return return
print(f'Sending updates to {user}')
user_data[Section.Running.value] = True user_data[Section.Running.value] = True
user_data[Section.LastRun.value] = current_timestamp()
market = Market(user_data[Section.API_Key.value]) market = Market(user_data[Section.API_Key.value])
now = current_timestamp()
if auto:
updater.bot.send_message(user, text='Getting updates 🌎') updater.bot.send_message(user, text='Getting updates 🌎')
first = True first = True
for item in user_data.get(Section.Watchlist.value, []): for code in codes if codes else user_data.get(Section.Watchlist.value, {}).keys():
try:
code_data = persistence.user_data[user][Section.Watchlist.value][code]
code_data = code_data['value']
print(code, code_data)
last_run = code_data[Section.LastRun.value]
frequency = parse(code_data[Section.Frequency.value])
interval = parse(code_data[Section.Interval.value])
print(code, last_run + frequency, now, last_run + frequency - now)
if auto and last_run + frequency > now:
continue
persistence.user_data[user][Section.Watchlist.value][code][Section.LastRun.value] = current_timestamp()
persistence.flush()
if first: if first:
first = False first = False
else: else:
@ -60,15 +80,18 @@ def send_update_to_user(user: str, delta: int):
run(sleep(60)) run(sleep(60))
msg.delete() msg.delete()
msg = updater.bot.send_message(user, text=f'Calculating {item}... ⏳') msg = updater.bot.send_message(user, text=f'Calculating {code}... ⏳')
chart = market.get_wma(item, datetime.fromtimestamp(delta)) delta = datetime.fromtimestamp(now - interval)
chart = market.get_wma(code, delta)
msg.delete() msg.delete()
updater.bot.send_photo(user, photo=chart, caption=f'*{item}*', updater.bot.send_photo(user, photo=chart, disable_notification=True,
parse_mode=ParseMode.MARKDOWN, disable_notification=True) caption=f'{code} - {code_data[Section.Interval.value]}')
except Exception as e: except Exception as e:
print(f'{user} - {e}') print(f'{user} - {e}')
updater.bot.send_message(user, text=f'There was an error ⚠️\n {e}') updater.bot.send_message(user, text=f'There was an error ⚠️\n {e}')
if auto:
updater.bot.send_message(user, text=f'Done ✅')
finally: finally:
if user_data: if user_data:
user_data[Section.Running.value] = False user_data[Section.Running.value] = False
@ -81,16 +104,9 @@ def send_updates(context: CallbackContext):
return return
SENDING = True SENDING = True
now = current_timestamp()
for user, user_data in persistence.user_data.items(): for user, user_data in persistence.user_data.items():
enabled = user_data.setdefault(Section.Enabled.value, True) if user_data.setdefault(Section.Enabled.value, False):
last_run = user_data.setdefault(Section.LastRun.value, 0) send_update_to_user(user=user, auto=True)
frequency = parse(user_data.setdefault(Section.Frequency.value, '1d'))
if enabled and last_run + frequency < now:
delta = now - user_data.setdefault(Section.Interval.value, delta_timestamp(days=365))
send_update_to_user(user=user, delta=delta)
except Exception as e: except Exception as e:
print(e) print(e)
finally: finally:

View File

@ -1,45 +1,232 @@
from telegram import Update from telegram import Update, InlineKeyboardButton, ParseMode, InlineKeyboardMarkup, ReplyKeyboardRemove
from telegram.ext import CallbackContext from telegram.ext import CallbackContext, ConversationHandler, CommandHandler, CallbackQueryHandler, MessageHandler, Filters
from limited_list import LimitedList from commands.config import Section
from utils import parse_command, config, Section from commands.other import send_update_to_user
from limited_dict import LimitedDict
from utils import parse_command, config
ALL, SINGLE, EDIT, ADD, DELETE, BACK, ENABLED, FREQUENCY, INTERVAL, DATA = map(chr, range(10))
END = str(ConversationHandler.END)
def get_watchlist(context: CallbackContext) -> LimitedList: def get_watchlist(context: CallbackContext) -> LimitedDict:
return LimitedList( return LimitedDict(
config[Section.Watchlist.value]['max_items'], config[Section.Watchlist.value]['max_items'],
context.user_data.setdefault(Section.Watchlist.value, []), context.user_data.setdefault(Section.Watchlist.value, {}),
) )
def save_watchlist(context: CallbackContext, l: LimitedList): def save_watchlist(context: CallbackContext, limited_dict: LimitedDict):
context.user_data[Section.Watchlist.value] = l.all() context.user_data[Section.Watchlist.value] = limited_dict.dict
def watchlist_add(update: Update, context: CallbackContext): def init(update: Update, context: CallbackContext):
value, *rest = parse_command(update) context.bot.delete_message(
chat_id=update.message.chat_id,
message_id=update.message.message_id,
)
return show_menu(update, context)
def show_menu(update: Update, context: CallbackContext):
wl = get_watchlist(context) wl = get_watchlist(context)
wl.add(str(value).upper()) saved = [
save_watchlist(context, wl) [InlineKeyboardButton(item, callback_data=item)]
update.message.reply_text('Saved 💾') for item in wl.all()
]
options = [[
InlineKeyboardButton('Add', callback_data=ADD),
InlineKeyboardButton('Done', callback_data=END)
]]
update.effective_user.send_message(
'_Your Watchlist:_\n'
f'*{len(wl)}/{wl.limit}* slots filled\n'
'\nYou can add, modify or delete items',
parse_mode=ParseMode.MARKDOWN,
reply_markup=InlineKeyboardMarkup(saved + options, one_time_keyboard=True)
)
return ALL
def watchlist_delete(update: Update, context: CallbackContext): def menu(update: Update, context: CallbackContext):
value, *rest = parse_command(update) context.bot.delete_message(
chat_id=update.callback_query.message.chat_id,
message_id=update.callback_query.message.message_id,
)
selected: str = update.callback_query.data
if selected == ADD:
return show_add(update, context)
elif selected == END:
return ConversationHandler.END
else:
context.user_data[Section.CurrentToEdit.value] = selected
return show_single(update, context)
def show_add(update: Update, context: CallbackContext):
update.effective_user.send_message(
'Send me the code (e.g. AAPL or URTH)\n'
'or send /cancel',
reply_markup=ReplyKeyboardRemove()
)
return ADD
def add(update, context):
reply: str = update.message.text
wl = get_watchlist(context) wl = get_watchlist(context)
found = wl.delete(value) wl[reply.upper()] = {
Section.Enabled.value: True,
Section.Frequency.value: '1d',
Section.Interval.value: '52w',
Section.LastRun.value: 0,
}
save_watchlist(context, wl) save_watchlist(context, wl)
update.message.reply_text('Deleted 🗑' if found else 'Not found ❓') update.message.reply_text(f'Saved {reply} 💾', reply_markup=ReplyKeyboardRemove())
return show_menu(update, context)
def watchlist_all(update: Update, context: CallbackContext): def show_single(update, context):
items = get_watchlist(context).all() current = context.user_data[Section.CurrentToEdit.value]
update.message.reply_text('\n'.join(items) if len(items) > 0 else 'Your list is empty 📭') current_data = get_watchlist(context)[current]
keyboard = [
[InlineKeyboardButton(f'Turn {"off" if current_data[Section.Enabled.value] else "on"} auto updates', callback_data=ENABLED)],
[InlineKeyboardButton(f'Frequency', callback_data=FREQUENCY)],
[InlineKeyboardButton(f'Time interval', callback_data=INTERVAL)],
[InlineKeyboardButton(f'Show data', callback_data=DATA)],
[InlineKeyboardButton('Delete', callback_data=DELETE)],
[InlineKeyboardButton('Back', callback_data=BACK)],
]
update.effective_user.send_message(
'_Current settings:_\n'
f'Auto Updates: *{current_data[Section.Enabled.value]}*\n'
f'Frequency: *{current_data[Section.Frequency.value]}*\n'
f'Interval: *{current_data[Section.Interval.value]}*\n'
f'\nEdit {current}: ⬇',
parse_mode=ParseMode.MARKDOWN,
reply_markup=InlineKeyboardMarkup(keyboard)
)
return SINGLE
def watchlist_clear(update: Update, context: CallbackContext): def single(update, context):
current = context.user_data[Section.CurrentToEdit.value]
selected = update.callback_query.data
wl = get_watchlist(context) wl = get_watchlist(context)
wl.clear()
context.bot.delete_message(
chat_id=update.callback_query.message.chat_id,
message_id=update.callback_query.message.message_id,
)
if selected == DELETE:
update.effective_user.send_message(f'Deleted {current} 💪')
del wl[current]
save_watchlist(context, wl) save_watchlist(context, wl)
update.message.reply_text('Cleared 🧼') return show_menu(update, context)
elif selected == BACK:
return show_menu(update, context)
elif selected == ENABLED:
print('Changing', wl[Section.Enabled.value])
wl[current][Section.Enabled.value] = not wl[current][Section.Enabled.value]
save_watchlist(context, wl)
return show_single(update, context)
elif selected == FREQUENCY:
return show_single_frequency(update, context)
elif selected == INTERVAL:
return show_single_interval(update, context)
elif selected == DATA:
send_update_to_user(update.effective_user['id'], False, [current])
return show_single(update, context)
else:
return cancel(update, context)
def show_single_frequency(update: Update, context: CallbackContext):
keyboard = [
[InlineKeyboardButton('2 minutes', callback_data='2m'), InlineKeyboardButton(
'30 minutes', callback_data='30m')],
[InlineKeyboardButton('hour', callback_data='1h'), InlineKeyboardButton(
'4 hours', callback_data='4h')],
[InlineKeyboardButton('12 hours', callback_data='12h'), InlineKeyboardButton(
'day', callback_data='1d')],
[InlineKeyboardButton('3 days', callback_data='3d'), InlineKeyboardButton(
'week', callback_data='1w')],
[InlineKeyboardButton('Cancel', callback_data='cancel')],
]
update.effective_user.send_message(
'Send me updates every: ⬇',
reply_markup=InlineKeyboardMarkup(keyboard)
)
return FREQUENCY
def single_frequency(update: Update, context: CallbackContext):
return save_single_attribute(update, context, Section.Frequency.value)
def show_single_interval(update: Update, context: CallbackContext):
keyboard = [
[InlineKeyboardButton('1 day', callback_data='1d'), InlineKeyboardButton(
'2 days', callback_data='2d')],
[InlineKeyboardButton('1 week', callback_data='7d'), InlineKeyboardButton(
'1 weeks', callback_data='14d')],
[InlineKeyboardButton('1 month', callback_data='30d'), InlineKeyboardButton(
'3 months', callback_data='90d')],
[InlineKeyboardButton('1 year', callback_data='52w'), InlineKeyboardButton(
'2 years', callback_data='104w')],
[InlineKeyboardButton('Cancel', callback_data='cancel')],
]
update.effective_user.send_message(
'Select the graph time span 📈:',
reply_markup=InlineKeyboardMarkup(keyboard)
)
return INTERVAL
def single_interval(update: Update, context: CallbackContext):
return save_single_attribute(update, context, Section.Interval.value)
def save_single_attribute(update: Update, context: CallbackContext, key):
current = context.user_data[Section.CurrentToEdit.value]
selected = update.callback_query.data
wl = get_watchlist(context)
context.bot.delete_message(
chat_id=update.callback_query.message.chat_id,
message_id=update.callback_query.message.message_id,
)
if selected != 'cancel':
update.effective_user.send_message(f'Saved {selected} 💾')
wl[current][key] = selected
return show_single(update, context)
def cancel(update: Update, context: CallbackContext):
update.effective_user.send_message('Canceled', reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
cancel_command_handler = CommandHandler('cancel', cancel)
watchlist_handler = ConversationHandler(
entry_points=[CommandHandler('list', init)],
states={
ALL: [CallbackQueryHandler(menu)],
ADD: [cancel_command_handler, MessageHandler(Filters.text, add)],
SINGLE: [cancel_command_handler, CallbackQueryHandler(single)],
FREQUENCY: [CallbackQueryHandler(single_frequency)],
INTERVAL: [CallbackQueryHandler(single_interval)],
},
fallbacks=[cancel_command_handler],
)

16
src/generator_dict.py Normal file
View File

@ -0,0 +1,16 @@
class GeneratorDict(dict):
def __init__(self, *args, generator=None, **kwargs):
super().__init__(*args, **kwargs)
if not generator:
def generator(x): return x
self.generator = generator
def __getitem__(self, key):
try:
return super().__getitem__(key)
except:
value = self.generator(key)
super().__setitem__(key, value)
return value

View File

@ -1,38 +1,44 @@
import time import time
import math from math import inf
class LimitedDict: class LimitedDict:
def __init__(self, init: dict, limit: int): def __init__(self, limit: int, init: dict):
self.dict = init self.dict = init
self.limit = limit self.limit = limit
def set(self, key, value): def __len__(self):
# Delete oldest element if there are too many return len(self.dict)
def __setitem__(self, key, value):
# Delete the oldest if there are too many entries
if len(self.dict) + 1 > self.limit: if len(self.dict) + 1 > self.limit:
timestamp = math.inf timestamp = inf
who = None oldest = None
for cur, item in self.dict.items(): for cur, item in self.dict.items():
if item['when'] < timestamp: if item['when'] < timestamp:
timestamp = item['when'] timestamp = item['when']
who = cur oldest = cur
del self.dict[who] del self.dict[oldest]
self.dict[key] = { self.dict[key] = {
'value': value, 'value': value,
'when': int(time.time()) 'when': int(time.time())
} }
def get(self, key): def __getitem__(self, key):
value = self.dict.get(key, None) value = self.dict.get(key, None)
return value['value'] if value else None return value['value'] if value else None
def delete(self, key): def __delitem__(self, key):
self.dict.pop(key, None) self.dict.pop(key, None)
def clear(self): def clear(self):
self.dict.clear() self.dict.clear()
def all(self): def all(self):
return [x['value'] for x in self.dict.values()] return {
key: value['value']
for key, value in self.dict.items()
}

View File

@ -11,10 +11,13 @@ class LimitedList:
self.data = init if init else [] self.data = init if init else []
self.limit = limit self.limit = limit
def __len__(self):
return len(self.data)
def _is_index(self, i: int) -> bool: def _is_index(self, i: int) -> bool:
return False if i < 0 or i > len(self.data) - 1 else True return False if i < 0 or i > len(self.data) - 1 else True
def add(self, value: str): def add(self, value: any):
print(f'Before {self.data}') print(f'Before {self.data}')
# Delete oldest element if there are too many # Delete oldest element if there are too many
if len(self.data) + 1 > self.limit: if len(self.data) + 1 > self.limit:

View File

@ -1,10 +1,10 @@
import matplotlib as mpl import matplotlib as mpl
from telegram.ext import CommandHandler from telegram.ext import CommandHandler
from utils import updater, persistence from utils import updater
from commands.config import config_handler from commands.config import config_handler
from commands.watchlist import watchlist_add, watchlist_delete, watchlist_all, watchlist_clear from commands.watchlist import watchlist_handler
from commands.other import start, data, send_updates from commands.other import data, send_updates, start_handler, help_handler, stop_handler, error_handler
def main(): def main():
@ -14,16 +14,16 @@ def main():
jq = updater.job_queue jq = updater.job_queue
# Handlers # Handlers
dp.add_handler(CommandHandler('add', watchlist_add)) dp.add_error_handler(error_handler)
dp.add_handler(CommandHandler('delete', watchlist_delete)) dp.add_handler(CommandHandler('start', start_handler))
dp.add_handler(CommandHandler('list', watchlist_all)) dp.add_handler(CommandHandler('stop', stop_handler))
dp.add_handler(CommandHandler('clear', watchlist_clear)) dp.add_handler(CommandHandler('help', help_handler))
dp.add_handler(config_handler)
dp.add_handler(CommandHandler('start', start))
dp.add_handler(CommandHandler('data', data)) dp.add_handler(CommandHandler('data', data))
dp.add_handler(config_handler)
dp.add_handler(watchlist_handler)
# Cron jobs # Cron jobs
jq.run_repeating(send_updates, interval=30, first=0) jq.run_repeating(send_updates, interval=30, first=5)
# Start # Start
print('Started 🚀') print('Started 🚀')

View File

@ -10,19 +10,9 @@ CONFIG_FILE = './config.yml'
config = load(open(CONFIG_FILE, 'r'), Loader=Loader) config = load(open(CONFIG_FILE, 'r'), Loader=Loader)
persistence = PicklePersistence(DB_FILE) persistence = PicklePersistence(DB_FILE)
# persistence.load_singlefile()
updater: Updater = Updater(config['token'], use_context=True, persistence=persistence) updater: Updater = Updater(config['token'], use_context=True, persistence=persistence)
class Section(Enum):
Watchlist = 'watchlist'
API_Key = 'api_key'
Running = 'running'
Interval = 'interval' # Time axis of the graph
Frequency = 'frequency' # How ofter updates should be sent
LastRun = 'last_run'
def current_timestamp(): def current_timestamp():
return int(datetime.now().timestamp()) return int(datetime.now().timestamp())
@ -32,11 +22,8 @@ def delta_timestamp(**kwargs):
def parse_command(update: Update) -> (str, str): def parse_command(update: Update) -> (str, str):
"""
Splits the command from the rest of the message and returns the tuple
"""
key, value = (update.message.text.split(' ', 1)[1].split(' ', 1) + [None])[:2] key, value = (update.message.text.split(' ', 1)[1].split(' ', 1) + [None])[:2]
return key, value return key, value
def parse_callback(update: Update) -> str:
selected = update.callback_query.data
cleaned = ''.join(selected.split(':')[1:]) # Remove the pattern from the start
return cleaned