forked from test/mau_mau_bot
settings UI added, save locale to database
This commit is contained in:
parent
cddf13dc5d
commit
6c610c1aeb
8 changed files with 388 additions and 147 deletions
164
bot.py
164
bot.py
|
@ -20,19 +20,14 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from functools import wraps
|
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
from telegram import ParseMode, Message, Chat, InlineKeyboardMarkup, \
|
from telegram import ParseMode, Message, Chat, InlineKeyboardMarkup, \
|
||||||
InlineKeyboardButton
|
InlineKeyboardButton
|
||||||
from telegram.ext import Updater, InlineQueryHandler, \
|
from telegram.ext import InlineQueryHandler, ChosenInlineResultHandler, \
|
||||||
ChosenInlineResultHandler, CommandHandler, MessageHandler, Filters, \
|
CommandHandler, MessageHandler, Filters, CallbackQueryHandler
|
||||||
CallbackQueryHandler
|
|
||||||
from telegram.ext.dispatcher import run_async
|
from telegram.ext.dispatcher import run_async
|
||||||
from telegram.utils.botan import Botan
|
|
||||||
|
|
||||||
from game_manager import GameManager
|
|
||||||
from credentials import TOKEN, BOTAN_TOKEN
|
|
||||||
from start_bot import start_bot
|
from start_bot import start_bot
|
||||||
from results import (add_call_bluff, add_choose_color, add_draw, add_gameinfo,
|
from results import (add_call_bluff, add_choose_color, add_draw, add_gameinfo,
|
||||||
add_no_game, add_not_started, add_other_cards, add_pass,
|
add_no_game, add_not_started, add_other_cards, add_pass,
|
||||||
|
@ -41,111 +36,18 @@ from utils import display_name
|
||||||
import card as c
|
import card as c
|
||||||
from errors import (NoGameInChatError, LobbyClosedError, AlreadyJoinedError,
|
from errors import (NoGameInChatError, LobbyClosedError, AlreadyJoinedError,
|
||||||
NotEnoughPlayersError, DeckEmptyError)
|
NotEnoughPlayersError, DeckEmptyError)
|
||||||
from utils import _, __
|
from utils import _, __, send_async, answer_async, user_locale, game_locales, \
|
||||||
|
error, TIMEOUT
|
||||||
|
from shared_vars import botan, gm, updater, dispatcher
|
||||||
|
|
||||||
|
import simple_commands, settings
|
||||||
|
|
||||||
TIMEOUT = 2.5
|
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
level=logging.DEBUG)
|
level=logging.DEBUG)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
gm = GameManager()
|
|
||||||
u = Updater(token=TOKEN, workers=32)
|
|
||||||
dp = u.dispatcher
|
|
||||||
|
|
||||||
botan = False
|
|
||||||
if BOTAN_TOKEN:
|
|
||||||
botan = Botan(BOTAN_TOKEN)
|
|
||||||
|
|
||||||
help_text = ("Follow these steps:\n\n"
|
|
||||||
"1. Add this bot to a group\n"
|
|
||||||
"2. In the group, start a new game with /new or join an already"
|
|
||||||
" running game with /join\n"
|
|
||||||
"3. After at least two players have joined, start the game with"
|
|
||||||
" /start\n"
|
|
||||||
"4. Type <code>@mau_mau_bot</code> into your chat box and hit "
|
|
||||||
"<b>space</b>, or click the <code>via @mau_mau_bot</code> text "
|
|
||||||
"next to messages. You will see your cards (some greyed out), "
|
|
||||||
"any extra options like drawing, and a <b>?</b> to see the "
|
|
||||||
"current game state. The <b>greyed out cards</b> are those you "
|
|
||||||
"<b>can not play</b> at the moment. Tap an option to execute "
|
|
||||||
"the selected action.\n"
|
|
||||||
"Players can join the game at any time. To leave a game, "
|
|
||||||
"use /leave. If a player takes more than 90 seconds to play, "
|
|
||||||
"you can use /skip to skip that player.\n\n"
|
|
||||||
"Other commands (only game creator):\n"
|
|
||||||
"/close - Close lobby\n"
|
|
||||||
"/open - Open lobby\n\n"
|
|
||||||
"<b>Experimental:</b> Play in multiple groups at the same time. "
|
|
||||||
"Press the <code>Current game: ...</code> button and select the "
|
|
||||||
"group you want to play a card in.\n"
|
|
||||||
"If you enjoy this bot, "
|
|
||||||
"<a href=\"https://telegram.me/storebot?start=mau_mau_bot\">"
|
|
||||||
"rate me</a>, join the "
|
|
||||||
"<a href=\"https://telegram.me/unobotupdates\">update channel</a>"
|
|
||||||
" and buy an UNO card game.")
|
|
||||||
|
|
||||||
source_text = ("This bot is Free Software and licensed under the AGPL. "
|
|
||||||
"The code is available here: \n"
|
|
||||||
"https://github.com/jh0ker/mau_mau_bot")
|
|
||||||
|
|
||||||
|
|
||||||
def user_locale(func):
|
|
||||||
@wraps(func)
|
|
||||||
def wrapped(*pargs, **kwargs):
|
|
||||||
_.push('de_DE') # TODO: Get user locale from Database
|
|
||||||
result = func(*pargs, **kwargs)
|
|
||||||
_.pop()
|
|
||||||
return result
|
|
||||||
return wrapped
|
|
||||||
|
|
||||||
|
|
||||||
def game_locales(func):
|
|
||||||
@wraps(func)
|
|
||||||
def wrapped(*pargs, **kwargs):
|
|
||||||
num_locales = 0
|
|
||||||
for loc in ('en_US', 'de_DE'): # TODO: Get user locales from Database
|
|
||||||
_.push(loc)
|
|
||||||
num_locales += 1
|
|
||||||
|
|
||||||
result = func(*pargs, **kwargs)
|
|
||||||
|
|
||||||
for i in range(num_locales):
|
|
||||||
_.pop()
|
|
||||||
return result
|
|
||||||
return wrapped
|
|
||||||
|
|
||||||
|
|
||||||
@run_async
|
|
||||||
def send_async(bot, *args, **kwargs):
|
|
||||||
"""Send a message asynchronously"""
|
|
||||||
if 'timeout' not in kwargs:
|
|
||||||
kwargs['timeout'] = TIMEOUT
|
|
||||||
|
|
||||||
try:
|
|
||||||
bot.sendMessage(*args, **kwargs)
|
|
||||||
except Exception as e:
|
|
||||||
error(None, None, e)
|
|
||||||
|
|
||||||
|
|
||||||
@run_async
|
|
||||||
def answer_async(bot, *args, **kwargs):
|
|
||||||
"""Answer an inline query asynchronously"""
|
|
||||||
if 'timeout' not in kwargs:
|
|
||||||
kwargs['timeout'] = TIMEOUT
|
|
||||||
|
|
||||||
try:
|
|
||||||
bot.answerInlineQuery(*args, **kwargs)
|
|
||||||
except Exception as e:
|
|
||||||
error(None, None, e)
|
|
||||||
|
|
||||||
|
|
||||||
def error(bot, update, error):
|
|
||||||
"""Simple error handler"""
|
|
||||||
logger.exception(error)
|
|
||||||
|
|
||||||
|
|
||||||
@user_locale
|
@user_locale
|
||||||
def new_game(bot, update):
|
def new_game(bot, update):
|
||||||
|
@ -487,29 +389,6 @@ def skip_player(bot, update):
|
||||||
|
|
||||||
gm.end_game(chat.id, skipped_player.user)
|
gm.end_game(chat.id, skipped_player.user)
|
||||||
|
|
||||||
|
|
||||||
@user_locale
|
|
||||||
def help(bot, update):
|
|
||||||
"""Handler for the /help command"""
|
|
||||||
send_async(bot, update.message.chat_id, text=_(help_text),
|
|
||||||
parse_mode=ParseMode.HTML, disable_web_page_preview=True)
|
|
||||||
|
|
||||||
|
|
||||||
@user_locale
|
|
||||||
def source(bot, update):
|
|
||||||
"""Handler for the /help command"""
|
|
||||||
send_async(bot, update.message.chat_id, text=_(source_text),
|
|
||||||
parse_mode=ParseMode.HTML, disable_web_page_preview=True)
|
|
||||||
|
|
||||||
|
|
||||||
@user_locale
|
|
||||||
def news(bot, update):
|
|
||||||
"""Handler for the /news command"""
|
|
||||||
send_async(bot, update.message.chat_id,
|
|
||||||
text=_("All news here: https://telegram.me/unobotupdates"),
|
|
||||||
disable_web_page_preview=True)
|
|
||||||
|
|
||||||
|
|
||||||
@game_locales
|
@game_locales
|
||||||
@user_locale
|
@user_locale
|
||||||
def reply_to_query(bot, update):
|
def reply_to_query(bot, update):
|
||||||
|
@ -712,21 +591,18 @@ def do_call_bluff(bot, player):
|
||||||
|
|
||||||
|
|
||||||
# Add all handlers to the dispatcher and run the bot
|
# Add all handlers to the dispatcher and run the bot
|
||||||
dp.add_handler(InlineQueryHandler(reply_to_query))
|
dispatcher.add_handler(InlineQueryHandler(reply_to_query))
|
||||||
dp.add_handler(ChosenInlineResultHandler(process_result))
|
dispatcher.add_handler(ChosenInlineResultHandler(process_result))
|
||||||
dp.add_handler(CallbackQueryHandler(select_game))
|
dispatcher.add_handler(CallbackQueryHandler(select_game))
|
||||||
dp.add_handler(CommandHandler('start', start_game, pass_args=True))
|
dispatcher.add_handler(CommandHandler('start', start_game, pass_args=True))
|
||||||
dp.add_handler(CommandHandler('new', new_game))
|
dispatcher.add_handler(CommandHandler('new', new_game))
|
||||||
dp.add_handler(CommandHandler('join', join_game))
|
dispatcher.add_handler(CommandHandler('join', join_game))
|
||||||
dp.add_handler(CommandHandler('leave', leave_game))
|
dispatcher.add_handler(CommandHandler('leave', leave_game))
|
||||||
dp.add_handler(CommandHandler('open', open_game))
|
dispatcher.add_handler(CommandHandler('open', open_game))
|
||||||
dp.add_handler(CommandHandler('close', close_game))
|
dispatcher.add_handler(CommandHandler('close', close_game))
|
||||||
dp.add_handler(CommandHandler('skip', skip_player))
|
dispatcher.add_handler(CommandHandler('skip', skip_player))
|
||||||
dp.add_handler(CommandHandler('help', help))
|
dispatcher.add_handler(MessageHandler([Filters.status_update], status_update))
|
||||||
dp.add_handler(CommandHandler('source', source))
|
dispatcher.add_error_handler(error)
|
||||||
dp.add_handler(CommandHandler('news', news))
|
|
||||||
dp.add_handler(MessageHandler([Filters.status_update], status_update))
|
|
||||||
dp.add_error_handler(error)
|
|
||||||
|
|
||||||
start_bot(u)
|
start_bot(updater)
|
||||||
u.idle()
|
updater.idle()
|
||||||
|
|
|
@ -350,3 +350,39 @@ msgstr "Passe"
|
||||||
#: results.py:148
|
#: results.py:148
|
||||||
msgid "I'm calling your bluff!"
|
msgid "I'm calling your bluff!"
|
||||||
msgstr "Ich glaube du bluffst!"
|
msgstr "Ich glaube du bluffst!"
|
||||||
|
|
||||||
|
#: settings.py:39
|
||||||
|
msgid "Please edit your settings in a private chat with the bot."
|
||||||
|
msgstr "Bitte ändere deine Einstellungen in einem privaten Chat mit dem Bot."
|
||||||
|
|
||||||
|
#: settings.py:49
|
||||||
|
msgid "Enable statistics"
|
||||||
|
msgstr "Statistiken aktivieren"
|
||||||
|
|
||||||
|
#: settings.py:51
|
||||||
|
msgid "Delete all statistics"
|
||||||
|
msgstr "Alle Statistiken löschen"
|
||||||
|
|
||||||
|
#: settings.py:53
|
||||||
|
msgid "Language"
|
||||||
|
msgstr "Sprache"
|
||||||
|
|
||||||
|
#: settings.py:54
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
|
#: settings.py:68
|
||||||
|
msgid "Enabled statistics!"
|
||||||
|
msgstr "Statistiken aktiviert!"
|
||||||
|
|
||||||
|
#: settings.py:70
|
||||||
|
msgid "Select locale"
|
||||||
|
msgstr "Bitte Sprache auswählen"
|
||||||
|
|
||||||
|
#: settings.py:81
|
||||||
|
msgid "Deleted and disabled statistics!"
|
||||||
|
msgstr "Alle Statistiken gelöscht und deaktiviert!"
|
||||||
|
|
||||||
|
#: settings.py:94
|
||||||
|
msgid "Set locale!"
|
||||||
|
msgstr "Sprache gesetzt!"
|
||||||
|
|
|
@ -294,3 +294,39 @@ msgstr ""
|
||||||
msgid "I'm calling your bluff!"
|
msgid "I'm calling your bluff!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:39
|
||||||
|
msgid "Please edit your settings in a private chat with the bot."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:49
|
||||||
|
msgid "Enable statistics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:51
|
||||||
|
msgid "Delete all statistics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:53
|
||||||
|
msgid "Language"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:54
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:68
|
||||||
|
msgid "Enabled statistics!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:70
|
||||||
|
msgid "Select locale"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:81
|
||||||
|
msgid "Deleted and disabled statistics!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: settings.py:94
|
||||||
|
msgid "Set locale!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
|
104
settings.py
Normal file
104
settings.py
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Telegram bot to play UNO in group chats
|
||||||
|
# Copyright (c) 2016 Jannes Höke <uno@jhoeke.de>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from telegram import ReplyKeyboardMarkup, Emoji
|
||||||
|
from telegram.ext import CommandHandler, RegexHandler
|
||||||
|
|
||||||
|
from utils import send_async
|
||||||
|
from user_setting import UserSetting
|
||||||
|
from utils import _, user_locale
|
||||||
|
from shared_vars import dispatcher
|
||||||
|
|
||||||
|
available_locales = [['en_US', 'de_DE']]
|
||||||
|
|
||||||
|
@user_locale
|
||||||
|
def show_settings(bot, update):
|
||||||
|
chat = update.message.chat
|
||||||
|
|
||||||
|
if update.message.chat.type != 'private':
|
||||||
|
send_async(bot, chat.id,
|
||||||
|
text=_("Please edit your settings in a private chat with "
|
||||||
|
"the bot."))
|
||||||
|
return
|
||||||
|
|
||||||
|
us = UserSetting.get(id=update.message.from_user.id)
|
||||||
|
|
||||||
|
if not us:
|
||||||
|
us = UserSetting(id=update.message.from_user.id)
|
||||||
|
|
||||||
|
if not us.stats:
|
||||||
|
stats = Emoji.BAR_CHART + ' ' + _("Enable statistics")
|
||||||
|
else:
|
||||||
|
stats = Emoji.CROSS_MARK + ' ' + _("Delete all statistics")
|
||||||
|
|
||||||
|
kb = [[stats], [Emoji.EARTH_GLOBE_EUROPE_AFRICA + ' ' + _("Language")]]
|
||||||
|
send_async(bot, chat.id, text=Emoji.WRENCH + ' ' + _("Settings"),
|
||||||
|
reply_markup=ReplyKeyboardMarkup(keyboard=kb,
|
||||||
|
one_time_keyboard=True))
|
||||||
|
|
||||||
|
|
||||||
|
@user_locale
|
||||||
|
def kb_select(bot, update, groups):
|
||||||
|
chat = update.message.chat
|
||||||
|
user = update.message.from_user
|
||||||
|
option = groups[0]
|
||||||
|
|
||||||
|
if option == Emoji.BAR_CHART:
|
||||||
|
us = UserSetting.get(id=user.id)
|
||||||
|
us.stats = True
|
||||||
|
send_async(bot, chat.id, text=_("Enabled statistics!"))
|
||||||
|
|
||||||
|
elif option == Emoji.EARTH_GLOBE_EUROPE_AFRICA:
|
||||||
|
send_async(bot, chat.id, text=_("Select locale"),
|
||||||
|
reply_markup=ReplyKeyboardMarkup(keyboard=available_locales,
|
||||||
|
one_time_keyboard=True))
|
||||||
|
|
||||||
|
elif option == Emoji.CROSS_MARK:
|
||||||
|
us = UserSetting.get(id=user.id)
|
||||||
|
us.stats = False
|
||||||
|
us.first_places = 0
|
||||||
|
us.games_played = 0
|
||||||
|
us.cards_played = 0
|
||||||
|
send_async(bot, chat.id, text=_("Deleted and disabled statistics!"))
|
||||||
|
|
||||||
|
|
||||||
|
@user_locale
|
||||||
|
def locale_select(bot, update, groups):
|
||||||
|
chat = update.message.chat
|
||||||
|
user = update.message.from_user
|
||||||
|
option = groups[0]
|
||||||
|
|
||||||
|
if option in [locale for row in available_locales for locale in row]:
|
||||||
|
us = UserSetting.get(id=user.id)
|
||||||
|
us.lang = option
|
||||||
|
_.push(option)
|
||||||
|
send_async(bot, chat.id, text=_("Set locale!"))
|
||||||
|
_.pop()
|
||||||
|
|
||||||
|
|
||||||
|
dispatcher.add_handler(CommandHandler('settings', show_settings))
|
||||||
|
dispatcher.add_handler(RegexHandler('^([' + Emoji.BAR_CHART +
|
||||||
|
Emoji.EARTH_GLOBE_EUROPE_AFRICA +
|
||||||
|
Emoji.CROSS_MARK + ']) .+$',
|
||||||
|
kb_select, pass_groups=True))
|
||||||
|
dispatcher.add_handler(RegexHandler(r'^(\w\w_\w\w)$',
|
||||||
|
locale_select, pass_groups=True))
|
37
shared_vars.py
Normal file
37
shared_vars.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Telegram bot to play UNO in group chats
|
||||||
|
# Copyright (c) 2016 Jannes Höke <uno@jhoeke.de>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from telegram.ext import Updater
|
||||||
|
from telegram.utils.botan import Botan
|
||||||
|
|
||||||
|
from game_manager import GameManager
|
||||||
|
from database import db
|
||||||
|
from credentials import TOKEN, BOTAN_TOKEN
|
||||||
|
|
||||||
|
db.bind('sqlite', 'uno.sqlite3', create_db=True)
|
||||||
|
db.generate_mapping(create_tables=True)
|
||||||
|
|
||||||
|
gm = GameManager()
|
||||||
|
updater = Updater(token=TOKEN, workers=32)
|
||||||
|
dispatcher = updater.dispatcher
|
||||||
|
|
||||||
|
botan = False
|
||||||
|
if BOTAN_TOKEN:
|
||||||
|
botan = Botan(BOTAN_TOKEN)
|
83
simple_commands.py
Normal file
83
simple_commands.py
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Telegram bot to play UNO in group chats
|
||||||
|
# Copyright (c) 2016 Jannes Höke <uno@jhoeke.de>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from telegram import ParseMode
|
||||||
|
from telegram.ext import CommandHandler
|
||||||
|
|
||||||
|
from utils import _, send_async, user_locale
|
||||||
|
from shared_vars import dispatcher
|
||||||
|
|
||||||
|
help_text = ("Follow these steps:\n\n"
|
||||||
|
"1. Add this bot to a group\n"
|
||||||
|
"2. In the group, start a new game with /new or join an already"
|
||||||
|
" running game with /join\n"
|
||||||
|
"3. After at least two players have joined, start the game with"
|
||||||
|
" /start\n"
|
||||||
|
"4. Type <code>@mau_mau_bot</code> into your chat box and hit "
|
||||||
|
"<b>space</b>, or click the <code>via @mau_mau_bot</code> text "
|
||||||
|
"next to messages. You will see your cards (some greyed out), "
|
||||||
|
"any extra options like drawing, and a <b>?</b> to see the "
|
||||||
|
"current game state. The <b>greyed out cards</b> are those you "
|
||||||
|
"<b>can not play</b> at the moment. Tap an option to execute "
|
||||||
|
"the selected action.\n"
|
||||||
|
"Players can join the game at any time. To leave a game, "
|
||||||
|
"use /leave. If a player takes more than 90 seconds to play, "
|
||||||
|
"you can use /skip to skip that player.\n\n"
|
||||||
|
"Other commands (only game creator):\n"
|
||||||
|
"/close - Close lobby\n"
|
||||||
|
"/open - Open lobby\n\n"
|
||||||
|
"<b>Experimental:</b> Play in multiple groups at the same time. "
|
||||||
|
"Press the <code>Current game: ...</code> button and select the "
|
||||||
|
"group you want to play a card in.\n"
|
||||||
|
"If you enjoy this bot, "
|
||||||
|
"<a href=\"https://telegram.me/storebot?start=mau_mau_bot\">"
|
||||||
|
"rate me</a>, join the "
|
||||||
|
"<a href=\"https://telegram.me/unobotupdates\">update channel</a>"
|
||||||
|
" and buy an UNO card game.")
|
||||||
|
|
||||||
|
source_text = ("This bot is Free Software and licensed under the AGPL. "
|
||||||
|
"The code is available here: \n"
|
||||||
|
"https://github.com/jh0ker/mau_mau_bot")
|
||||||
|
|
||||||
|
|
||||||
|
@user_locale
|
||||||
|
def help(bot, update):
|
||||||
|
"""Handler for the /help command"""
|
||||||
|
send_async(bot, update.message.chat_id, text=_(help_text),
|
||||||
|
parse_mode=ParseMode.HTML, disable_web_page_preview=True)
|
||||||
|
|
||||||
|
|
||||||
|
@user_locale
|
||||||
|
def source(bot, update):
|
||||||
|
"""Handler for the /help command"""
|
||||||
|
send_async(bot, update.message.chat_id, text=_(source_text),
|
||||||
|
parse_mode=ParseMode.HTML, disable_web_page_preview=True)
|
||||||
|
|
||||||
|
|
||||||
|
@user_locale
|
||||||
|
def news(bot, update):
|
||||||
|
"""Handler for the /news command"""
|
||||||
|
send_async(bot, update.message.chat_id,
|
||||||
|
text=_("All news here: https://telegram.me/unobotupdates"),
|
||||||
|
disable_web_page_preview=True)
|
||||||
|
|
||||||
|
|
||||||
|
dispatcher.add_handler(CommandHandler('help', help))
|
||||||
|
dispatcher.add_handler(CommandHandler('source', source))
|
||||||
|
dispatcher.add_handler(CommandHandler('news', news))
|
|
@ -18,14 +18,15 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from database import db, Optional, Required, PrimaryKey
|
from database import db, Optional, Required, PrimaryKey, db_session
|
||||||
|
|
||||||
|
|
||||||
class UserSetting(db.Entity):
|
class UserSetting(db.Entity):
|
||||||
|
|
||||||
id = PrimaryKey(int, auto=False) # Telegram User ID
|
id = PrimaryKey(int, auto=False, size=64) # Telegram User ID
|
||||||
lang = Optional(str, default='en') # The language setting for this user
|
lang = Optional(str, default='en') # The language setting for this user
|
||||||
stats = Optional(bool, default=False) # Opt-in to keep game statistics
|
stats = Optional(bool, default=False) # Opt-in to keep game statistics
|
||||||
first_places = Optional(int, default=0) # Nr. of games won in first place
|
first_places = Optional(int, default=0) # Nr. of games won in first place
|
||||||
games_played = Optional(int, default=0) # Nr. of games completed
|
games_played = Optional(int, default=0) # Nr. of games completed
|
||||||
cards_played = Optional(int, default=0) # Nr. of cards played
|
cards_played = Optional(int, default=0) # Nr. of cards played total
|
||||||
|
use_keyboards = Optional(bool, default=False) # Use keyboards (unused)
|
||||||
|
|
68
utils.py
68
utils.py
|
@ -19,18 +19,24 @@
|
||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
from flufl.i18n import registry
|
from flufl.i18n import registry
|
||||||
from flufl.i18n import PackageStrategy
|
from flufl.i18n import PackageStrategy
|
||||||
|
|
||||||
from telegram import Emoji
|
from telegram import Emoji
|
||||||
|
from telegram.ext.dispatcher import run_async
|
||||||
import locales
|
import locales
|
||||||
|
from database import db_session
|
||||||
|
from user_setting import UserSetting
|
||||||
|
|
||||||
strategy = PackageStrategy('unobot', locales)
|
strategy = PackageStrategy('unobot', locales)
|
||||||
application = registry.register(strategy)
|
application = registry.register(strategy)
|
||||||
_ = application._
|
_ = application._
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
TIMEOUT = 2.5
|
||||||
|
|
||||||
|
|
||||||
def __(string):
|
def __(string):
|
||||||
"""Translates text into all locales on the stack"""
|
"""Translates text into all locales on the stack"""
|
||||||
|
@ -85,3 +91,65 @@ def display_color(color):
|
||||||
return Emoji.GREEN_HEART + " Green"
|
return Emoji.GREEN_HEART + " Green"
|
||||||
if color == "y":
|
if color == "y":
|
||||||
return Emoji.YELLOW_HEART + " Yellow"
|
return Emoji.YELLOW_HEART + " Yellow"
|
||||||
|
|
||||||
|
|
||||||
|
def error(bot, update, error):
|
||||||
|
"""Simple error handler"""
|
||||||
|
logger.exception(error)
|
||||||
|
|
||||||
|
|
||||||
|
@run_async
|
||||||
|
def send_async(bot, *args, **kwargs):
|
||||||
|
"""Send a message asynchronously"""
|
||||||
|
if 'timeout' not in kwargs:
|
||||||
|
kwargs['timeout'] = TIMEOUT
|
||||||
|
|
||||||
|
try:
|
||||||
|
bot.sendMessage(*args, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
error(None, None, e)
|
||||||
|
|
||||||
|
|
||||||
|
@run_async
|
||||||
|
def answer_async(bot, *args, **kwargs):
|
||||||
|
"""Answer an inline query asynchronously"""
|
||||||
|
if 'timeout' not in kwargs:
|
||||||
|
kwargs['timeout'] = TIMEOUT
|
||||||
|
|
||||||
|
try:
|
||||||
|
bot.answerInlineQuery(*args, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
error(None, None, e)
|
||||||
|
|
||||||
|
|
||||||
|
def user_locale(func):
|
||||||
|
@wraps(func)
|
||||||
|
@db_session
|
||||||
|
def wrapped(bot, update, *pargs, **kwargs):
|
||||||
|
with db_session:
|
||||||
|
us = UserSetting.get(id=update.message.from_user.id)
|
||||||
|
if us:
|
||||||
|
_.push(us.lang)
|
||||||
|
else:
|
||||||
|
_.push('en_US')
|
||||||
|
result = func(bot, update, *pargs, **kwargs)
|
||||||
|
_.pop()
|
||||||
|
return result
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
|
def game_locales(func):
|
||||||
|
@wraps(func)
|
||||||
|
@db_session
|
||||||
|
def wrapped(*pargs, **kwargs):
|
||||||
|
num_locales = 0
|
||||||
|
for loc in ('en_US', 'de_DE'): # TODO: Get user locales from Database
|
||||||
|
_.push(loc)
|
||||||
|
num_locales += 1
|
||||||
|
|
||||||
|
result = func(*pargs, **kwargs)
|
||||||
|
|
||||||
|
for i in range(num_locales):
|
||||||
|
_.pop()
|
||||||
|
return result
|
||||||
|
return wrapped
|
Loading…
Reference in a new issue