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-30 06:45:24 +00:00
__version__ = " 0.6.0 "
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-09 16:01:59 +00:00
import datetime as dt
2022-05-09 16:34:46 +00:00
import time
2022-05-28 20:59:51 +00:00
from xml . dom . pulldom import START_DOCUMENT
2022-05-02 15:04:54 +00:00
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
from telebot import types
2022-05-09 18:02:31 +00:00
from db import User , session , Product , Score
2022-05-03 10:07:54 +00:00
from fetcher import *
2022-05-28 09:44:23 +00:00
import helper_functions as hf
2022-05-28 20:59:51 +00:00
import scoring
2022-05-02 15:22:50 +00:00
2022-05-03 12:28:41 +00:00
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-29 18:31:52 +00:00
BOT_VERSION = " 0.6.5 " # version of bot
2022-05-28 20:59:51 +00:00
START_DAY = dt . time ( 8 , 0 , 0 )
END_DAY = dt . time ( 23 , 0 , 0 )
2022-05-02 15:04:54 +00:00
bot = telebot . TeleBot ( os . getenv ( ' BOT_API_KEY ' ) )
2022-05-28 14:09:53 +00:00
@bot.message_handler ( commands = [ ' version ' , ' Version ' ] )
def send_version ( message ) :
2022-05-30 06:45:24 +00:00
""" Sending program version
2022-05-28 14:09:53 +00:00
2022-05-30 06:45:24 +00:00
Args :
message ( Message ) : Message to react to in this case / version
2022-05-28 14:09:53 +00:00
"""
bot . reply_to ( message , " the current bot version is " + BOT_VERSION )
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-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Returns :
None : None
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Raises :
None : None
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
type / start as command in telegram as an unregistered user and check if bot responds with start message and waits for name
type / start as command in telegram as a registered user and check if bot responds with informing user about being already registered
2022-05-02 15:04:54 +00:00
"""
2022-05-16 16:07:09 +00:00
if message . from_user . id in session . query ( User . telegram_id ) . all ( ) :
bot . reply_to ( message , " You are already registered. Type /changename to change your name or /help for an overview of all commands " )
return
2022-05-27 21:36:23 +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-16 16:07:09 +00:00
Returns :
None : None
Raises :
None : None
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
check Regex pattern with incorrect patterns and test if these patterns are denied
check Regex pattern with correct patterns and test if these patterns are accepted
check if username is set in database after typing correct name
2022-05-03 11:20:49 +00:00
"""
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-16 16:27:02 +00:00
if not re . match ( r ' ^[a-zA-Z][a-zA-Z0-9 \ -]+$ ' , str ( message . text ) ) : # regex pattern for username: has to start with a letter, can contain letters, numbers and hyphen
bot . reply_to ( message , " Name has to be alphanumeric (including -) and start with a letter " )
2022-05-03 16:34:00 +00:00
return
2022-05-27 21:36:23 +00:00
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 )
2022-05-16 16:19:53 +00:00
session . add ( user ) # add user to database
session . commit ( ) # commit changes to database
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 :
2022-05-16 16:19:53 +00:00
session . rollback ( ) # rollback changes
2022-05-03 15:52:48 +00:00
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-16 16:07:09 +00:00
Test :
type / help as command in telegram and check if bot responds with help message
type / Help < text > as command in telegram and check if bot responds with help message , ignoring the text in message after command
2022-05-02 16:15:04 +00:00
"""
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 "
2022-05-27 21:36:23 +00:00
" /daily get todays challenge \n "
2022-05-09 18:02:31 +00:00
" /setAdmin set admin status of user (ADMIN) \n "
" /addproduct add product for further challenges (ADMIN) \n "
" /users get all users (ADMIN) \n " )
2022-05-16 16:07:09 +00:00
bot . reply_to ( message , help_message )
2022-05-02 16:33:08 +00:00
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
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
2022-05-27 21:36:23 +00:00
type / gameinfo or / Gameinfo as command in telegram and check if bot responds with game info message
2022-05-16 16:07:09 +00:00
type / gameInfo as command in telegramand check if bot responds with unknown command message
2022-05-02 16:45:32 +00:00
"""
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 "
2022-05-27 21:36:23 +00:00
" To see the challenge type /daily \n "
2022-05-02 16:45:32 +00:00
" To guess the price type /guess \n "
" At 22:00 pm the scores and answer will be shown \n " )
2022-05-16 16:07:09 +00:00
bot . reply_to ( message , gameinfo_message )
2022-05-02 16:45:32 +00:00
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
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
type / me as command in telegram as an registered User and check if bot responds with user info message
type / me as command in telegram as an unregistered User and check if bot responds with User does not exist message
2022-05-02 16:54:41 +00:00
"""
user_id = message . from_user . id
2022-05-16 16:19:53 +00:00
user = session . query ( User ) . filter ( User . telegram_id == user_id ) . first ( ) # get user from database, only one user per telegram id exists
scores = session . query ( Score ) . filter ( User . telegram_id == user_id ) . all ( ) # get all scores of user
2022-05-09 17:35:48 +00:00
today_score = session . query ( Score ) . filter ( Score . date == dt . datetime . now ( ) , Score . telegram_id == user_id ) . first ( ) # get today's score object for user
2022-05-09 16:08:31 +00:00
today_guess = " not guessed today "
if today_score is not None :
2022-05-16 16:19:53 +00:00
today_guess = str ( today_score . guess ) # get guess of today's score object of user
2022-05-03 16:46:06 +00:00
2022-05-16 16:19:53 +00:00
if user is not None : # if user is registered
2022-05-03 08:20:50 +00:00
user_name = user . username # tbd: get user name by id from db
2022-05-09 17:35:48 +00:00
user_score = sum ( score . score for score in scores ) # tbd: get user score by adding all scores related to userid
2022-05-09 16:08:31 +00:00
user_guess = today_guess # tbd: display if user has guessed today and how much
2022-05-03 08:20:50 +00:00
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 " )
2022-05-16 16:19:53 +00:00
else : # if user is not registered
2022-05-03 08:20:50 +00:00
# User not found
2022-05-09 16:01:59 +00:00
user_info = " User does not exist. "
2022-05-02 16:54:41 +00:00
2022-05-16 16:07:09 +00:00
bot . reply_to ( message , user_info )
2022-05-02 16:54:41 +00:00
2022-05-09 16:16:48 +00:00
@bot.message_handler ( commands = [ ' users ' , ' Users ' ] )
def send_users ( message ) :
""" send user info to user
Args : ( Message ) : Message from telegram user , here / users
Returns :
None : None
Raises :
None : None
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
type / users as command in telegram as an registered Admin and check if bot responds with user info messages
type / users as command in telegram as an an registered User where Admin = False and check if bot responds with " Admin rights are required to see all users " message
type / users as command in telegram as an an unregistered User and check if bot responds with " Admin rights are required to see all users " message
2022-05-09 16:16:48 +00:00
"""
user_id = message . from_user . id
2022-05-16 16:19:53 +00:00
# check if user exists
user = session . query ( User ) . filter ( User . telegram_id == user_id ) . first ( )
if not user or user is None : # should never happen, /start is required to chat, but just in case
bot . reply_to ( message , " Error: You are not registered, please register with /start " )
return
2022-05-09 16:16:48 +00:00
# Check if user is admin
2022-05-16 16:19:53 +00:00
if not session . query ( User ) . filter ( User . telegram_id == user_id ) . first ( ) . admin : # if user is not admin
2022-05-09 16:16:48 +00:00
bot . reply_to ( message , " Error: Admin rights are required to see all users. " )
return
2022-05-09 16:18:14 +00:00
users = session . query ( User ) . all ( )
2022-05-09 16:19:09 +00:00
2022-05-09 16:18:14 +00:00
if len ( users ) == 0 :
bot . reply_to ( message , " No users registered. " )
2022-05-09 16:16:48 +00:00
for user in users :
user_info = ( f " Telegram ID: { user . telegram_id } \n "
f " Username: { user . username } \n "
f " Admin: { user . admin } \n " )
2022-05-16 16:07:09 +00:00
bot . reply_to ( message , user_info )
2022-05-09 16:16:48 +00:00
2022-05-09 14:43:45 +00:00
@bot.message_handler ( commands = [ ' setAdmin ' , ' SetAdmin ' , ' Setadmin ' , ' setadmin ' ] )
def set_admin ( message ) :
""" set admin status of user
Args :
message ( Message ) : Message from telegram user , here / setAdmin
Returns :
None : None
Raises :
None : None
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
type / setAdmin as command in telegram as an registered Admin and check if bot requests id and boolean for changing admin status
type / setAdmin as command in telegram as an an registered User where Admin = False in db and check if bot responds with " Admin rights are required to change admin status " message
type / setAdmin as command in telegram as an an unregistered User and check if bot responds with " Admin rights are required to change admin status " message
2022-05-09 14:43:45 +00:00
"""
user_id = message . from_user . id
2022-05-09 14:57:17 +00:00
try :
2022-05-27 21:36:23 +00:00
2022-05-09 17:35:48 +00:00
user = session . query ( User ) . filter ( User . telegram_id == user_id ) . first ( )
2022-05-09 14:57:17 +00:00
2022-05-16 16:19:53 +00:00
if not user . admin : # admin is a boolean
2022-05-09 14:57:17 +00:00
bot . reply_to ( message , " Error: Admin rights are required to change admin rights of users. " )
return
2022-05-09 14:43:45 +00:00
2022-05-09 14:57:17 +00:00
if user . admin :
bot . reply_to ( message , " Type the telegram_id and boolean of admin attribute like <telegram_id> <value> " )
bot . register_next_step_handler ( message , set_admin_handler )
2022-05-27 21:36:23 +00:00
2022-05-09 14:57:17 +00:00
except sqlalchemy . exc . IntegrityError :
session . rollback ( )
bot . reply_to ( message , " Something went wrong. " )
2022-05-09 14:43:45 +00:00
def set_admin_handler ( message ) :
""" set admin status of user
2022-05-16 16:07:09 +00:00
Args :
message ( Message ) : Message from telegram user , here / setAdmin
2022-05-09 14:43:45 +00:00
2022-05-16 16:07:09 +00:00
Returns :
None : None
2022-05-09 14:43:45 +00:00
2022-05-16 16:07:09 +00:00
Raises :
None : None
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
type in correct regex pattern and check if bot sets admin status of user correctly
type in wrong regex pattern and check if bot responds with Invalid format message
test with incorrect user id and check if bot responds with User not registered message
2022-05-09 14:43:45 +00:00
"""
if not re . match ( r ' [0-9]* (True|False|true|false) ' , str ( message . text ) ) :
bot . reply_to ( message , " Error: Invalid format. Try again with /setAdmin " )
return
telegram_id , admin = str ( message . text ) . split ( sep = " " )
2022-05-16 16:19:53 +00:00
user = session . query ( User ) . filter ( User . telegram_id == telegram_id ) . first ( ) # get user from database, only one user per telegram id exists
2022-05-09 14:43:45 +00:00
2022-05-16 16:19:53 +00:00
if user is None or not user :
2022-05-09 14:43:45 +00:00
bot . reply_to ( message , " Error: User with entered telegram id is not registered. " )
return
2022-05-09 15:02:04 +00:00
2022-05-09 14:43:45 +00:00
try :
2022-05-09 15:02:04 +00:00
if admin in ( " True " , " true " ) :
2022-05-09 14:43:45 +00:00
user . admin = True
2022-05-09 15:02:04 +00:00
elif admin in ( " False " , " false " ) :
2022-05-09 14:43:45 +00:00
user . admin = False
2022-05-16 16:19:53 +00:00
session . commit ( ) # commit changes to database
2022-05-09 14:43:45 +00:00
bot . reply_to ( message , f " Admin rights of user { user . username } set to { user . admin } " )
except sqlalchemy . exc . IntegrityError :
session . rollback ( )
bot . reply_to ( message , " Something went wrong " )
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
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
type / scoreboard as command in telegram and check if bot responds with scoreboard with correct info and formatting
test with db with no Users and check if bot responds with " No users registered " message
2022-05-02 17:01:19 +00:00
"""
2022-05-09 17:35:48 +00:00
alltime_board = [ ]
weekly_board = [ ]
users = session . query ( User ) . all ( )
if users is None :
bot . reply_to ( message , " No users registered. " )
return
# generate alltime scoreboard
for user in users :
telegram_id = user . telegram_id
2022-05-16 16:19:53 +00:00
user_scores = session . query ( Score ) . filter ( Score . telegram_id == telegram_id ) . all ( ) # get all scores of user
2022-05-27 21:36:23 +00:00
2022-05-09 17:35:48 +00:00
if user_scores is None :
continue
2022-05-16 16:19:53 +00:00
alltime_score = sum ( score . score for score in user_scores ) # sum all scores of user
alltime_board . append ( ( user . username , alltime_score ) ) # append to alltime scoreboard
2022-05-09 17:35:48 +00:00
# generate weekly scoreboard
for user in users :
telegram_id = user . telegram_id
2022-05-09 18:02:31 +00:00
print ( session . query ( Score ) . all ( ) )
all_user_scores = session . query ( Score ) . filter ( Score . telegram_id == telegram_id ) . all ( ) # get all user scores
user_scores = None # initialize variable
if all_user_scores is not None :
user_scores = [ score for score in all_user_scores if score . date . date ( ) . isocalendar ( ) . week == dt . date . today ( ) . isocalendar ( ) . week ] # get user scores for today
2022-05-09 17:35:48 +00:00
if user_scores is None :
continue
2022-05-27 21:36:23 +00:00
2022-05-09 17:35:48 +00:00
weekly_score = sum ( score . score for score in user_scores )
weekly_board . append ( ( user . username , weekly_score ) )
# sort scoreboards
alltime_board . sort ( key = lambda x : x [ 1 ] , reverse = True )
weekly_board . sort ( key = lambda x : x [ 1 ] , reverse = True )
2022-05-09 18:02:31 +00:00
str_alltime_board = " *Scoreboard (AllTime)*: \n "
str_weekly_board = " *Scoreboard (Weekly)*: \n "
2022-05-09 17:35:48 +00:00
for user in alltime_board :
2022-05-09 18:02:31 +00:00
str_alltime_board + = f " \n { user [ 1 ] } _( { user [ 0 ] } )_ "
2022-05-09 17:35:48 +00:00
if len ( alltime_board ) == 0 :
2022-05-09 18:02:31 +00:00
bot . reply_to ( message , str_alltime_board + " \n No users have scored yet. " , parse_mode = ' MARKDOWN ' )
2022-05-09 17:35:48 +00:00
else :
2022-05-09 18:02:31 +00:00
bot . reply_to ( message , str_alltime_board , parse_mode = ' MARKDOWN ' )
2022-05-09 17:35:48 +00:00
for user in weekly_board :
2022-05-09 18:02:31 +00:00
str_weekly_board + = f " \n { user [ 1 ] } _( { user [ 0 ] } )_ "
2022-05-09 17:35:48 +00:00
if len ( weekly_board ) == 0 :
2022-05-09 18:02:31 +00:00
bot . reply_to ( message , str_weekly_board + " \n No users have scored yet. " , parse_mode = ' MARKDOWN ' )
2022-05-27 21:36:23 +00:00
2022-05-09 17:35:48 +00:00
else :
2022-05-09 18:02:31 +00:00
bot . reply_to ( message , str_weekly_board , parse_mode = ' MARKDOWN ' )
2022-05-09 17:35:48 +00:00
2022-05-09 16:34:46 +00:00
@bot.message_handler ( commands = [ ' changename ' , ' Changename ' ] )
def change_name ( message ) :
""" change user name
2022-05-02 17:01:19 +00:00
Args :
2022-05-09 16:34:46 +00:00
message ( Message ) : Message from telegram user , here / changename
2022-05-02 17:01:19 +00:00
Returns :
None : None
Raises :
None : None
2022-05-16 16:07:09 +00:00
Test :
type / changename as command in telegram and check if bot sends change name request message
type / Changename as command in telegram and check if bot sends change name request message
2022-05-02 17:01:19 +00:00
"""
2022-05-09 16:34:46 +00:00
bot . reply_to ( message , " type new name (else type \" cancel \" ): " )
2022-05-16 16:19:53 +00:00
bot . register_next_step_handler ( message , change_name_setter ) # register next step handler, send message and take users answer as input for change_name_setter
2022-05-16 16:07:09 +00:00
def change_name_setter ( message ) :
""" change user name
Args :
message ( Message ) : Message to react to
Returns :
None : None
Raises :
None : None
2022-05-27 21:36:23 +00:00
2022-05-16 16:07:09 +00:00
Test :
type in correct regex pattern and check if bot changes user name correctly , also in db
type in wrong regex pattern and check if bot responds with Invalid format message
type cancel and check that name is not changed in db and bot responds with " Name not changed " message
"""
if str ( message . text ) . lower ( ) == " cancel " : # Set user name to user
bot . reply_to ( message , " Name not changed " )
return
2022-05-16 16:27:02 +00:00
if not re . match ( r ' ^[a-zA-Z][a-zA-Z0-9 \ -]+$ ' , str ( message . text ) ) : # same pattern as in /start
bot . reply_to ( message , " Name has to be alphanumeric (including -) and start with a letter " )
2022-05-16 16:07:09 +00:00
return
else :
user_id = int ( message . from_user . id )
user_name = str ( message . text )
try :
user = session . query ( User ) . filter ( User . 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-14 19:33:13 +00:00
def time_in_range ( start , end , current ) :
2022-05-16 16:19:53 +00:00
""" Returns whether current is in the range [start, end] """ # docstring is missing!!!!!
2022-05-14 19:33:13 +00:00
return start < = current < = end
2022-05-27 21:36:23 +00:00
2022-05-28 09:44:23 +00:00
def find_todays_product_from_db ( ) :
""" Find todays product from db based on todays_product
"""
product = None
for element in session . query ( Product ) . all ( ) :
if element . todays_product :
product = element
break
return product
2022-05-09 16:34:46 +00:00
@bot.message_handler ( commands = [ ' daily ' , ' Daily ' ] )
def daily_message ( message ) :
2022-05-28 09:44:23 +00:00
""" send daily challenge
2022-05-02 17:01:19 +00:00
Args :
2022-05-28 09:44:23 +00:00
message ( Message ) : Message from telegram user , here / daily
2022-05-02 17:01:19 +00:00
Returns :
None : None
Raises :
None : None
2022-05-30 06:45:24 +00:00
Test :
type / daily as command in telegram and check if bot sends daily challenge message
type / daily again for message that you already played today and your guess
2022-05-02 17:01:19 +00:00
"""
2022-05-09 16:34:46 +00:00
user_id = int ( message . from_user . id )
2022-05-27 21:36:23 +00:00
2022-05-28 14:09:53 +00:00
current = dt . datetime . now ( ) . time ( )
2022-05-27 21:36:23 +00:00
2022-05-28 20:59:51 +00:00
if not time_in_range ( START_DAY , END_DAY , current ) :
2022-05-14 19:33:13 +00:00
bot . send_message ( chat_id = user_id , text = " Currently there is no challenge. \n \n "
" Times are 8am to 10pm. " )
return
2022-05-27 21:36:23 +00:00
2022-05-29 07:32:19 +00:00
# Check if user already guessed today by date, time and user_id
all_scores_user = session . query ( Score ) . filter (
Score . telegram_id == user_id
) . all ( )
for element in all_scores_user :
if element . date . date ( ) == dt . datetime . now ( ) . date ( ) :
2022-05-29 18:31:52 +00:00
bot . send_message ( chat_id = user_id , text = " You already guessed today! \n "
2022-05-30 06:45:24 +00:00
f " Your guess was: { element . guess } " )
2022-05-29 07:32:19 +00:00
return
2022-05-09 16:34:46 +00:00
bot . send_message ( chat_id = user_id , text = " Welcome to todays challenge! \n "
" As soon as the picture loads \n "
2022-05-28 20:59:51 +00:00
" you will have 20 seconds to send \n "
2022-05-09 16:34:46 +00:00
" your price guess \n " )
2022-05-27 21:36:23 +00:00
2022-05-09 16:34:46 +00:00
time . sleep ( 2 )
2022-05-27 21:36:23 +00:00
2022-05-09 16:34:46 +00:00
bot . send_message ( chat_id = user_id , text = " Lets Go! " )
2022-05-27 21:36:23 +00:00
2022-05-09 16:34:46 +00:00
time . sleep ( 1 )
2022-05-27 21:36:23 +00:00
2022-05-09 16:34:46 +00:00
for i in range ( 3 ) :
iteration = 3 - i
bot . send_message ( chat_id = user_id , text = str ( iteration ) )
iteration - = 1
time . sleep ( 1 )
2022-05-02 17:01:19 +00:00
2022-05-28 13:27:55 +00:00
try :
product_for_today = find_todays_product_from_db ( )
2022-05-29 07:32:19 +00:00
bot . send_message ( chat_id = user_id , text = str (
hf . make_markdown_proof ( product_for_today . image_link )
) , parse_mode = " MARKDOWNV2 " )
2022-05-29 10:40:35 +00:00
bot . send_message ( chat_id = user_id , text = product_for_today . title )
2022-05-28 13:27:55 +00:00
start_time = time . time ( )
2022-05-28 20:59:51 +00:00
# next step with message and start time
bot . register_next_step_handler ( message , get_user_guess , start_time )
except ( TypeError , AttributeError ) as exception_message :
print ( exception_message )
bot . send_message ( chat_id = user_id , text = " An Error occured. Please try again later. " )
2022-05-28 09:44:23 +00:00
def get_time_difference ( start_time , end_time ) :
""" Get time difference
"""
return end_time - start_time
def get_user_guess ( message , start_time ) :
""" Get users guess after typing /daily
Args :
message ( Message ) : Message element to react to . In this case next step after / daily
start_time ( time . time ) : Time the user got the image
2022-05-30 06:45:24 +00:00
Test :
Send a price and see if the bot responds correctly ( guess accepted )
Send text withwith wrong format ( right format = number fitting for float ) and see if bot notices and gives you another try
See if score changes after you guessed ( only if you guessed somewhat correctly so your score is not 0 )
2022-05-28 09:44:23 +00:00
"""
end_time = time . time ( )
user_id = int ( message . from_user . id )
2022-05-28 20:59:51 +00:00
2022-05-29 07:32:19 +00:00
2022-05-28 20:59:51 +00:00
try :
user_guess = float ( message . text )
except ValueError :
bot . send_message ( chat_id = user_id , text = " Please type a number (or float with ' . ' ) " )
bot . register_next_step_handler ( message , get_user_guess , start_time )
return
2022-05-29 07:32:19 +00:00
2022-05-28 20:59:51 +00:00
if get_time_difference ( start_time , end_time ) > 20 :
2022-05-28 09:44:23 +00:00
bot . send_message ( chat_id = user_id , text = " You took too long to guess. \n "
" No more tries today. " )
return
2022-05-28 20:59:51 +00:00
message_text = f " You guessed { round ( user_guess , 2 ) } € "
bot . send_message ( chat_id = user_id , text = message_text )
# calculate score for guess
product_for_today = find_todays_product_from_db ( )
user_score = scoring . eval_score ( product_for_today . price , user_guess )
score = Score (
telegram_id = user_id ,
date = dt . date . today ( ) ,
product_id = product_for_today . product_id ,
guess = user_guess ,
score = user_score
)
session . add ( score )
session . commit ( )
2022-05-28 09:44:23 +00:00
2022-05-02 17:01:19 +00:00
2022-05-27 21:36:23 +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-09 14:19:32 +00:00
user_id = message . from_user . id
# Check if user is admin
2022-05-21 09:41:20 +00:00
if not session . query ( User ) . filter ( User . telegram_id == user_id ) . first ( ) . admin :
2022-05-09 14:19:32 +00:00
bot . reply_to ( message , " Error: Admin rights are required to add products " )
return
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 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 )
2022-05-10 12:00:41 +00:00
image_url = get_image ( product_src )
2022-05-03 10:07:54 +00:00
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 ' )
2022-05-21 09:41:20 +00:00
except pymysql . err . OperationalError :
session . rollback ( )
bot . send_message ( chat_id = user_id , text = ' Unknown error ' )
2022-05-03 10:07:54 +00:00
@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-28 14:09:53 +00:00
@bot.message_handler ( func = lambda message : True ) # Returning that command is unknown for any other statement
def echo_all ( message ) :
""" Echo all other messages
Args :
message ( Message ) : user message that doesnt match any of the commands
"""
answer = ' Do not know this command or text: ' + message . text
bot . reply_to ( message , answer )
2022-05-03 10:07:54 +00:00
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: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
"""
2022-05-09 18:05:42 +00:00
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 ( ' \n Exiting by user request. \n ' )
2022-05-02 15:22:50 +00:00
sys . exit ( 0 )