1
0
mirror of https://gitlab.com/questable/questable_bot synced 2025-10-22 17:00:06 +02:00

Merge branch 'v2'

This commit is contained in:
2019-03-19 18:26:31 +05:30
6 changed files with 575 additions and 76 deletions

191
bot.py Normal file → Executable file
View File

@@ -10,6 +10,7 @@ from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, \
import signal
import sys
import re
import button_groups
try:
import config
@@ -28,16 +29,15 @@ def escape_html(message):
def start(bot, update):
chat_id = update.message.chat_id
name = str(update.message.from_user.first_name)
if update.message.from_user.last_name:
name += " " + str(update.message.from_user.last_name)
if update.message.chat.type == "private":
name = str(update.message.from_user.first_name)
if update.message.from_user.last_name:
name += " " + str(update.message.from_user.last_name)
else:
name = update.message.chat.title
text = f"Hello {name}!\n" + \
"Welcome to Questable. To get started, check /help."
custom_keyboard = [
['❇️ Add Quest', '📯 Add Side Quest'],
['📜 List Quests', '📃 List Side Quests'],
['🏅 Player Status']
]
custom_keyboard = button_groups.main
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup)
@@ -68,7 +68,10 @@ def add_quest(bot, update, player, type="quest"):
chat_id = update.message.chat_id
text = ("What shall the name of " +
{"quest": "Quest", "side_quest": "Side Quest"}[type] + " be?")
reply_markup = telegram.ReplyKeyboardRemove()
if update.message.chat.type == "private":
reply_markup = telegram.ReplyKeyboardRemove()
else:
reply_markup = telegram.ForceReply()
bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup)
@@ -87,7 +90,7 @@ def add_name(bot, update, player, type, qid):
chat_id = update.message.chat_id
text = "How difficult is it?"
custom_keyboard = [["📙 Low", "📘 Medium", "📗 High"]]
custom_keyboard = button_groups.difficulty
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup)
@@ -118,7 +121,7 @@ def add_diff(bot, update, player, type, qid):
x.update_db()
text = "How important is it?"
custom_keyboard = [["🔹 Low", "🔸 Medium", "🔺 High"]]
custom_keyboard = button_groups.importance
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup)
@@ -154,9 +157,12 @@ def add_imp(bot, update, player, type, qid):
def send_status(bot, update, player, prefix=""):
name = str(update.message.from_user.first_name)
if update.message.from_user.last_name:
name += " " + str(update.message.from_user.last_name)
if update.message.chat.type == "private":
name = str(update.message.from_user.first_name)
if update.message.from_user.last_name:
name += " " + str(update.message.from_user.last_name)
else:
name = update.message.chat.title
name = escape_html(name)
points = player.get_points()
total_quests = len(player.get_quests(None))
@@ -170,11 +176,7 @@ def send_status(bot, update, player, prefix=""):
f'<b>💠 Side Quests:</b> {completed_side_quests}/'
f'{total_side_quests}\n')
chat_id = update.message.chat_id
custom_keyboard = [
['❇️ Add Quest', '📯 Add Side Quest'],
['📜 List Quests', '📃 List Side Quests'],
['🏅 Player Status']
]
custom_keyboard = button_groups.main
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup,
parse_mode="HTML")
@@ -246,13 +248,7 @@ def quest(bot, update, player, qid, type):
elif x.state == 0:
state = {"quest": "eq", "side_quest": "esq"}[type]
player.set_state(state, qid)
custom_keyboard = [
["✅ Mark as done"],
["📝 Edit Name", "⚠️ Change Priority"],
["📚 Change Difficulty", "🗑 Delete " +
{"quest": "Quest", "side_quest": "Side Quest"}[type]],
["⬅️ Back"]]
custom_keyboard = button_groups.quests(type)
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
chat_id = update.message.chat_id
bot.send_message(chat_id=chat_id, text=text, parse_mode="HTML",
@@ -260,7 +256,7 @@ def quest(bot, update, player, qid, type):
def quest_handling(bot, update, db):
text = update.message.text.lower().split("_")
text = update.message.text.lower().split("@")[0].split("_")
chat_id = update.message.chat_id
player = questable.player(db, chat_id)
drop_state(bot, update, player)
@@ -287,11 +283,7 @@ def mark_as_done(bot, update, player, qid, type):
player.set_state('none', 0)
send_status(bot, update, player, f"<b>🌟 Earned {points} XP</b>\n\n")
chat_id = update.message.chat_id
custom_keyboard = [
['❇️ Add Quest', '📯 Add Side Quest'],
['📜 List Quests', '📃 List Side Quests'],
['🏅 Player Status']
]
custom_keyboard = button_groups.main
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_animation(chat_id=chat_id, animation=random.choice(config.gifs),
reply_markup=reply_markup)
@@ -365,17 +357,15 @@ def drop_state(bot, update, player):
x = questable.get_side_quest(player.DB, player.CHAT_ID, state["extra"])
x.delete_from_db()
player.set_state('none', 0)
else:
player.set_state('none', 0)
def help_command(bot, update, db):
player = questable.player(db, update.message.chat_id)
drop_state(bot, update, player)
chat_id = update.message.chat_id
custom_keyboard = [
['❇️ Add Quest', '📯 Add Side Quest'],
['📜 List Quests', '📃 List Side Quests'],
['🏅 Player Status']
]
custom_keyboard = button_groups.main
text = ("*Questable Bot*\n\nQuestable is an RPG-like bot for maintaining "
"events in real life. _Main Tasks_ are _Quests_ while _other "
"tasks_ are _Side Quests._ You can use the bot to maintain a "
@@ -396,11 +386,7 @@ def rate_command(bot, update, db):
player = questable.player(db, update.message.chat_id)
drop_state(bot, update, player)
chat_id = update.message.chat_id
custom_keyboard = [
['❇️ Add Quest', '📯 Add Side Quest'],
['📜 List Quests', '📃 List Side Quests'],
['🏅 Player Status']
]
custom_keyboard = button_groups.main
text = ("[Vote for us on Telegram Directory!](https://t.me/tgdrbot?"
"start=questable_bot)\n\n"
"Telegram Directory is a website that helps you discover top "
@@ -410,6 +396,56 @@ def rate_command(bot, update, db):
reply_markup=reply_markup)
def tokens(bot, update):
custom_keyboard = button_groups.tokens
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
reply_text = ("Tokens are used to authenticate external "
"applications. This only provides access to "
"Questable data.")
bot.send_message(chat_id=update.message.chat_id, text=reply_text,
reply_markup=reply_markup)
def add_token(bot, update, player):
custom_keyboard = button_groups.main
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
if len(player.get_tokens()) < 3:
reply_text = player.add_token()
else:
reply_text = "Maximum number of tokens reached."
bot.send_message(chat_id=player.CHAT_ID, text=reply_text,
reply_markup=reply_markup)
def delete_token(bot, update, player):
tokens = player.get_tokens()
custom_keyboard = list(map(lambda x: [x], tokens))
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
reply_text = "Choose token to remove."
player.set_state("rt")
bot.send_message(chat_id=update.message.chat_id, text=reply_text,
reply_markup=reply_markup)
def delete_token_rt(bot, update, player):
player.delete_token(update.message.text.lower())
custom_keyboard = button_groups.main
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
reply_text = "Token has been removed."
player.set_state("none")
bot.send_message(chat_id=player.CHAT_ID, text=reply_text,
reply_markup=reply_markup)
def list_tokens(bot, update, player):
custom_keyboard = button_groups.main
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
reply_text = "📋 List of tokens\n\n"
reply_text += "\n".join(player.get_tokens())
bot.send_message(chat_id=update.message.chat_id, text=reply_text,
reply_markup=reply_markup)
def message_handling(bot, update, db):
text = update.message.text.lower()
player = questable.player(db, update.message.chat_id)
@@ -427,6 +463,7 @@ def message_handling(bot, update, db):
# eqn / esqn: Edit Quest / Side Quest Name
# eqi / esqi: Edit Quest / Side Quest Importance
# eqd / esqd: Edit Quest / Side Quest Difficulty
# rt: Remove token
if state["state"] == "none":
if text == "add quest" or text == "❇️ add quest":
@@ -437,9 +474,20 @@ def message_handling(bot, update, db):
list_quests(bot, update, player, "quest")
elif text == "list side quests" or text == "📃 list side quests":
list_quests(bot, update, player, "side_quest")
elif text == "tokens" or text == "🔑 tokens":
tokens(bot, update)
elif text == "list tokens" or text == "📋 list tokens":
list_tokens(bot, update, player)
elif text == "generate token" or text == "🔑 generate token":
add_token(bot, update, player)
elif text == "delete token" or text == "🧹 delete token":
delete_token(bot, update, player)
else:
drop_state(bot, update, player)
send_status(bot, update, player)
if update.message.chat.type == "private":
send_status(bot, update, player)
elif state["state"] == "aq":
add_name(bot, update, player, "quest", state["extra"])
@@ -474,14 +522,14 @@ def message_handling(bot, update, db):
elif text == "change priority" or text == "⚠️ change priority":
player.set_state('eqi', state["extra"])
text = "How important is it?"
custom_keyboard = [["🔹 Low", "🔸 Medium", "🔺 High"]]
custom_keyboard = button_groups.importance
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=player.CHAT_ID, text=text,
reply_markup=reply_markup)
elif text == "change difficulty" or text == "📚 change difficulty":
player.set_state('eqd', state["extra"])
text = "How difficult is it?"
custom_keyboard = [["📙 Low", "📘 Medium", "📗 High"]]
custom_keyboard = button_groups.difficulty
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=player.CHAT_ID, text=text,
reply_markup=reply_markup)
@@ -492,8 +540,9 @@ def message_handling(bot, update, db):
prefix = f"<b>Quest {quest.name} has been deleted</b>\n\n"
send_status(bot, update, player, prefix=prefix)
else:
drop_state(bot, update, player)
send_status(bot, update, player)
if update.message.chat.type == "private":
drop_state(bot, update, player)
send_status(bot, update, player)
elif state["state"] == "esq":
if text == "back" or text == "⬅️ back":
@@ -510,14 +559,14 @@ def message_handling(bot, update, db):
elif text == "change priority" or text == "⚠️ change priority":
player.set_state('esqi', state["extra"])
text = "How important is it?"
custom_keyboard = [["🔹 Low", "🔸 Medium", "🔺 High"]]
custom_keyboard = button_groups.importance
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=player.CHAT_ID, text=text,
reply_markup=reply_markup)
elif text == "change difficulty" or text == "📚 change difficulty":
player.set_state('esqd', state["extra"])
text = "How difficult is it?"
custom_keyboard = [["📙 Low", "📘 Medium", "📗 High"]]
custom_keyboard = button_groups.difficulty
reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
bot.send_message(chat_id=player.CHAT_ID, text=text,
reply_markup=reply_markup)
@@ -528,12 +577,14 @@ def message_handling(bot, update, db):
prefix = f"<b>Side Quest {sq.name} has been deleted</b>\n\n"
send_status(bot, update, player, prefix=prefix)
else:
drop_state(bot, update, player)
send_status(bot, update, player)
if update.message.chat.type == "private":
drop_state(bot, update, player)
send_status(bot, update, player)
elif state["state"] == "bo":
player.set_state('none', 0)
send_status(bot, update, player)
if text == "back" or update.message.chat.type == "private":
player.set_state('none', 0)
send_status(bot, update, player)
elif state["state"] == "eqn":
edit_quest(bot, update, player, state["extra"], "name", "quest")
@@ -553,9 +604,12 @@ def message_handling(bot, update, db):
elif state["state"] == "esqd":
edit_quest(bot, update, player, state["extra"], "diff", "side_quest")
elif state["state"] == "rt":
delete_token_rt(bot, update, player)
else:
drop_state(bot, update, player)
send_status(bot, update, player)
if update.message.chat.type == "private":
drop_state(bot, update, player)
send_status(bot, update, player)
def sigterm_handler(signal, frame, db):
@@ -563,28 +617,13 @@ def sigterm_handler(signal, frame, db):
sys.exit(0)
db = sqlite3.connect("questable.db", check_same_thread=False)
cursor = db.cursor()
signal.signal(signal.SIGTERM, lambda x, y: sigterm_handler(x, y, db))
# Set up tables
queries = [
("CREATE TABLE IF NOT EXISTS quests(chat_id int NOT NULL, qid int NOT"
" NULL, name varchar(255), difficulty int, importance int, "
"state int DEFAULT 0, UNIQUE(chat_id, qid));"),
("CREATE TABLE IF NOT EXISTS side_quests(chat_id int NOT NULL, qid int "
"NOT NULL, name varchar(255), difficulty int, importance int, "
"state int DEFAULT 0, UNIQUE(chat_id, qid));"),
("CREATE TABLE IF NOT EXISTS points(chat_id int PRIMARY KEY, points "
"int);"),
("CREATE TABLE IF NOT EXISTS state(chat_id int PRIMARY KEY, state "
"varchar(10), extra varchar(10));"),
]
for query in queries:
cursor.execute(query)
# Set up database and tables
db = sqlite3.connect("questable.db", check_same_thread=False)
cursor = db.cursor()
with open('schema.sql') as f:
cursor.executescript(f.read())
db.commit()
updater = Updater(token=config.api_key)