diff --git a/.flaskenv b/.flaskenv new file mode 100644 index 0000000..0271bb7 --- /dev/null +++ b/.flaskenv @@ -0,0 +1,2 @@ +FLASK_APP=system.app +FLASK_ENV=development diff --git a/.gitignore b/.gitignore index 7675bff..7b41ba2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ __pycache__/ .idea/ +.vscode/ venv/ -app.db -environ.sh +db.sqlite3 +.env diff --git a/Procfile b/Procfile index 6c8a22f..3ebb06a 100644 --- a/Procfile +++ b/Procfile @@ -1,4 +1,3 @@ -web: python webhook.py -init: python manage.py db init -migrate: python manage.py db migrate -upgrade: python manage.py db upgrade +web: flask run +webhook: flask webhook +upgrade: flask db upgrade diff --git a/config.py b/config.py deleted file mode 100644 index 2872290..0000000 --- a/config.py +++ /dev/null @@ -1,17 +0,0 @@ -import os - - -basedir = os.path.abspath(os.path.dirname(__file__)) - - -class Config: - HOME_DIR = '/srv/math_bot' - - URL = os.environ.get('URL') - - TELEGRAM_TOKEN = os.environ.get('MATH_BOT_TOKEN') - WOLFRAM_APP_ID = os.environ.get('WOLFRAM_APP_ID') - - SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \ - 'sqlite:///' + os.path.join(basedir, 'app.db') - SQLALCHEMY_TRACK_MODIFICATIONS = False diff --git a/manage.py b/manage.py deleted file mode 100644 index 0ce7a4b..0000000 --- a/manage.py +++ /dev/null @@ -1,14 +0,0 @@ -from flask_script import Manager -from flask_migrate import Migrate, MigrateCommand - -from math_bot.app import app, db - - -migrate = Migrate(app, db) -manager = Manager(app) - -manager.add_command('db', MigrateCommand) - - -if __name__ == '__main__': - manager.run() diff --git a/math_bot/app.py b/math_bot/app.py deleted file mode 100644 index 58fe86b..0000000 --- a/math_bot/app.py +++ /dev/null @@ -1,12 +0,0 @@ -from flask import Flask -from flask_migrate import Migrate - -from math_bot.models import db -from config import Config - - -app = Flask(__name__) -app.config.from_object(Config) -db.app = app -db.init_app(app) -migrate = Migrate(app, db) diff --git a/migrations/README b/migrations/README old mode 100755 new mode 100644 diff --git a/migrations/env.py b/migrations/env.py old mode 100755 new mode 100644 index 23663ff..169d487 --- a/migrations/env.py +++ b/migrations/env.py @@ -1,8 +1,12 @@ from __future__ import with_statement -from alembic import context -from sqlalchemy import engine_from_config, pool -from logging.config import fileConfig + import logging +from logging.config import fileConfig + +from sqlalchemy import engine_from_config +from sqlalchemy import pool + +from alembic import context # this is the Alembic Config object, which provides # access to the values within the .ini file in use. @@ -41,7 +45,9 @@ def run_migrations_offline(): """ url = config.get_main_option("sqlalchemy.url") - context.configure(url=url) + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) with context.begin_transaction(): context.run_migrations() @@ -65,21 +71,23 @@ def process_revision_directives(context, revision, directives): directives[:] = [] logger.info('No changes in schema detected.') - engine = engine_from_config(config.get_section(config.config_ini_section), - prefix='sqlalchemy.', - poolclass=pool.NullPool) + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool, + ) - connection = engine.connect() - context.configure(connection=connection, - target_metadata=target_metadata, - process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args) + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions['migrate'].configure_args + ) - try: with context.begin_transaction(): context.run_migrations() - finally: - connection.close() + if context.is_offline_mode(): run_migrations_offline() diff --git a/migrations/script.py.mako b/migrations/script.py.mako old mode 100755 new mode 100644 diff --git a/migrations/versions/1ccf08c974d4_.py b/migrations/versions/f417e7b610f4_.py similarity index 90% rename from migrations/versions/1ccf08c974d4_.py rename to migrations/versions/f417e7b610f4_.py index fcbc0a6..a06143c 100644 --- a/migrations/versions/1ccf08c974d4_.py +++ b/migrations/versions/f417e7b610f4_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: 1ccf08c974d4 +Revision ID: f417e7b610f4 Revises: -Create Date: 2018-03-01 00:52:29.279182 +Create Date: 2019-02-28 16:20:39.378017 """ from alembic import op @@ -10,7 +10,7 @@ # revision identifiers, used by Alembic. -revision = '1ccf08c974d4' +revision = 'f417e7b610f4' down_revision = None branch_labels = None depends_on = None diff --git a/polling.py b/polling.py deleted file mode 100644 index b0d18fb..0000000 --- a/polling.py +++ /dev/null @@ -1,13 +0,0 @@ -import logging - -from math_bot.logic import init_updater - - -if __name__ == '__main__': - logging.basicConfig( - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - level=logging.INFO - ) - updater = init_updater() - updater.start_polling() - updater.idle() diff --git a/requirements.txt b/requirements.txt index f3a7214..24bccee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,29 +1,28 @@ -alembic==0.9.8 -certifi==2017.11.5 +alembic==1.0.7 +asn1crypto==0.24.0 +certifi==2018.11.29 +cffi==1.12.1 chardet==3.0.4 -click==6.7 -Flask==0.12.2 -Flask-Migrate==2.1.1 -Flask-Script==2.0.6 +Click==7.0 +cryptography==2.5 +Flask==1.0.2 +Flask-Migrate==2.4.0 Flask-SQLAlchemy==2.3.2 -future==0.16.0 -idna==2.6 -inflect==0.2.5 -itsdangerous==0.24 -jaraco.itertools==2.1 +future==0.17.1 +idna==2.8 +itsdangerous==1.1.0 Jinja2==2.10 Mako==1.0.7 -MarkupSafe==1.0 -more-itertools==4.0.1 -nginxparser-eb==0.0.9 -psycopg2==2.7.4 -pyparsing==2.2.0 -python-dateutil==2.6.1 -python-editor==1.0.3 -python-telegram-bot==10.0.1 -requests==2.18.4 -six==1.11.0 -SQLAlchemy==1.2.4 -urllib3==1.22 +MarkupSafe==1.1.1 +psycopg2==2.7.7 +pycparser==2.19 +python-dateutil==2.8.0 +python-dotenv==0.10.1 +python-editor==1.0.4 +python-telegram-bot==11.1.0 +requests==2.21.0 +six==1.12.0 +SQLAlchemy==1.2.18 +urllib3==1.24.1 Werkzeug==0.14.1 -xmltodict==0.11.0 +xmltodict==0.12.0 diff --git a/math_bot/__init__.py b/system/__init__.py similarity index 100% rename from math_bot/__init__.py rename to system/__init__.py diff --git a/system/app.py b/system/app.py new file mode 100644 index 0000000..42e27f0 --- /dev/null +++ b/system/app.py @@ -0,0 +1,19 @@ +from flask import Flask + +from system.db import db, migrate +from system.blueprints import register_blueprints +from system.commands import register_commands + + +def create_app(): + app = Flask(__name__) + app.url_map.strict_slashes = False + app.config.from_object('system.config') + + db.app = app + db.init_app(app) + migrate.init_app(app, db) + register_blueprints(app) + register_commands(app) + + return app diff --git a/system/blueprints.py b/system/blueprints.py new file mode 100644 index 0000000..3b870ad --- /dev/null +++ b/system/blueprints.py @@ -0,0 +1,9 @@ +from system.routes import system_blueprint + + +def register_blueprints(app): + with app.app_context(): + app.register_blueprint(system_blueprint) + + from telegram_bot.routes import telegram_blueprint + app.register_blueprint(telegram_blueprint, url_prefix='/telegram') diff --git a/system/commands.py b/system/commands.py new file mode 100644 index 0000000..a499901 --- /dev/null +++ b/system/commands.py @@ -0,0 +1,23 @@ +import click + +from flask.cli import with_appcontext + +import telegram_bot.polling +import telegram_bot.webhook + + +@click.command('polling') +@with_appcontext +def start_polling(): + telegram_bot.polling.start_polling() + + +@click.command('webhook') +@with_appcontext +def start_webhook(): + telegram_bot.webhook.set_webhook() + + +def register_commands(app): + app.cli.add_command(start_polling) + app.cli.add_command(start_webhook) diff --git a/system/config.py b/system/config.py new file mode 100644 index 0000000..9bab6df --- /dev/null +++ b/system/config.py @@ -0,0 +1,15 @@ +import os +import dotenv + + +BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +dotenv.load_dotenv(BASE_DIR) + +HOST_URL = os.getenv('HOST_URL') + +TELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN') +WOLFRAM_APP_ID = os.getenv('WOLFRAM_APP_ID') + +SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL') or \ + 'sqlite:///%s' % os.path.join(BASE_DIR, 'db.sqlite3') +SQLALCHEMY_TRACK_MODIFICATIONS = False diff --git a/system/db.py b/system/db.py new file mode 100644 index 0000000..1ce2ce3 --- /dev/null +++ b/system/db.py @@ -0,0 +1,6 @@ +from flask_sqlalchemy import SQLAlchemy +from flask_migrate import Migrate + + +db = SQLAlchemy() +migrate = Migrate() diff --git a/system/routes.py b/system/routes.py new file mode 100644 index 0000000..70414b9 --- /dev/null +++ b/system/routes.py @@ -0,0 +1,9 @@ +from flask import Blueprint + + +system_blueprint = Blueprint('system_routes', __name__) + + +@system_blueprint.route('/') +def index(): + return 'It works' diff --git a/telegram_bot/__init__.py b/telegram_bot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/telegram_bot/blueprint.py b/telegram_bot/blueprint.py new file mode 100644 index 0000000..f4975f6 --- /dev/null +++ b/telegram_bot/blueprint.py @@ -0,0 +1,9 @@ +from flask import Blueprint + +from utils.singleton import Singleton + + +@Singleton +class TelegramBlueprint(Blueprint): + def __init__(self, *args): + super().__init__('telegram_blueprint', __name__, *args) diff --git a/telegram_bot/bot.py b/telegram_bot/bot.py new file mode 100644 index 0000000..bb4f904 --- /dev/null +++ b/telegram_bot/bot.py @@ -0,0 +1,8 @@ +from telegram import Bot + +from utils.singleton import Singleton + + +@Singleton +class TelegramBot(Bot): + pass diff --git a/telegram_bot/dispatcher.py b/telegram_bot/dispatcher.py new file mode 100644 index 0000000..27ecbe8 --- /dev/null +++ b/telegram_bot/dispatcher.py @@ -0,0 +1,86 @@ +from threading import Thread +from queue import Queue + +from telegram.ext import CommandHandler, MessageHandler, Filters, \ + ConversationHandler, Dispatcher + +import telegram_bot.logic as logic +from telegram_bot.menu import MenuEntry + +from utils.singleton import Singleton + + +@Singleton +class DispatcherProxy(Dispatcher): + def __init__(self, bot, *args, **kwargs): + update_queue = Queue() + super().__init__(bot, update_queue, *args, **kwargs) + self._setup_dispatcher() + self._start_thread() + + def _setup_dispatcher(self): + conversation_handler = ConversationHandler( + entry_points=[ + CommandHandler('start', logic.handle_start), + MessageHandler(Filters.all, logic.handle_other_messages) + ], + states={ + MenuEntry.START_MENU.value: [ + MessageHandler(Filters.text, logic.handle_start_menu), + MessageHandler(Filters.all, logic.handle_other_messages) + ], + MenuEntry.MANUAL_QUERY.value: [ + MessageHandler(Filters.text, logic.handle_wolfram_request) + ], + MenuEntry.INTEGRAL.value: [ + MessageHandler(Filters.text, logic.handle_integral_query) + ], + MenuEntry.DERIVATIVE.value: [ + MessageHandler(Filters.text, logic.handle_derivative_query) + ], + MenuEntry.LIMIT.value: [ + MessageHandler(Filters.text, logic.handle_limit_query) + ], + MenuEntry.SUM.value: [ + MessageHandler(Filters.text, logic.handle_sum_query) + ], + MenuEntry.PLOT.value: [ + MessageHandler(Filters.text, logic.handle_plot_query) + ], + MenuEntry.EQUATION.value: [ + MessageHandler(Filters.text, logic.handle_equation_query) + ], + MenuEntry.TAYLOR_SERIES.value: [ + MessageHandler(Filters.text, + logic.handle_taylor_series_query) + ], + MenuEntry.EXTREMA.value: [ + MessageHandler(Filters.text, logic.handle_extrema_query) + ] + }, + fallbacks=[ + CommandHandler('cancel', logic.handle_cancel) + ] + ) + self.add_handler( + CommandHandler('help', logic.handle_help) + ) + self.add_handler( + CommandHandler('examples', logic.handle_examples) + ) + self.add_handler( + CommandHandler('simple_mode', logic.handle_simple_mode) + ) + self.add_handler( + CommandHandler('detailed_mode', logic.handle_detailed_mode) + ) + self.add_handler(conversation_handler) + self.add_error_handler(logic.handle_errors) + + def _start_thread(self): + dispatcher_thread = Thread( + target=self.start, + name='dispatcher', + daemon=True + ) + dispatcher_thread.start() diff --git a/math_bot/logic.py b/telegram_bot/logic.py similarity index 75% rename from math_bot/logic.py rename to telegram_bot/logic.py index 218a424..7b49d31 100644 --- a/math_bot/logic.py +++ b/telegram_bot/logic.py @@ -1,17 +1,16 @@ -from telegram import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove -from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, \ - ConversationHandler import logging -from math_bot.app import db -from math_bot.tools import send_typing, write_logs, remember_new_user -from math_bot.wolfram import make_wolfram_query -from math_bot.models import User -from config import Config +from telegram import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove +from telegram.ext import ConversationHandler + +from system.config import WOLFRAM_APP_ID +from system.db import db +from telegram_bot.tools import send_typing, write_logs, remember_new_user +from telegram_bot.models import User +from telegram_bot.menu import MenuEntry -START_MENU, MANUAL_QUERY, INTEGRAL, DERIVATIVE, LIMIT, SUM, \ - PLOT, EQUATION, TAYLOR_SERIES, EXTREMA, *_ = range(100) +from wolfram_tools.requests import make_wolfram_request @write_logs @@ -40,7 +39,7 @@ def handle_start(bot, update): text='Choose one of the following options', reply_markup=reply_markup ) - return START_MENU + return MenuEntry.START_MENU.value @write_logs @@ -76,7 +75,7 @@ def handle_manual_query(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return MANUAL_QUERY + return MenuEntry.MANUAL_QUERY.value @write_logs @@ -90,14 +89,14 @@ def handle_integral(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return INTEGRAL + return MenuEntry.INTEGRAL.value @write_logs @send_typing def handle_integral_query(bot, update): update.message.text = 'integrate {}'.format(update.message.text) - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -109,14 +108,14 @@ def handle_derivative(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return DERIVATIVE + return MenuEntry.DERIVATIVE.value @write_logs @send_typing def handle_derivative_query(bot, update): update.message.text = 'derivative {}'.format(update.message.text) - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -130,14 +129,14 @@ def handle_limit(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return LIMIT + return MenuEntry.LIMIT.value @write_logs @send_typing def handle_limit_query(bot, update): update.message.text = 'limit {}'.format(update.message.text) - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -151,14 +150,14 @@ def handle_sum(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return SUM + return MenuEntry.SUM.value @write_logs @send_typing def handle_sum_query(bot, update): update.message.text = 'sum {}'.format(update.message.text) - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -171,14 +170,14 @@ def handle_plot(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return PLOT + return MenuEntry.PLOT.value @write_logs @send_typing def handle_plot_query(bot, update): update.message.text = 'plot {}'.format(update.message.text) - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -191,13 +190,13 @@ def handle_equation(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return EQUATION + return MenuEntry.EQUATION.value @write_logs @send_typing def handle_equation_query(bot, update): - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -209,14 +208,14 @@ def handle_extrema(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return EXTREMA + return MenuEntry.EXTREMA.value @write_logs @send_typing def handle_extrema_query(bot, update): update.message.text = 'extrema {}'.format(update.message.text) - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -228,14 +227,14 @@ def handle_taylor_series(bot, update): chat_id=chat_id, reply_markup=ReplyKeyboardRemove() ) - return TAYLOR_SERIES + return MenuEntry.TAYLOR_SERIES.value @write_logs @send_typing def handle_taylor_series_query(bot, update): update.message.text = 'taylor series {}'.format(update.message.text) - return handle_wolfram_query(bot, update) + return handle_wolfram_request(bot, update) @write_logs @@ -309,13 +308,13 @@ def handle_simple_mode(bot, update): @write_logs @send_typing -def handle_wolfram_query(bot, update): +def handle_wolfram_request(bot, update): current_user = db.session.query(User).filter_by( telegram_id=update.message.from_user.id ).all()[0] chat_id = update.message.chat_id text = update.message.text - answer = make_wolfram_query(text) + answer = make_wolfram_request(text, WOLFRAM_APP_ID) if answer.error or not answer.success: bot.send_message( chat_id=chat_id, @@ -374,71 +373,3 @@ def handle_errors(bot, update, error): handle_start(bot, update) except Exception: pass - - -def init_updater(): - updater = Updater( - Config.TELEGRAM_TOKEN, - request_kwargs={ - 'read_timeout': 15, - 'connect_timeout': 15 - } - ) - dispatcher = updater.dispatcher - conversation_handler = ConversationHandler( - entry_points=[ - CommandHandler('start', handle_start), - MessageHandler(Filters.all, handle_other_messages) - ], - states={ - START_MENU: [ - MessageHandler(Filters.text, handle_start_menu), - MessageHandler(Filters.all, handle_other_messages) - ], - MANUAL_QUERY: [ - MessageHandler(Filters.text, handle_wolfram_query) - ], - INTEGRAL: [ - MessageHandler(Filters.text, handle_integral_query) - ], - DERIVATIVE: [ - MessageHandler(Filters.text, handle_derivative_query) - ], - LIMIT: [ - MessageHandler(Filters.text, handle_limit_query) - ], - SUM: [ - MessageHandler(Filters.text, handle_sum_query) - ], - PLOT: [ - MessageHandler(Filters.text, handle_plot_query) - ], - EQUATION: [ - MessageHandler(Filters.text, handle_equation_query) - ], - TAYLOR_SERIES: [ - MessageHandler(Filters.text, handle_taylor_series_query) - ], - EXTREMA: [ - MessageHandler(Filters.text, handle_extrema_query) - ] - }, - fallbacks=[ - CommandHandler('cancel', handle_cancel) - ] - ) - dispatcher.add_handler( - CommandHandler('help', handle_help) - ) - dispatcher.add_handler( - CommandHandler('examples', handle_examples) - ) - dispatcher.add_handler( - CommandHandler('simple_mode', handle_simple_mode) - ) - dispatcher.add_handler( - CommandHandler('detailed_mode', handle_detailed_mode) - ) - dispatcher.add_handler(conversation_handler) - dispatcher.add_error_handler(handle_errors) - return updater diff --git a/telegram_bot/menu.py b/telegram_bot/menu.py new file mode 100644 index 0000000..3d02bb0 --- /dev/null +++ b/telegram_bot/menu.py @@ -0,0 +1,27 @@ +from itertools import count +from enum import Enum + + +MenuEntry = Enum( + 'MenuEntry', + zip( + [ + 'START_MENU', + 'MANUAL_QUERY', + 'INTEGRAL', + 'DERIVATIVE', + 'LIMIT', + 'SUM', + 'PLOT', + 'EQUATION', + 'TAYLOR_SERIES', + 'EXTREMA', + ], + count() + ) +) + + +if __name__ == '__main__': + for entry in MenuEntry: + print("%s = %s" % (entry, entry.value)) diff --git a/math_bot/models.py b/telegram_bot/models.py similarity index 85% rename from math_bot/models.py rename to telegram_bot/models.py index 936a0df..1b316b5 100644 --- a/math_bot/models.py +++ b/telegram_bot/models.py @@ -1,7 +1,4 @@ -from flask_sqlalchemy import SQLAlchemy - - -db = SQLAlchemy() +from system.app import db class User(db.Model): diff --git a/telegram_bot/polling.py b/telegram_bot/polling.py new file mode 100644 index 0000000..2a81b86 --- /dev/null +++ b/telegram_bot/polling.py @@ -0,0 +1,25 @@ +import logging +import time + +from flask import current_app + +from telegram_bot.dispatcher import DispatcherProxy +from telegram_bot.bot import TelegramBot + + +def start_polling(): + logging.basicConfig( + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.INFO + ) + bot = TelegramBot(current_app.config['TELEGRAM_TOKEN']) + dispatcher = DispatcherProxy(bot) + current_offset = 0 + while True: + updates = bot.get_updates(offset=current_offset) + print(current_offset) + for update in updates: + print(updates) + dispatcher.update_queue.put(update) + current_offset = update.update_id + 1 + time.sleep(1) diff --git a/telegram_bot/routes.py b/telegram_bot/routes.py new file mode 100644 index 0000000..182309f --- /dev/null +++ b/telegram_bot/routes.py @@ -0,0 +1,27 @@ +from flask import current_app, request + +from telegram.update import Update + +from telegram_bot.blueprint import TelegramBlueprint +from telegram_bot.bot import TelegramBot +from telegram_bot.dispatcher import DispatcherProxy + + +telegram_blueprint = TelegramBlueprint() + + +@telegram_blueprint.route( + '/%s' % current_app.config['TELEGRAM_TOKEN'], + methods=['POST'] +) +def webhook(): + bot = TelegramBot(current_app.config['TELEGRAM_TOKEN']) + dispatcher = DispatcherProxy(bot) + update = Update.de_json(request.get_json(force=True), bot=bot) + dispatcher.update_queue.put(update) + return 'OK' + + +@telegram_blueprint.route('/') +def check(): + return 'Telegram bot works' diff --git a/math_bot/tools.py b/telegram_bot/tools.py similarity index 90% rename from math_bot/tools.py rename to telegram_bot/tools.py index 8001d94..24c1b88 100644 --- a/math_bot/tools.py +++ b/telegram_bot/tools.py @@ -1,9 +1,11 @@ import logging -from telegram import ChatAction from functools import wraps -from math_bot.app import db -from math_bot.models import User +from telegram import ChatAction + +from system.db import db + +from telegram_bot.models import User def send_typing(func): @@ -25,7 +27,7 @@ def decorated(bot, update): user_username = update.message.from_user.username action = update.message.text logging.info( - 'User %s:%s - %s' % (user_id, user_username, action) + 'User %s: %s - %s' % (user_id, user_username, action) ) return func(bot, update) return decorated diff --git a/telegram_bot/webhook.py b/telegram_bot/webhook.py new file mode 100644 index 0000000..7549901 --- /dev/null +++ b/telegram_bot/webhook.py @@ -0,0 +1,17 @@ +from flask import current_app + +from telegram_bot.bot import TelegramBot + + +def set_webhook(): + host_url = current_app.config['HOST_URL'] + host_port = current_app.config['HOST_PORT'] + telegram_token = current_app.config['TELEGRAM_TOKEN'] + bot = TelegramBot(telegram_token) + bot.set_webhook( + webhook_url='https://%s:%s/telegram/%s' % ( + host_url, + host_port, + telegram_token + ) + ) diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/singleton.py b/utils/singleton.py new file mode 100644 index 0000000..7ffcccd --- /dev/null +++ b/utils/singleton.py @@ -0,0 +1,9 @@ +class Singleton: + def __init__(self, klass): + self.klass = klass + self.instance = None + + def __call__(self, *args, **kwargs): + if not self.instance: + self.instance = self.klass(*args, **kwargs) + return self.instance diff --git a/webhook.py b/webhook.py deleted file mode 100644 index 18132a4..0000000 --- a/webhook.py +++ /dev/null @@ -1,22 +0,0 @@ -import logging -import os - -from math_bot.logic import init_updater -from config import Config - - -if __name__ == '__main__': - logging.basicConfig( - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - level=logging.INFO - ) - updater = init_updater() - updater.start_webhook( - listen='0.0.0.0', - port=int(os.environ.get('PORT', '8443')), - url_path=Config.TELEGRAM_TOKEN - ) - updater.bot.set_webhook( - url='{}/{}'.format(Config.URL, Config.TELEGRAM_TOKEN) - ) - updater.idle() diff --git a/wolfram_tools/__init__.py b/wolfram_tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/math_bot/wolfram.py b/wolfram_tools/requests.py similarity index 94% rename from math_bot/wolfram.py rename to wolfram_tools/requests.py index 2467192..1e0194d 100644 --- a/math_bot/wolfram.py +++ b/wolfram_tools/requests.py @@ -1,8 +1,20 @@ +from collections import OrderedDict + import requests + from xmltodict import parse -from collections import OrderedDict -from config import Config + +def make_wolfram_request(query, app_id): + params = { + 'input': query, + 'appid': app_id + } + answer = requests.get( + url='http://api.wolframalpha.com/v2/query', + params=params + ) + return WolframResult(parse(answer.content)) class WolframResult(OrderedDict): @@ -43,15 +55,3 @@ class WolframImage(OrderedDict): def __init__(self, parsed_img: OrderedDict): super().__init__(parsed_img) self.src = parsed_img['@src'] - - -def make_wolfram_query(query): - params = { - 'input': query, - 'appid': Config.WOLFRAM_APP_ID - } - answer = requests.get( - url='http://api.wolframalpha.com/v2/query', - params=params - ) - return WolframResult(parse(answer.content))