Ejemplo n.º 1
0
def add_penalty_game(request, game_id):
    game = TournamentGame.objects.get(id=game_id)

    headers = {"X-Auth-Token": settings.PANTHEON_ADMIN_TOKEN}
    data = {
        "jsonrpc": "2.0",
        "method": "addPenaltyGame",
        "params": {
            "eventId": settings.PANTHEON_EVENT_ID,
            "players": [x.player.pantheon_id for x in game.game_players.all()],
        },
        "id": make_random_letters_and_digit_string(),
    }

    response = requests.post(settings.PANTHEON_URL, json=data, headers=headers)
    if response.status_code == 500:
        return HttpResponse("addPenaltyGame. 500 response")

    content = response.json()
    if content.get("error"):
        return HttpResponse("addPenaltyGame. Pantheon error: {}".format(
            content.get("error")))

    handler = TournamentHandler()
    handler.init(tournament=Tournament.objects.get(id=settings.TOURNAMENT_ID),
                 lobby="",
                 game_type="",
                 destination="")
    player_names = handler.get_players_message_string(
        [x.player for x in game.game_players.all()])
    handler.create_notification(TournamentNotification.GAME_PENALTY,
                                {"player_names": player_names})
    handler.check_round_was_finished()

    return redirect(request.META.get("HTTP_REFERER"))
Ejemplo n.º 2
0
    def __init__(self):
        super(DiscordClient, self).__init__()

        self.channels_dict = {}
        self.bg_task = self.loop.create_task(self.send_notifications())

        tournament = Tournament.objects.get(id=settings.TOURNAMENT_ID)
        self.tournament_handler = TournamentHandler()
        self.tournament_handler.init(
            tournament,
            settings.TOURNAMENT_PRIVATE_LOBBY,
            settings.TOURNAMENT_GAME_TYPE,
            TournamentHandler.DISCORD_DESTINATION,
        )
Ejemplo n.º 3
0
def finish_game_api(request):
    api_token = request.POST.get("api_token")
    if api_token != settings.TOURNAMENT_API_TOKEN:
        return HttpResponse(status=403)

    message = request.POST.get("message")

    handler = TournamentHandler()
    handler.init(tournament=Tournament.objects.get(id=settings.TOURNAMENT_ID),
                 lobby="",
                 game_type="",
                 destination="")
    handler.game_pre_end(message)

    return JsonResponse({"success": True})
Ejemplo n.º 4
0
from django.conf import settings
from django.core.management.base import BaseCommand
from django.db.models import Q
from django.utils.translation import activate
from telegram import ParseMode, Update
from telegram.error import BadRequest, ChatMigrated, NetworkError, TelegramError, TimedOut, Unauthorized
from telegram.ext import CallbackContext, CommandHandler, Defaults, Filters, MessageHandler, Updater
from telegram.utils.helpers import escape_markdown

from online.handler import TournamentHandler
from online.models import TournamentGame, TournamentNotification
from tournament.models import Tournament
from utils.logs import set_up_logging

logger = logging.getLogger("tournament_bot")
tournament_handler = TournamentHandler()


class Command(BaseCommand):
    def handle(self, *args, **options):
        set_up_logging(TournamentHandler.TELEGRAM_DESTINATION)
        bot = TelegramBot()
        bot.init()


class TelegramBot:
    def init(self):
        if not settings.TELEGRAM_ADMIN_USERNAME or not settings.TELEGRAM_ADMIN_USERNAME.startswith("@"):
            logger.error("Telegram admin username should starts with @")
            return
Ejemplo n.º 5
0
    def handle(self, *args, **options):
        set_up_logging()

        tournament_id = settings.TOURNAMENT_ID
        lobby = settings.TOURNAMENT_PRIVATE_LOBBY
        game_type = settings.TOURNAMENT_GAME_TYPE

        if not tournament_id or not lobby or not game_type:
            print('Tournament wasn\'t configured properly')
            return

        tournament = Tournament.objects.get(id=tournament_id)

        global tournament_handler
        tournament_handler = TournamentHandler(tournament, lobby, game_type)

        updater = Updater(token=settings.TELEGRAM_TOKEN)
        dispatcher = updater.dispatcher

        def stop_and_restart():
            """Gracefully stop the Updater and replace the current process with a new one"""
            updater.stop()
            os.execl(sys.executable, sys.executable, *sys.argv)

        def restart(bot, update):
            message = 'Bot is restarting...'
            logger.info(message)
            update.message.reply_text(message)
            Thread(target=stop_and_restart).start()

        start_handler = CommandHandler('me',
                                       set_tenhou_nickname,
                                       pass_args=True)
        log_handler = CommandHandler('log', set_game_log, pass_args=True)
        status_handler = CommandHandler('status', get_tournament_status)
        help_handler = CommandHandler('help', help_bot)

        # admin commands
        dispatcher.add_handler(
            CommandHandler('restart',
                           restart,
                           filters=Filters.user(username='******')))
        dispatcher.add_handler(
            CommandHandler('prepare_next_round',
                           prepare_next_round,
                           filters=Filters.user(username='******')))
        dispatcher.add_handler(
            CommandHandler('start_failed_games',
                           start_failed_games,
                           filters=Filters.user(username='******')))
        dispatcher.add_handler(
            CommandHandler('start_games',
                           start_games,
                           filters=Filters.user(username='******')))
        dispatcher.add_handler(
            CommandHandler('close_registration',
                           close_registration,
                           filters=Filters.user(username='******')))

        dispatcher.add_handler(start_handler)
        dispatcher.add_handler(log_handler)
        dispatcher.add_handler(status_handler)
        dispatcher.add_handler(help_handler)
        dispatcher.add_error_handler(error_callback)
        dispatcher.add_handler(
            MessageHandler(Filters.status_update.new_chat_members,
                           new_chat_member))

        logger.info('Starting the bot...')
        updater.start_polling()

        updater.idle()
Ejemplo n.º 6
0
class DiscordClient(discord.Client):
    CONFIRMATION_EN = "confirmation_en"
    CONFIRMATION_RU = "confirmation_ru"
    NOTIFICATIONS_EN = "notifications_en"
    NOTIFICATIONS_RU = "notifications_ru"
    GENERAL_EN = "general_en"
    GENERAL_RU = "general_ru"
    GAME_LOGS = "game_logs"

    REQUIRED_CHANNELS = [
        CONFIRMATION_EN,
        CONFIRMATION_RU,
        NOTIFICATIONS_EN,
        NOTIFICATIONS_RU,
        GAME_LOGS,
        GENERAL_EN,
        GENERAL_RU,
    ]

    guild = None
    channels_dict = None

    def __init__(self):
        super(DiscordClient, self).__init__()

        self.channels_dict = {}
        self.bg_task = self.loop.create_task(self.send_notifications())

        tournament = Tournament.objects.get(id=settings.TOURNAMENT_ID)
        self.tournament_handler = TournamentHandler()
        self.tournament_handler.init(
            tournament,
            settings.TOURNAMENT_PRIVATE_LOBBY,
            settings.TOURNAMENT_GAME_TYPE,
            TournamentHandler.DISCORD_DESTINATION,
        )

    async def on_ready(self):
        self.guild = discord.utils.get(self.guilds,
                                       name=settings.DISCORD_GUILD_NAME)

        for channel in self.guild.channels:
            self.channels_dict[channel.name] = channel.id

        logger.info(
            f'"{self.user}" has connected to {self.guild.name} (id: {self.guild.id}) guild'
        )
        logger.info(f"found {len(self.guild.channels)} channels")

        for required_channel in self.REQUIRED_CHANNELS:
            if required_channel not in self.channels_dict:
                raise AssertionError(
                    f"Guild doesn't have required #{required_channel} channel")

    async def on_message(self, message: Message):
        if message.author == self.user:
            return

        channel_name = message.channel.name

        if channel_name == DiscordClient.CONFIRMATION_EN or channel_name == DiscordClient.CONFIRMATION_RU:
            await self.confirm_participation(message)
            return

        if channel_name == DiscordClient.GAME_LOGS:
            await self.add_game_log(message)
            return

        if message.content == "!status":
            await self.get_status(message)
            return

        if message.content == "!help":
            await self.get_help(message)
            return

    async def get_help(self, message: Message):
        self.activate_language(message.channel.name)

        m = ""
        m += _("1. Tournament lobby:\n <%(lobby_link)s> \n") % {
            "lobby_link": self.tournament_handler.get_lobby_link()
        }
        m += _("2. Tournament statistics:\n <%(rating_link)s> \n") % {
            "rating_link": self.tournament_handler.get_rating_link()
        }
        # m += _("2.1. Team statistics:\n <%(rating_link)s>/team \n") % {
        #     "rating_link": self.tournament_handler.get_rating_link()
        # }
        m += _("3. Current games:\n <%(current_games_link)s> \n") % {
            "current_games_link":
            f"https://tenhou.net/wg/?{settings.TOURNAMENT_PUBLIC_LOBBY[:5]}"
        }

        await message.channel.send(m)

    async def add_game_log(self, message: Message):
        _, success = self.tournament_handler.add_game_log(message.content)
        emoji = success and "\N{THUMBS UP SIGN}" or "\N{NO ENTRY SIGN}"
        await message.add_reaction(emoji)

    async def get_status(self, message: Message):
        self.activate_language(message.channel.name)

        response = self.tournament_handler.get_tournament_status()
        await message.channel.send(response)

    async def confirm_participation(self, message: Message):
        self.activate_language(message.channel.name)

        tenhou_nickname = message.content
        ds_nickname = message.author.name

        response = self.tournament_handler.confirm_participation_in_tournament(
            tenhou_nickname, discord_username=ds_nickname)
        await self.replay(message.channel, message.author, response)

    async def send_notifications(self):
        await self.wait_until_ready()

        if not self.channels_dict:
            print("no dicts")
            await asyncio.sleep(5)

        while not self.is_closed():
            notification = TournamentNotification.objects.filter(
                is_processed=False,
                destination=TournamentNotification.DISCORD).last()

            if not notification:
                await asyncio.sleep(2)
                continue

            extra_kwargs = {
                "confirmation_channel":
                self.channel_mention(DiscordClient.CONFIRMATION_EN)
            }
            message = self.tournament_handler.get_notification_text(
                "en", notification, extra_kwargs)
            channel = self.get_channel(
                self.channels_dict[DiscordClient.NOTIFICATIONS_EN])
            await channel.send(message)

            extra_kwargs = {
                "confirmation_channel":
                self.channel_mention(DiscordClient.CONFIRMATION_RU)
            }
            message = self.tournament_handler.get_notification_text(
                "ru", notification, extra_kwargs)
            channel = self.get_channel(
                self.channels_dict[DiscordClient.NOTIFICATIONS_RU])
            await channel.send(message)

            notification.is_processed = True
            notification.save()

            logger.info(f"notification id={notification.id} sent")

            await asyncio.sleep(2)

    async def replay(self, channel, user, message):
        m = f"{user.mention}\n{message}"
        await channel.send(m)

    def channel_mention(self, channel_name):
        return f"<#{self.channels_dict[channel_name]}>"

    def activate_language(self, channel_name: str):
        lang = "en"
        if channel_name.endswith("_ru"):
            lang = "ru"
        activate(lang)
        return lang