def build_stream(self, twitch_reports, time_limit): embeds = [] for key, player in twitch_reports.items(): report_amount = len(player['reports']) utilities.dlog("Building stream report embed") if report_amount == 1: report = player['reports'][0] link = "".join(["https://pubg.report/streams/", report['MatchID'], "/", str(report['AttackID'])]) embed = discord.Embed(title="PUBG Report", url=link, color=0x00ff00) embed.add_field(name=" ".join([report['Killer'], "has been streamed killing", report['Victim']]), value="Weapon: WeapG36C_C", inline=True) embeds.append(embed) elif report_amount > 1: link = "".join(["https://pubg.report/streams/", player['id'], "/"]) embed = discord.Embed(title="PUBG Report", url=link, color=0x00ff00) embed.add_field(name=" ".join([player['name'], "has", str(report_amount), "new reports in the last", str(time_limit), "days"]), value=" ".join([str(player['knocks']), "knocks and", str(player['downs']), "downs"]), inline=True) embed.set_footer(text="PUBG-BOT") embeds.append(embed) if len(embeds) > 0: return { "embeds": embeds, "type": ConfigOption.notification_channel_stream_report } else: return None
async def send_guild_notifications(self, guild, queue): send_channel = utilities.get_guild_config(guild.id, queue['type']) for embed in queue['embeds']: utilities.dlog("Sending notification to", guild.name, "in channel", send_channel) text_channel = utilities.get_channel(guild.text_channels, send_channel) await text_channel.send(embed=embed)
def get_match_reports(self): latest_match = 0 searched_maches = {} latest_match = None for player_result in self.players_pubg: match_id = player_result.matches[0]['id'] if latest_match != None and latest_match.id == match_id: continue match = pubg.Api(match_id, shard=self.shard).get_match().result if (latest_match == None or match.createdAt > latest_match.createdAt and match.createdAt > utilities.time_days_ago( config.MATCH_NOTIFICATION_TIME_LIMIT)): latest_match = match if latest_match != None: roster = self.get_group_roster(latest_match, self.players) cache_key = [ "pubg_roster_match_report", roster.id, latest_match.id ] if roster != None and not cache.exists_or_create(cache_key): utilities.dlog("Found unreported latest match for a roster") roster.total_kills = utilities.get_participants_total_kills( roster.participants) return {"match": latest_match, "roster": roster}
async def config_get(message, param, param2): utilities.dlog("Config read request. Key:", param) if param in config.CONFIG_OPTIONS: value = utilities.get_guild_config(message.guild.id, param) await message.channel.send(" ".join(['Configuration value for key:', param, "is:", value])) else: utilities.dlog("Invalid config change request") await message.channel.send('Configuration read failed. Key does not exist.')
def __init__(self, players, region_roles): self.region_roles = region_roles self.members = players self.players = utilities.flatten_member_list(players) self.players_key = "|".join(self.players) self.region = self.get_region() utilities.dlog("Using shard for region:", self.region) self.shard = shard_map[self.region] self.players_pubg = pubg.Api(self.players, shard=self.shard).get_players().result
def check_expiry(self, key, data): if isinstance(data, dict) and 'expiry' in data: time_now = utilities.time_now() if data['expiry'] < time_now: utilities.dlog("Deleting expired cache item", key, "Expiry:", data['expiry'], "Time:", time_now) self.delete(key) return False else: return data['value'] else: return data
def get_active_guild_members(guild): utilities.dlog("processing guild:", guild.name) voice_channels = guild.voice_channels members = [] listen_channel = utilities.get_guild_config(guild.id, ConfigOption.listener_channel_name) utilities.dlog("Getting members from channel:", listen_channel) for channel in voice_channels: if channel.name.lower() == listen_channel: members = members + channel.members return members
async def run(self, guilds): try: utilities.dlog("# of active guilds: ", len(guilds)) loop.create_task(self.loop_guilds(guilds)) self.sleeper = Sleeper(loop) await self.sleeper.sleep(self.config.TICK_RATE) except Exception as e: print(e) print("Error raised in listener.") if self.stop_request != True: await self.run(guilds)
def build_match(self, match, members): if match == None: return elif match['roster'].won: roster = match['roster'] url = utilities.get_match_telemetry_link(match) embed = discord.Embed(title=" ".join(["Chicken Dinner With", str(roster.total_kills), "Kills"]), url=url, color=0x00ff00) for participant in roster.participants: member = utilities.get_member(members, participant.name) mention = "**" + participant.name + "**" if member: mention = member.mention embed.add_field(name="Player Overview", value=" ".join([mention, "\n", str(participant.stats.kills), "kills\n", str(participant.stats.DBNOs), "DBNOs\n", str(round(participant.stats.damageDealt)), "damage\n", str(participant.stats.headshotKills), "headshots\n", str(round(participant.stats.timeSurvived / 60)), "minutes alive"]), inline=True) if match['match'].isCustomMatch: embed.set_footer(text=" ".join(["Custom Match -", utilities.get_map_name(match['match'].mapName), "- PUBG-BOT"])) else: embed.set_footer(text=" ".join(["Regular Match -", utilities.get_map_name(match['match'].mapName), "- PUBG-BOT"])) utilities.dlog("Building chicken dinner embed") return { "embeds": [embed], "type": ConfigOption.notification_channel_win } elif match['roster'].rank <= self.config.MIN_RANK: roster = match['roster'] url = utilities.get_match_telemetry_link(match) embed = discord.Embed(title=" ".join(["Ranked #" + str(roster.rank), "With", str(roster.total_kills), "Kills"]), url=url, color=0x00ff00) for participant in roster.participants: member = utilities.get_member(members, participant.name) mention = "**" + participant.name + "**" if member: mention = member.mention embed.add_field(name="Player Overview", value=" ".join([mention, "\n", str(participant.stats.kills), "kills\n", str(participant.stats.DBNOs), "DBNOs\n", str(round(participant.stats.damageDealt)), "damage\n", str(participant.stats.headshotKills), "headshots\n", str(round(participant.stats.timeSurvived / 60)), "minutes alive"]), inline=True) if match['match'].isCustomMatch: embed.set_footer(text=" ".join(["Custom Match -", utilities.get_map_name(match['match'].mapName), "- PUBG-BOT"])) else: embed.set_footer(text=" ".join(["Regular Match -", utilities.get_map_name(match['match'].mapName), "- PUBG-BOT"])) utilities.dlog("Building high rank embed") return { "embeds": [embed], "type": ConfigOption.notification_channel_high_rank } else: return None
def write(self, key, value=True, expire=0): if isinstance(key, list): key = self.key(key) if expire != 0: utilities.dlog("Writing expirable cache item", key) self.db[key] = { "expiry": utilities.time_days_ahead(expire), "value": value } else: self.db[key] = value
def exists(self, key, check_expiry=True): if isinstance(key, list): key = self.key(key) if key in self.db: utilities.dlog("Item exists in cache", key) if check_expiry == True: if self.check_expiry(key, self.db[key]) != False: return True else: return True
def get_active_season(self): key = [CacheKey.active_season] if cache.exists(key): return cache.read(key, check_exists=False) else: utilities.dlog("Updating active season ID") active_season = self.get_seasons().result[-1] cache.write(key, active_season, expire=utilities.hours_from_day( config.ACTIVE_SEASON_CACHE_DAYS)) return active_season
async def config_set(message, param, param2): split_param = param.split(" ") key = split_param[0] value = param[len(key) + 1:] utilities.dlog("Config change request. Key:", key, "Value:", value) if key in config.CONFIG_OPTIONS and utilities.valid_config(value): cache.write([CacheKey.config_option, str(message.guild.id), key], value) await message.channel.send('Configuration has succesfully been stored.') else: utilities.dlog("Invalid config change request") await message.channel.send('Configuration change failed. Key does not exist or value is invalid.')
def build_stats(player): utilities.dlog("Building stats embed") embed = discord.Embed(title=" ".join(['Stats for', player.name]), color=0x00ff00) embed.add_field(name="KD", value=player.kd, inline=True) embed.add_field(name="Wins", value=player.wins, inline=True) embed.add_field(name="Kills", value=player.kills, inline=True) embed.add_field(name="Rounds", value=player.roundsPlayed, inline=True) embed.add_field(name="Longest Kill", value=str(round(player.longestKill)) + "m", inline=True) embed.add_field(name="Team Kills", value=player.teamKills, inline=True) embed.add_field(name="Season playtime", value=str(round(player.timeSurvived / 60 / 60)) + " hours", inline=True) embed.add_field(name="Top 10", value=str(round((player.top10s / player.roundsPlayed) * 100.0)) + "%", inline=True) embed.add_field(name="Headshots", value=str(round((player.headshotKills / player.kills) * 100.0)) + "%", inline=True) return embed
def get(self, query, build_query=True): utilities.dlog("GET:", query) if build_query == True: query = self.build_endpoint(query) try: self.result = requests.get(url=query, headers=self.headers).json() except json.decoder.JSONDecodeError: self.result = {"errors": [{"title": "Rate Limit"}]} return self self.log_errors() return self
async def loop_guilds(self, guilds): queue = {} for guild in guilds: if utilities.should_skip_guild(guild.id): utilities.dlog("Skipping server:", guild.name, "because of debug mode") continue reports = self.get_guild_reports(guild) if reports == None: continue match_notifications = self.notifications.build_match(reports['match'], guild.members) stream_notifications = self.notifications.build_stream(reports['stream'], self.config.STREAM_TIME_LIMIT) if match_notifications != None: await self.send_guild_notifications(guild, match_notifications) if stream_notifications != None: await self.send_guild_notifications(guild, stream_notifications)
async def on_message(self, message): if message.author == self.user: return utilities.dlog("Message received:", message.content) if message.author == message.guild.owner or utilities.get_role( message.author.roles, 'bot-commander'): await commands.register(';config-set', commands.config_set, message) await commands.register(';config-get', commands.config_get, message) if message.author == message.guild.owner: await commands.register(';purge', commands.purge, message, self.user) await commands.register(';get-id', commands.get_id, message, self.user) if utilities.should_skip_guild(message.guild.id): utilities.dlog("Skipping command request from:", message.guild.name, "because of debug mode") return # Admin commands #if message.author == message.guild.owner or utilities.get_role(message.author.roles, 'bot-commander'): #await commands.register(';config-set', commands.config_set, message) #await commands.register(';config-get', commands.config_get, message) await commands.register([';help', ';h'], commands.help_manager, message) await commands.register(';register', commands.register_pubg, message, param=client, channel="register", delete_otherwise=True)
def log_errors(self): if self.has_errors(): if self.has_error(ApiError.not_found): utilities.dlog("PUBG API request returned 404") else: utilities.dlog("PUBG API unknown error", self.result['errors'])
async def on_guild_remove(self, guild): utilities.dlog("{} has been removed".format(guild.name))
async def on_guild_join(self, guild): utilities.dlog("{} has been added".format(guild.name))
async def register_pubg(message, param, param2): if message.channel.name != "register": return params = param.split(" ") if len(params) != 2: utilities.dlog("Incorrect number of parameters") await message.channel.send("Incorrect number of parameters. Please include your name and whether you are EU/NA.") return name = params[0] region_param = params[1].lower() if region_param not in shard_map: utilities.dlog("Invalid region") await message.channel.send("Invalid region") return region = shard_map[region_param] season = pubg.Api(name, shard=region).get_season_stats().result if season == None: utilities.dlog("No season stats found") await message.channel.send("No season stats found. Make sure you have typed the name correctly (with capitals).") return stats = season.squad_fpp stats.name = name if stats.roundsPlayed < 30: utilities.dlog("You must play at least 30 rounds before being registered.") await message.channel.send('You must play at least 30 rounds before being registered.') return if stats.kd >= 2: min_kd = 2 elif stats.kd >= 1: min_kd = 1 else: utilities.dlog("Too low rank") await message.channel.send('Sorry, your KD is too low to match you with any channels.') return region_roles = { "eu": utilities.get_role(message.guild.roles, "eu"), "na": utilities.get_role(message.guild.roles, "na") } delete_roles = [ utilities.get_role(message.guild.roles, "kd-1"), utilities.get_role(message.guild.roles, "kd-2"), region_roles['eu'], region_roles['na'], ] add_role = utilities.get_role(message.guild.roles, "kd-" + str(min_kd)) try: for role in delete_roles: await message.author.remove_roles(role) utilities.dlog("Adding roles:", add_role, region_roles[region_param]) await message.author.add_roles(add_role, region_roles[region_param]) except discord.errors.Forbidden: utilities.dlog("Cannot set roles for:", message.author.name, "to role:", role) try: await message.author.edit(nick=stats.name) except discord.errors.Forbidden: utilities.dlog("Cannot set nickname for:", message.author.name) await message.channel.send('Succesfully linked. You may now join channels up to +' + str(min_kd) + ' KD.')
async def on_ready(self): utilities.dlog('Logged on as', self.user)