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)
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)
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)
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)
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)
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"))
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()
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
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)
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)
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}>")
async def _send_stuck_msg(): await disp.LB_STUCK.send(ContextWrapper.channel(cfg.channels["lobby"]))
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"])
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)