Esempio n. 1
0
 async def on_rule_accept(player, interaction_id, interaction,
                          interaction_values):
     user = interaction.user
     if modules.loader.is_all_locked():
         raise modules.interactions.InteractionNotAllowed
     # reaction to the rule message?
     p = Player.get(user.id)
     if not p:  # if new player
         # create a new profile
         p = Player(user.id, user.name)
         await modules.roles.role_update(p)
         await modules.database.async_db_call(modules.database.set_element,
                                              "users", p.id, p.get_data())
         await disp.REG_RULES.send(
             ContextWrapper.channel(cfg.channels["register"]), user.mention)
     elif p.is_away:
         p.is_away = False
         await modules.roles.role_update(p)
         await p.db_update("away")
         await disp.AWAY_BACK.send(
             ContextWrapper.channel(cfg.channels["register"]), p.mention)
     else:
         i_ctx = InteractionContext(interaction)
         await disp.REG_RULES_ALREADY.send(i_ctx)
         await modules.roles.role_update(p)
Esempio n. 2
0
async def send_account(channel: discord.TextChannel,
                       a_player: classes.ActivePlayer):
    """
    Actually send its account to the player.

    :param channel: Current match channel.
    :param a_player: Player to send the account to.
    """
    msg = None
    # Try 3 times to send a DM:
    ctx = a_player.account.get_new_context(ContextWrapper.user(a_player.id))
    for j in range(3):
        try:
            msg = await disp.ACC_UPDATE.send(ctx, account=a_player.account)
            break
        except discord.errors.Forbidden:
            pass
    if not msg:
        # Else validate the account and send it to staff channel instead
        await disp.ACC_CLOSED.send(channel, a_player.mention)
        await a_player.account.validate()
        msg = await disp.ACC_STAFF.send(ContextWrapper.channel(
            cfg.channels["staff"]),
                                        f'<@&{cfg.roles["admin"]}>',
                                        a_player.mention,
                                        account=a_player.account)
    # Set the account message, log the account:
    a_player.account.message = msg
    await disp.ACC_LOG.send(ContextWrapper.channel(cfg.channels["spam"]),
                            a_player.name, a_player.id, a_player.account.id)
Esempio n. 3
0
    async def on_ready():
        # Initialise matches channels
        Match.init_channels(client, cfg.channels["matches"])

        modules.roles.init(client)
        # Init signal handler
        modules.signal.init()

        # fetch rule message, remove all reaction but the bot's
        channel = client.get_channel(cfg.channels["rules"])
        msg = await channel.fetch_message(channel.last_message_id)
        if msg.author.id == client.user.id:
            ctx = _interactions_handler.get_new_context(msg)
            await disp.RULES.edit(ctx)
        else:
            ctx = _interactions_handler.get_new_context(channel)
            await disp.RULES.send(ctx)

        # Update all players roles
        for p in Player.get_all_players_list():
            await modules.roles.role_update(p)
        _add_main_handlers(client)

        if not modules.lobby.get_all_names_in_lobby():
            try:
                last_lobby = modules.database.get_field(
                    "restart_data", 0, "last_lobby")
            except KeyError:
                pass
            else:
                for p_id in last_lobby:
                    try:
                        player = Player.get(int(p_id))
                        if player and not modules.lobby.is_lobby_stuck(
                        ) and player.is_registered:
                            modules.lobby.add_to_lobby(player)
                    except ValueError:
                        pass
                modules.database.set_field("restart_data", 0,
                                           {"last_lobby": list()})
            names = modules.lobby.get_all_names_in_lobby()
            if names:
                await disp.LB_QUEUE.send(
                    ContextWrapper.channel(cfg.channels["lobby"]),
                    names_in_lobby=modules.lobby.get_all_names_in_lobby())
        modules.loader.unlock_all(client)
        log.info('Client is ready!')
        await disp.RDY.send(ContextWrapper.channel(cfg.channels["spam"]),
                            cfg.VERSION)
Esempio n. 4
0
    async def init(self):
        for p in self.p_list:
            self.players[p.id] = p
            await p.on_match_selected(self.match.proxy)
            # print(f"{p.name}, matches: {p.stats.nb_matches_played}")
            # ctx = ContextWrapper.user(p.id)
            # try:
            #     await disp.MATCH_DM_PING.send(ctx, match.id, match.channel.name)
            # except discord.errors.Forbidden:
            #     log.warning(f"Player id:[{p.id}], name:[{p.name}] is refusing DMs")

        # Open match channel
        await roles.modify_match_channel(self.match.channel, view=True)
        await disp.LB_MATCH_STARTING.send(
            ContextWrapper.channel(cfg.channels["lobby"]),
            self.match.channel.id)

        players_ping = " ".join(p.mention for p in self.players.values())
        await disp.MATCH_INIT.send(self.match.channel, players_ping)

        # Initialize teams
        self.match.teams[0] = Team(0, f"Team 1", self.match.proxy)
        self.match.teams[1] = Team(1, f"Team 2", self.match.proxy)

        await self.info()

        self.auto_captain.start()
        await disp.CAP_AUTO_ANNOUNCE.send(self.match.channel)
Esempio n. 5
0
async def _lobby_loop():
    for p in _lobby_list:
        now = tools.timestamp_now()
        if p.lobby_stamp < (now - 7800):
            remove_from_lobby(p)
            await disp.LB_TOO_LONG.send(
                ContextWrapper.channel(cfg.channels["lobby"]),
                p.mention,
                names_in_lobby=get_all_names_in_lobby())
        elif p.lobby_stamp < (now - 7200):
            if p not in _warned_players:
                ih = interactions.InteractionHandler(p, views.reset_button)
                _warned_players[p] = ih
                _add_ih_callback(ih, p)
                ctx = ih.get_new_context(
                    ContextWrapper.channel(cfg.channels["lobby"]))
                await disp.LB_WARNING.send(ctx, p.mention)
Esempio n. 6
0
    async def timeout(self, ctx, *args):
        if len(args) == 1 and args[0] == "help":
            await disp.RM_TIMEOUT_HELP.send(ctx)
            return
        if len(ctx.message.mentions) != 1:
            await disp.RM_MENTION_ONE.send(ctx)
            return
        player = Player.get(ctx.message.mentions[0].id)
        if not player:
            # player isn't even registered in the system...
            player = Player(ctx.message.mentions[0].id,
                            ctx.message.mentions[0].name)
            await db.async_db_call(db.set_element, "users", player.id,
                                   player.get_data())
        if player.is_lobbied:
            lobby.remove_from_lobby(player)
            await disp.RM_LOBBY.send(
                ContextWrapper.channel(cfg.channels["lobby"]),
                player.mention,
                names_in_lobby=lobby.get_all_names_in_lobby())
        if player.match:
            await disp.RM_IN_MATCH.send(ctx)
            return

        if len(args) == 0:
            if player.is_timeout:
                await disp.RM_TIMEOUT_INFO.send(
                    ctx,
                    dt.utcfromtimestamp(
                        player.timeout).strftime("%Y-%m-%d %H:%M UTC"))
                return
            await roles.role_update(player)
            await roles.perms_muted(False, player.id)
            await disp.RM_TIMEOUT_NO.send(ctx)
            return
        # =timeout @player remove
        if len(args) == 1 and args[0] == 'remove':
            player.timeout = 0
            await player.db_update("timeout")
            await disp.RM_TIMEOUT_FREE.send(ctx, player.mention)
            await roles.role_update(player)
            await roles.perms_muted(False, player.id)
            return
        # Check if command is correct (=timeout @player 12 d)

        time = tools.time_calculator(" ".join(args))
        if time == 0:
            await disp.RM_TIMEOUT_INVALID.send(ctx)
            return

        end_time = tools.timestamp_now() + time
        player.timeout = end_time
        await roles.role_update(player)
        await player.db_update("timeout")
        await roles.perms_muted(True, player.id)
        await disp.RM_TIMEOUT.send(
            ctx, player.mention,
            dt.utcfromtimestamp(end_time).strftime("%Y-%m-%d %H:%M UTC"))
Esempio n. 7
0
 async def on_match_over(self):
     player_pings = [" ".join(tm.all_pings) for tm in self.match.teams]
     self.auto_info_loop.cancel()
     self.ih.clean()
     self.match.plugin_manager.on_round_over()
     round_no = self.match.round_no
     self.match.ready_next_process()
     await disp.MATCH_ROUND_OVER.send(self.match.channel, *player_pings, round_no)
     try:
         await census.process_score(self.match.data, self.match.last_start_stamp, self.match.channel)
         try:
             await i_maker.publish_match_image(self.match)
         except Exception as e:
             # Should not happen
             log.error(f"Error in publish_match_image : {e}")
             await disp.PUBLISH_ERROR.send(ContextWrapper.channel(cfg.channels["results"]), self.match.id, round_no)
     except ApiNotReachable as e:
         log.error(f"ApiNotReachable caught when processing scores : {e.url}")
         await disp.API_SCORE_ERROR.send(ContextWrapper.channel(cfg.channels["results"]), self.match.id, round_no)
     self.match.start_next_process()
Esempio n. 8
0
 async def on_user_react(p, interaction_id, interaction,
                         interaction_values):
     user = interaction.user
     if user.id == player.id:
         ctx = ContextWrapper.channel(cfg.channels["lobby"])
         ctx.author = user
         reset_timeout(player)
         await disp.LB_REFRESHED.send(ctx)
     else:
         i_ctx = InteractionContext(interaction)
         await disp.LB_REFRESH_NO.send(i_ctx)
         raise interactions.InteractionNotAllowed
Esempio n. 9
0
async def on_dm(message):
    # Check if too many requests from this user:
    if await spam_checker.is_spam(message.author, message.channel):
        return
    if message.content[:1] == "=":
        message.content = message.content[1:]
    if message.content.lower().startswith(("stat", "stats", "s")):
        await on_stats(message.author)
    elif message.content.lower().startswith(("modmail ", "dm ", "staff ")):
        i = message.content.index(' ')
        message.content = message.content[i + 1:]
        player = Player.get(message.author.id)
        await disp.BOT_DM.send(ContextWrapper.channel(cfg.channels["staff"]),
                               player=player,
                               msg=message)
        await disp.BOT_DM_RECEIVED.send(message.author)
    elif message.content.lower().startswith(("help", "h")):
        await disp.HELP.send(message.author, is_dm=True)
    spam_checker.unlock(message.author.id)
Esempio n. 10
0
 async def unregister(self, ctx):
     if not await _check_channels(ctx, cfg.channels["register"]):
         return
     player = await get_check_player(ctx)
     if not player:
         return
     if player.is_lobbied:
         lobby.remove_from_lobby(player)
         await disp.RM_LOBBY.send(
             ContextWrapper.channel(cfg.channels["lobby"]),
             player.mention,
             names_in_lobby=lobby.get_all_names_in_lobby())
     if not player.match:
         try:
             await db.async_db_call(db.remove_element, "users", player.id)
         except db.DatabaseError:
             pass  # ignored if not yet in db
         await roles.remove_roles(player.id)
         player.remove()
         await disp.RM_OK.send(ctx)
         return
     await disp.RM_IN_MATCH.send(ctx)
Esempio n. 11
0
 async def remove(self, ctx):
     if ctx.channel.id == cfg.channels["lobby"]:
         player = await get_check_player(ctx)
         if not player:
             return
         if player.is_lobbied:
             lobby.remove_from_lobby(player)
             await disp.RM_LOBBY.send(
                 ContextWrapper.channel(cfg.channels["lobby"]),
                 player.mention,
                 names_in_lobby=lobby.get_all_names_in_lobby())
             return
         await disp.RM_NOT_LOBBIED.send(ctx)
         return
     # if ctx.channel.id == cfg.channels["register"]:
     #     player = await get_check_player(ctx)
     #     if not player:
     #         return
     #     #TODO: remove ig names
     else:
         await disp.WRONG_CHANNEL_2.send(ctx, ctx.command.name,
                                         f"<#{ctx.channel.id}>")
Esempio n. 12
0
async def _send_stuck_msg():
    await disp.LB_STUCK.send(ContextWrapper.channel(cfg.channels["lobby"]))
Esempio n. 13
0
async def _auto_ping():
    if _MatchClass.find_empty() is None:
        return
    await disp.LB_NOTIFY.send(ContextWrapper.channel(cfg.channels["lobby"]),
                              f'<@&{cfg.roles["notify"]}>', get_lobby_len(),
                              cfg.general["lobby_size"])
Esempio n. 14
0
async def process_score(match: 'match.classes.MatchData',
                        start_time: int,
                        match_channel: 'TextChannel' = None):
    """
    Calculate the result score for the MatchData object provided.

    :param match: MatchData object to fill with scores.
    :param start_time: Round start timestamp: will process score starting form this time.
    :param match_channel: Match channel for illegal weapons display (optional).
    :raise ApiNotReachable: If an API call fail.
    """
    # Temp data structures
    ig_dict = dict()
    current_ill_weapons = dict()

    # Start and end timestamps
    start = start_time
    end = start + (match.round_length * 60)

    # Fill player dictionary (in-game id -> player object)
    for tm in match.teams:
        for player in tm.players:
            if not player.is_disabled:
                ig_dict[int(player.ig_id)] = player
            else:
                print(f"{player.name} is disabled!")

    # Request url:
    url = f'http://census.daybreakgames.com/s:{cfg.general["api_key"]}/get/ps2:v2/characters_event/?character_id=' \
          f'{",".join(str(p.ig_id) for p in ig_dict.values())}&type=KILL&after={start}&before={end}&c:limit=500'
    j_data = await http_request(url, retries=5)

    if j_data["returned"] == 0:
        raise ApiNotReachable(f"Empty answer on score calculation (url={url})")

    event_list = j_data["characters_event_list"]

    ill_weapons = dict()

    # Loop through all events retrieved:
    for event in event_list:

        # Get opponent player
        oppo = ig_dict.get(int(event["character_id"]))
        if not oppo:
            # interaction with outside player, skip it
            continue
        opo_loadout = oppo.get_loadout(int(event["character_loadout_id"]))

        player = ig_dict.get(int(event["attacker_character_id"]))
        if not player:
            # interaction with outside player, skip it
            continue
        player_loadout = player.get_loadout(int(event["attacker_loadout_id"]))

        # Get weapon
        weap_id = int(event["attacker_weapon_id"])
        is_hs = int(event["is_headshot"]) == 1
        weapon = Weapon.get(weap_id)
        if not weapon:
            log.error(f'Weapon not found in database: id={weap_id}')
            weapon = Weapon.get(0)

        # Parse event into loadout objects
        if oppo is player:
            # Player killed themselves
            player_loadout.add_one_suicide()
        elif oppo.team is player.team:
            # Team-kill
            player_loadout.add_one_tk()
            opo_loadout.add_one_death(0)
        else:
            # Regular kill
            if not weapon.is_banned:
                # If weapon is allowed
                pts = weapon.points
                player_loadout.add_one_kill(pts, is_hs)
                opo_loadout.add_one_death(pts)
            else:
                # If weapon is banned, add it to illegal weapons list
                player_loadout.add_illegal_weapon(weapon.id)
                if player not in ill_weapons:
                    ill_weapons[player] = AutoDict()
                ill_weapons[player].auto_add(weapon.id, 1)

    # Display all banned-weapons uses for this player:
    for player in ill_weapons.keys():
        for weap_id in ill_weapons[player]:
            weapon = Weapon.get(weap_id)
            if match_channel:
                await display.SC_ILLEGAL_WE.send(match_channel, player.mention,
                                                 weapon.name, match.id,
                                                 ill_weapons[player][weap_id])
                await display.SC_ILLEGAL_WE.send(
                    ContextWrapper.channel(cfg.channels["staff"]),
                    player.mention, weapon.name, match.id,
                    ill_weapons[player][weap_id])

    # Also get base captures
    await get_captures(match, start, end)