173 lines
4.6 KiB
Python
173 lines
4.6 KiB
Python
#!/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 gettext
|
|
from functools import wraps
|
|
|
|
from locales import available_locales
|
|
from database import db_session
|
|
from user_setting import UserSetting
|
|
from shared_vars import gm
|
|
|
|
GETTEXT_DOMAIN = 'unobot'
|
|
GETTEXT_DIR = 'locales'
|
|
|
|
|
|
class _Underscore(object):
|
|
"""Class to emulate flufl.i18n behaviour, but with plural support"""
|
|
def __init__(self):
|
|
self.translators = {
|
|
locale: gettext.GNUTranslations(
|
|
open(gettext.find(
|
|
GETTEXT_DOMAIN, GETTEXT_DIR, languages=[locale]
|
|
), 'rb')
|
|
)
|
|
for locale
|
|
in available_locales.keys()
|
|
if locale != 'en_US' # No translation file for en_US
|
|
}
|
|
self.locale_stack = list()
|
|
|
|
def push(self, locale):
|
|
self.locale_stack.append(locale)
|
|
|
|
def pop(self):
|
|
if self.locale_stack:
|
|
return self.locale_stack.pop()
|
|
else:
|
|
return None
|
|
|
|
@property
|
|
def code(self):
|
|
if self.locale_stack:
|
|
return self.locale_stack[-1]
|
|
else:
|
|
return None
|
|
|
|
def __call__(self, singular, plural=None, n=1, locale=None):
|
|
if not locale:
|
|
locale = self.locale_stack[-1]
|
|
|
|
if locale not in self.translators.keys():
|
|
if n is 1:
|
|
return singular
|
|
else:
|
|
return plural
|
|
|
|
translator = self.translators[locale]
|
|
|
|
if plural is None:
|
|
return translator.gettext(singular)
|
|
else:
|
|
return translator.ngettext(singular, plural, n)
|
|
|
|
_ = _Underscore()
|
|
|
|
|
|
def __(singular, plural=None, n=1, multi=False):
|
|
"""Translates text into all locales on the stack"""
|
|
translations = list()
|
|
|
|
if not multi:
|
|
_.push('en_US')
|
|
translations.append(_(singular))
|
|
_.pop()
|
|
|
|
else:
|
|
for locale in _.locale_stack:
|
|
translation = _(singular, plural, n, locale)
|
|
|
|
if translation not in translations:
|
|
translations.append(translation)
|
|
|
|
return '\n'.join(translations)
|
|
|
|
|
|
def user_locale(func):
|
|
@wraps(func)
|
|
@db_session
|
|
def wrapped(bot, update, *pargs, **kwargs):
|
|
user, chat = _user_chat_from_update(update)
|
|
|
|
with db_session:
|
|
us = UserSetting.get(id=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(bot, update, *pargs, **kwargs):
|
|
user, chat = _user_chat_from_update(update)
|
|
player = gm.player_for_user_in_chat(user, chat)
|
|
locales = list()
|
|
|
|
if player:
|
|
for player in player.game.players:
|
|
us = UserSetting.get(id=player.user.id)
|
|
|
|
if us:
|
|
loc = us.lang
|
|
else:
|
|
loc = 'en_US'
|
|
|
|
if loc in locales:
|
|
continue
|
|
|
|
_.push(loc)
|
|
locales.append(loc)
|
|
|
|
result = func(bot, update, *pargs, **kwargs)
|
|
|
|
while _.code:
|
|
_.pop()
|
|
|
|
return result
|
|
return wrapped
|
|
|
|
|
|
def _user_chat_from_update(update):
|
|
|
|
try:
|
|
user = update.message.from_user
|
|
chat = update.message.chat
|
|
except (NameError, AttributeError):
|
|
try:
|
|
user = update.inline_query.from_user
|
|
chat = gm.userid_current[user.id].game.chat
|
|
except KeyError:
|
|
chat = None
|
|
except (NameError, AttributeError):
|
|
try:
|
|
user = update.chosen_inline_result.from_user
|
|
chat = gm.userid_current[user.id].game.chat
|
|
except (NameError, AttributeError):
|
|
chat = None
|
|
|
|
return user, chat
|