2022-05-02 15:04:54 +00:00
|
|
|
"""
|
|
|
|
script for telegram bot and its functions
|
|
|
|
"""
|
|
|
|
__author__ = "Florian Kellermann, Linus Eickhoff, Florian Kaiser"
|
|
|
|
__date__ = "02.05.2022"
|
2022-05-02 15:22:50 +00:00
|
|
|
__version__ = "0.0.1"
|
2022-05-02 15:04:54 +00:00
|
|
|
__license__ = "None"
|
|
|
|
|
|
|
|
# main bot at http://t.me/guess_the_price_bot
|
|
|
|
# debug bot at http://t.me/amazondebug_bot
|
|
|
|
|
2022-05-02 15:07:28 +00:00
|
|
|
import logging
|
2022-05-02 15:04:54 +00:00
|
|
|
import os
|
2022-05-03 16:34:00 +00:00
|
|
|
import re
|
2022-05-02 15:04:54 +00:00
|
|
|
import sys
|
|
|
|
|
2022-05-03 10:07:54 +00:00
|
|
|
import sqlalchemy
|
2022-05-02 15:22:50 +00:00
|
|
|
import telebot
|
|
|
|
from dotenv import load_dotenv
|
2022-05-03 12:28:41 +00:00
|
|
|
from sqlalchemy.exc import IntegrityError
|
2022-05-02 15:22:50 +00:00
|
|
|
from telebot import types
|
2022-05-03 15:52:48 +00:00
|
|
|
from random import randrange
|
2022-05-02 15:22:50 +00:00
|
|
|
|
2022-05-03 10:07:54 +00:00
|
|
|
from db import User, session, Product
|
|
|
|
from fetcher import *
|
2022-05-03 16:46:06 +00:00
|
|
|
from source.db import Score
|
2022-05-02 15:22:50 +00:00
|
|
|
|
2022-05-03 12:28:41 +00:00
|
|
|
# from apscheduler.schedulers.background import BackgroundScheduler
|
|
|
|
|
2022-05-02 15:22:50 +00:00
|
|
|
load_dotenv(dotenv_path='.env') # load environment variables
|
2022-05-02 15:04:54 +00:00
|
|
|
|
2022-05-02 15:46:04 +00:00
|
|
|
BOT_VERSION = "0.0.1" # version of bot
|
2022-05-02 15:04:54 +00:00
|
|
|
|
|
|
|
bot = telebot.TeleBot(os.getenv('BOT_API_KEY'))
|
|
|
|
|
2022-05-02 15:22:50 +00:00
|
|
|
|
|
|
|
@bot.message_handler(commands=['start', 'Start'])
|
2022-05-02 15:04:54 +00:00
|
|
|
def send_start(message):
|
2022-05-02 16:15:04 +00:00
|
|
|
"""send start message to user
|
2022-05-02 15:04:54 +00:00
|
|
|
|
2022-05-02 16:15:04 +00:00
|
|
|
Args:
|
|
|
|
message (Message): message from telegram user, here /start
|
2022-05-02 15:04:54 +00:00
|
|
|
"""
|
2022-05-03 12:28:41 +00:00
|
|
|
bot.send_message(chat_id=int(message.from_user.id), text=("Welcome to the game... \
|
2022-05-03 16:12:01 +00:00
|
|
|
\nTo start please set a name for yourself or type cancel to set generated name:"))
|
2022-05-03 12:28:41 +00:00
|
|
|
|
2022-05-03 11:20:49 +00:00
|
|
|
bot.register_next_step_handler(message, start_name_setter)
|
2022-05-03 12:28:41 +00:00
|
|
|
|
|
|
|
|
2022-05-03 11:20:49 +00:00
|
|
|
def start_name_setter(message):
|
|
|
|
"""Set name for user and send introduction
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message to react to
|
|
|
|
"""
|
2022-05-03 15:52:48 +00:00
|
|
|
user_id = int(message.from_user.id)
|
|
|
|
user_name = ""
|
|
|
|
|
2022-05-03 16:34:00 +00:00
|
|
|
if str(message.text).lower() == "cancel": # Set user name to user
|
2022-05-03 16:12:01 +00:00
|
|
|
user_name = "User" + str(user_id) # generate user name, user can change it with /changename
|
2022-05-03 15:52:48 +00:00
|
|
|
|
2022-05-03 16:34:00 +00:00
|
|
|
if not re.match(r'^[a-zA-Z][a-zA-Z0-9_]+$', str(message.text)):
|
|
|
|
bot.reply_to(message, "Name has to be alphanumeric (including underscores) and start with a letter")
|
|
|
|
return
|
2022-05-06 20:26:37 +00:00
|
|
|
|
|
|
|
user_name = str(message.text)
|
2022-05-02 15:22:50 +00:00
|
|
|
|
2022-05-03 15:52:48 +00:00
|
|
|
try:
|
|
|
|
user = User(telegram_id=user_id, username=user_name, admin=False)
|
|
|
|
session.add(user)
|
|
|
|
session.commit()
|
2022-05-03 16:34:00 +00:00
|
|
|
bot.reply_to(message, f"Thank you for setting your name {user_name} \
|
|
|
|
\nType /gameinfo for information about GuessThePrice \
|
|
|
|
\nType /help for an overview of all commands")
|
2022-05-03 15:52:48 +00:00
|
|
|
|
|
|
|
except sqlalchemy.exc.IntegrityError:
|
|
|
|
session.rollback()
|
|
|
|
bot.reply_to(message, "You are already registered, change name with /changename")
|
|
|
|
|
2022-05-02 15:22:50 +00:00
|
|
|
|
2022-05-02 15:07:28 +00:00
|
|
|
telebot.logger.setLevel(logging.DEBUG)
|
2022-05-02 15:22:50 +00:00
|
|
|
|
|
|
|
|
2022-05-02 16:15:04 +00:00
|
|
|
@bot.message_handler(commands=['help', 'Help'])
|
|
|
|
def send_help(message):
|
|
|
|
"""send all commands to user
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /help
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
2022-05-02 16:33:08 +00:00
|
|
|
help_message = ("/me get my user info\n"
|
|
|
|
"/help get this help message\n"
|
|
|
|
"/gameinfo get game info\n"
|
|
|
|
"/scoreboard get scoreboard\n"
|
|
|
|
"/changename change your name\n"
|
|
|
|
"/challenge get todays challenge\n"
|
|
|
|
"/guess make guess for today")
|
|
|
|
bot.reply_to(message, help_message, parse_mode='MARKDOWN')
|
|
|
|
|
|
|
|
|
2022-05-02 16:45:32 +00:00
|
|
|
@bot.message_handler(commands=['gameinfo', 'Gameinfo'])
|
|
|
|
def send_gameinfo(message):
|
|
|
|
"""send game info to user
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /gameinfo
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
|
|
|
gameinfo_message = ("GuessThePrice is a game where you have to guess\n"
|
|
|
|
"the price of an amazon product.\n"
|
|
|
|
"Start by setting your name with /changename\n"
|
|
|
|
"You can get a new challenge every day.\n"
|
|
|
|
"You are informed when a new challenge is available.\n"
|
|
|
|
"To see the challenge type /challenge\n"
|
|
|
|
"To guess the price type /guess\n"
|
|
|
|
"At 22:00 pm the scores and answer will be shown\n")
|
|
|
|
bot.reply_to(message, gameinfo_message, parse_mode='MARKDOWN')
|
|
|
|
|
|
|
|
|
2022-05-02 16:54:41 +00:00
|
|
|
@bot.message_handler(commands=['me', 'Me'])
|
|
|
|
def send_user_info(message):
|
|
|
|
"""send user info to user
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /me
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
|
|
|
user_id = message.from_user.id
|
2022-05-03 08:20:50 +00:00
|
|
|
user = session.query(User).filter_by(telegram_id=user_id).first()
|
2022-05-03 16:46:06 +00:00
|
|
|
|
2022-05-03 08:20:50 +00:00
|
|
|
if user is not None:
|
|
|
|
user_name = user.username # tbd: get user name by id from db
|
2022-05-03 16:46:06 +00:00
|
|
|
user_score = sum(0) # tbd: get user score by adding all scores related to userid
|
2022-05-03 08:20:50 +00:00
|
|
|
user_guess = 0.0 # tbd: display if user has guessed today and how much
|
|
|
|
user_info = (f"Your user info:\n"
|
|
|
|
f"User ID: {user_id}\n"
|
|
|
|
f"Username: {user_name}\n"
|
|
|
|
f"Today's guess: {user_guess}\n"
|
|
|
|
f"Your Score: {user_score}\n")
|
|
|
|
else:
|
|
|
|
# User not found
|
|
|
|
user_info = f"User does not exist."
|
2022-05-02 16:54:41 +00:00
|
|
|
|
|
|
|
bot.reply_to(message, user_info, parse_mode='MARKDOWN')
|
|
|
|
|
|
|
|
|
2022-05-02 17:01:19 +00:00
|
|
|
@bot.message_handler(commands=['scoreboard', 'Scoreboard'])
|
|
|
|
def send_scoreboard(message):
|
|
|
|
"""send scoreboard to user
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /scoreboard
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
|
|
|
bot.reply_to(message, "Scoreboard not implemented yet")
|
|
|
|
|
|
|
|
|
|
|
|
@bot.message_handler(commands=['challenge', 'Challenge'])
|
|
|
|
def send_challenge(message):
|
|
|
|
"""send challenge to user
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /challenge
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
|
|
|
bot.reply_to(message, "Challenge not implemented yet")
|
|
|
|
|
|
|
|
|
|
|
|
@bot.message_handler(commands=['guess', 'Guess'])
|
|
|
|
def send_guess(message):
|
|
|
|
"""send guess to user
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /guess
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
|
|
|
bot.reply_to(message, "Guess not implemented yet")
|
|
|
|
|
|
|
|
|
|
|
|
@bot.message_handler(commands=['changename', 'Changename'])
|
|
|
|
def change_name(message):
|
|
|
|
"""change user name
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /changename
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
2022-05-03 16:34:00 +00:00
|
|
|
|
|
|
|
bot.reply_to(message, "type new name (else type \"cancel\"):")
|
|
|
|
bot.register_next_step_handler(message, change_name_setter)
|
|
|
|
|
|
|
|
|
|
|
|
def change_name_setter(message):
|
|
|
|
"""change user name
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message to react to
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
if str(message.text).lower() == "cancel": # Set user name to user
|
|
|
|
bot.reply_to(message, "Name not changed")
|
|
|
|
return
|
|
|
|
|
|
|
|
if not re.match(r'^[a-zA-Z][a-zA-Z0-9_]+$', str(message.text)):
|
|
|
|
bot.reply_to(message, "Name has to be alphanumeric (including underscores) and start with a letter")
|
|
|
|
return
|
|
|
|
|
|
|
|
else:
|
|
|
|
user_id = int(message.from_user.id)
|
|
|
|
user_name = str(message.text)
|
|
|
|
try:
|
|
|
|
user = session.query(User).filter_by(telegram_id=user_id).first()
|
|
|
|
user.username = user_name
|
|
|
|
session.commit()
|
|
|
|
bot.reply_to(message, f"Your name has been changed to {user_name}")
|
|
|
|
|
|
|
|
except sqlalchemy.exc.IntegrityError:
|
|
|
|
session.rollback()
|
|
|
|
bot.reply_to(message, "Something went wrong")
|
2022-05-02 17:01:19 +00:00
|
|
|
|
|
|
|
|
2022-05-03 10:07:54 +00:00
|
|
|
@bot.message_handler(commands=['addproduct', 'Addproduct'])
|
|
|
|
def add_product(message):
|
|
|
|
"""Add product to database
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message from telegram user, here /addproduct
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
None: None
|
|
|
|
|
|
|
|
"""
|
2022-05-03 12:28:41 +00:00
|
|
|
# TODO: Check if user is admin
|
2022-05-03 10:07:54 +00:00
|
|
|
user_id = int(message.from_user.id)
|
|
|
|
bot.send_message(chat_id=user_id, text='Please insert the Amazon product id (i.e. B00XKZYZ2S)')
|
|
|
|
bot.register_next_step_handler(message, receive_product_data) # executes function when user sends message
|
|
|
|
|
|
|
|
|
|
|
|
def receive_product_data(message):
|
2022-05-06 20:26:37 +00:00
|
|
|
""" registering new product in the db and fetching it from amazon
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (Message): Message that is being reacted to. Always from add_product because of next_step_handler
|
|
|
|
"""
|
2022-05-03 12:28:41 +00:00
|
|
|
# TODO: Check if user is admin
|
2022-05-03 10:07:54 +00:00
|
|
|
user_id = int(message.from_user.id)
|
|
|
|
product_id = str(message.text)
|
|
|
|
|
|
|
|
product_src = fetch_url('https://www.amazon.de/dp/' + product_id)
|
|
|
|
|
|
|
|
title = get_title(product_src)
|
|
|
|
image_url = get_image(product_src, get_title(product_src))
|
|
|
|
price = get_price(product_src)
|
|
|
|
description = get_description(product_src)
|
|
|
|
|
|
|
|
bot.send_message(chat_id=user_id, text=title)
|
|
|
|
bot.send_message(chat_id=user_id, text=image_url)
|
|
|
|
bot.send_message(chat_id=user_id, text=price)
|
|
|
|
bot.send_message(chat_id=user_id, text=description)
|
|
|
|
|
|
|
|
# markup = InlineKeyboardMarkup()
|
|
|
|
# markup.row_width = 2
|
|
|
|
# markup.add(InlineKeyboardButton("Yes", callback_data="cb_yes"),
|
|
|
|
# InlineKeyboardButton("No", callback_data="cb_no"))
|
|
|
|
#
|
|
|
|
# bot.send_message(chat_id=user_id, text="Is this the product you want to add?", reply_markup=markup)
|
|
|
|
|
|
|
|
# Insert into database
|
|
|
|
try:
|
|
|
|
product = Product(
|
|
|
|
product_id=product_id,
|
|
|
|
title=title,
|
|
|
|
image_link=image_url,
|
|
|
|
price=price[0],
|
|
|
|
currency=price[1],
|
|
|
|
description=description
|
|
|
|
)
|
|
|
|
session.add(product)
|
|
|
|
session.commit()
|
|
|
|
|
|
|
|
bot.send_message(chat_id=user_id, text='Successfully added product to database')
|
|
|
|
except sqlalchemy.exc.IntegrityError:
|
|
|
|
session.rollback()
|
|
|
|
bot.send_message(chat_id=user_id, text='Product is in database already')
|
|
|
|
|
|
|
|
|
|
|
|
@bot.callback_query_handler(func=lambda call: True)
|
|
|
|
def callback_query(call):
|
|
|
|
if call.data == "cb_yes":
|
|
|
|
bot.answer_callback_query(call.id, "Answer is Yes")
|
|
|
|
elif call.data == "cb_no":
|
|
|
|
bot.answer_callback_query(call.id, "Answer is No")
|
|
|
|
|
|
|
|
|
2022-05-02 16:33:08 +00:00
|
|
|
# inline prints for debugging
|
|
|
|
@bot.inline_handler(lambda query: query.query == 'text')
|
2022-05-02 15:04:54 +00:00
|
|
|
def query_text(inline_query):
|
2022-05-02 16:17:07 +00:00
|
|
|
"""inline query handler for debugging
|
2022-05-02 15:04:54 +00:00
|
|
|
|
2022-05-02 16:17:07 +00:00
|
|
|
Args:
|
|
|
|
inline_query (InlineQuery): inline query from telegram user
|
2022-05-02 16:33:08 +00:00
|
|
|
|
2022-05-02 16:17:07 +00:00
|
|
|
Returns:
|
|
|
|
None: None
|
2022-05-02 16:33:08 +00:00
|
|
|
|
2022-05-02 16:17:07 +00:00
|
|
|
Raises:
|
|
|
|
None: None
|
2022-05-02 15:04:54 +00:00
|
|
|
"""
|
|
|
|
try:
|
2022-05-02 16:33:08 +00:00
|
|
|
r = types.InlineQueryResultArticle('1', 'Result1', types.InputTextMessageContent(
|
|
|
|
'hi')) # pylint: disable=invalid-name
|
|
|
|
r2 = types.InlineQueryResultArticle(
|
|
|
|
'2', 'Result2', types.InputTextMessageContent('hi')) # pylint: disable=invalid-name
|
2022-05-02 15:04:54 +00:00
|
|
|
bot.answer_inline_query(inline_query.id, [r, r2])
|
2022-05-02 16:33:08 +00:00
|
|
|
except Exception as e: # pylint: disable=broad-except, invalid-name
|
2022-05-02 15:04:54 +00:00
|
|
|
print(e)
|
|
|
|
|
2022-05-02 15:22:50 +00:00
|
|
|
|
2022-05-02 15:04:54 +00:00
|
|
|
def main_loop():
|
2022-05-02 16:12:06 +00:00
|
|
|
# nur zum ärgern
|
2022-05-02 16:17:07 +00:00
|
|
|
"""main loop for bot
|
2022-05-02 15:04:54 +00:00
|
|
|
|
2022-05-02 16:17:07 +00:00
|
|
|
Args:
|
|
|
|
None: None
|
2022-05-02 16:33:08 +00:00
|
|
|
|
2022-05-02 16:17:07 +00:00
|
|
|
Returns:
|
|
|
|
None: None
|
2022-05-02 16:33:08 +00:00
|
|
|
|
2022-05-02 16:17:07 +00:00
|
|
|
Raises:
|
|
|
|
None: None
|
2022-05-02 15:04:54 +00:00
|
|
|
"""
|
|
|
|
bot.infinity_polling()
|
|
|
|
|
2022-05-02 15:22:50 +00:00
|
|
|
|
2022-05-02 15:04:54 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
try:
|
|
|
|
main_loop()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
print('\nExiting by user request.\n')
|
2022-05-02 15:22:50 +00:00
|
|
|
sys.exit(0)
|