Compare commits

...
8 changed files with 117 additions and 67 deletions
-4
View File
@@ -2,9 +2,6 @@
Defines cog for guild listeners. Contains functions for various guild events. Defines cog for guild listeners. Contains functions for various guild events.
""" """
import os
import json
from nextcord.ext import commands from nextcord.ext import commands
import nextcord import nextcord
@@ -20,7 +17,6 @@ class GuildListener(commands.Cog, name="Guild Listener"):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_join(self, guild: nextcord.Guild): async def on_guild_join(self, guild: nextcord.Guild):
"""Listener for Guild Join. Creates skeleton for new guild joined and saves it.""" """Listener for Guild Join. Creates skeleton for new guild joined and saves it."""
# turning guild id into string because json doesn't support ints as object keys.
highscores_data.add_new_server(guild.id) highscores_data.add_new_server(guild.id)
welcome_message: str = "Hello, I keep track of Highscores for you!" welcome_message: str = "Hello, I keep track of Highscores for you!"
+14
View File
@@ -2,6 +2,8 @@
Defines cog for on message listener. Defines cog for on message listener.
""" """
from datetime import date
import random
import re import re
from nextcord.ext import commands from nextcord.ext import commands
@@ -22,7 +24,19 @@ class SubmissionListener(commands.Cog, name="Message Listener"):
@commands.Cog.listener() @commands.Cog.listener()
async def on_message(self, message: nextcord.Message): async def on_message(self, message: nextcord.Message):
"""Listener for message creation. Adds score and attachments to submission.""" """Listener for message creation. Adds score and attachments to submission."""
# don't want to process any messages from bot.
if message.author.id == self.bot.user.id:
return
guild_id = message.guild.id guild_id = message.guild.id
# troll addition for friends birthday
if guild_id == 239758371358638080 and date.today() == date(2022, 7, 31):
# 5% chance to send the message
chance = random.randint(1, 20)
if chance == 1:
await message.channel.send("Happy Birthday Chris <@642330132958281750>")
if message.author.id in submission_objects: if message.author.id in submission_objects:
message_id = submission_objects[message.author.id]["message_id"] message_id = submission_objects[message.author.id]["message_id"]
submission_channel_id = highscores_data.get_guild_submission_channel(guild_id) submission_channel_id = highscores_data.get_guild_submission_channel(guild_id)
+53
View File
@@ -0,0 +1,53 @@
"""
Functions for controlling the bot's presence.
"""
import random
from nextcord.ext import commands
from nextcord.ext import tasks
import nextcord
class BotPresence(commands.Cog, name="Bot Presence"):
"""Class for bot presence functions."""
def __init__(self, bot: commands.Bot):
self.bot = bot
@commands.Cog.listener()
async def on_guild_join(self, guild: nextcord.Guild): # pylint: disable=unused-argument
"""Listener for Guild Join. Updated presence on guild join."""
await self.change_presence()
@commands.Cog.listener()
async def on_ready(self):
"""Starts the loop when bot is ready."""
await self.bot.wait_until_ready()
# pylint doesn't recognize that periodic_change_presense is subclassed from tasks.loop.
self.periodic_change_presence.start() # pylint: disable=no-member
@tasks.loop(minutes=2)
async def periodic_change_presence(self):
"""Loops every 2 minutes and changes presence."""
await self.change_presence()
async def change_presence(self):
"""Randomly chooses a presence and updates bot's presence."""
statuses = [
f"?help | {len(self.bot.guilds)} servers",
f"Vuln Pls. | {len(self.bot.guilds)} servers",
f"All your base are belong to us. | {len(self.bot.guilds)} servers",
f"Double plus good. | {len(self.bot.guilds)} servers",
]
status = random.choice(statuses)
await self.bot.change_presence(activity=nextcord.Game(status))
# This function will be called when this extension is loaded.
# It is necessary to add these functions to the bot.
def setup(bot: commands.Bot):
"""Adds function to bot"""
bot.add_cog(BotPresence(bot))
+11 -2
View File
@@ -236,7 +236,7 @@ class SubmissionView(nextcord.ui.View):
bot: commands.Bot, bot: commands.Bot,
submission_user: int, submission_user: int,
*, *,
timeout: Optional[float] = 180, timeout: Optional[float] = 300,
): ):
super().__init__(timeout=timeout) super().__init__(timeout=timeout)
self._submission_user = submission_user self._submission_user = submission_user
@@ -264,4 +264,13 @@ class SubmissionView(nextcord.ui.View):
self.add_item(SubmitButton(self._bot)) self.add_item(SubmitButton(self._bot))
async def interaction_check(self, interaction: nextcord.Interaction) -> bool: async def interaction_check(self, interaction: nextcord.Interaction) -> bool:
return self._submission_user == interaction.user.id check = self._submission_user == interaction.user.id
if not check:
await interaction.send("This is not your submission.", ephemeral=True)
return check
async def on_timeout(self) -> None:
# remove user from submission objects after time out. Allows user to start new submission.
submission_objects.pop(self._submission_user)
+14 -14
View File
@@ -1,8 +1,8 @@
{ {
"tables": { "tables": {
"The Ambassador": [ "The Ambassador": [
"Kill Count", "Solo Kill Count",
"Kill Time", "Solo Kill Time",
"Group Kill Count", "Group Kill Count",
"Group Kill Time", "Group Kill Time",
"Spooned Log" "Spooned Log"
@@ -21,8 +21,8 @@
"Spooned Log" "Spooned Log"
], ],
"Astellarn": [ "Astellarn": [
"Kill Count", "Solo Kill Count",
"Kill Time", "Solo Kill Time",
"Group Kill Count", "Group Kill Count",
"Group Kill Time", "Group Kill Time",
"Spooned Log" "Spooned Log"
@@ -42,8 +42,8 @@
"Spooned Log" "Spooned Log"
], ],
"Black Stone Dragon": [ "Black Stone Dragon": [
"Kill Count", "Solo Kill Count",
"Kill Time", "Solo Kill Time",
"Group Kill Count", "Group Kill Count",
"Group Kill Time", "Group Kill Time",
"Spooned Log" "Spooned Log"
@@ -65,8 +65,8 @@
"Spooned Log" "Spooned Log"
], ],
"Crassian Leviathan": [ "Crassian Leviathan": [
"Kill Count", "Solo Kill Count",
"Kill Time", "Solo Kill Time",
"Group Kill Count", "Group Kill Count",
"Group Kill Time", "Group Kill Time",
"Spooned Log" "Spooned Log"
@@ -160,8 +160,8 @@
"Spooned Log" "Spooned Log"
], ],
"Masuta the Ascended": [ "Masuta the Ascended": [
"Kill Count", "Solo Kill Count",
"Kill Time", "Solo Kill Time",
"Group Kill Count", "Group Kill Count",
"Group Kill Time", "Group Kill Time",
"Spooned Log" "Spooned Log"
@@ -193,15 +193,15 @@
"Spooned Log" "Spooned Log"
], ],
"The Sanctum Guardian": [ "The Sanctum Guardian": [
"Kill Count", "Solo Kill Count",
"Kill Time", "Solo Kill Time",
"Group Kill Count", "Group Kill Count",
"Group Kill Time", "Group Kill Time",
"Spooned Log" "Spooned Log"
], ],
"Seiryu the Azure Serpent": [ "Seiryu the Azure Serpent": [
"Kill Count", "Solo Kill Count",
"Kill Time", "Solo Kill Time",
"Group Kill Count", "Group Kill Count",
"Group Kill Time", "Group Kill Time",
"Spooned Log" "Spooned Log"
+6 -6
View File
@@ -4,6 +4,7 @@ main file for pvm-highscores bot
import logging import logging
import os import os
import sys
import nextcord import nextcord
from nextcord.ext import commands from nextcord.ext import commands
@@ -32,6 +33,11 @@ submission_objects: dict = {}
def main(): def main():
"""Main function for bot.""" """Main function for bot."""
min_python_version = (3, 7)
if sys.version_info < min_python_version:
print("ERROR: Python version must be >= 3.7")
sys.exit()
# Allows privledged intents for monitoring members joining, roles editing, and role assignments # Allows privledged intents for monitoring members joining, roles editing, and role assignments
# These need to be enabled in the developer portal as well # These need to be enabled in the developer portal as well
intents = nextcord.Intents.default() intents = nextcord.Intents.default()
@@ -45,15 +51,9 @@ def main():
# To enable the members priveleged intent: # To enable the members priveleged intent:
# intents.members = True # intents.members = True
# Set custom status to "Listening to ?help"
activity = nextcord.Activity(
type=nextcord.ActivityType.listening, name=f"{config.BOT_PREFIX}help"
)
bot = commands.Bot( bot = commands.Bot(
commands.when_mentioned_or(config.BOT_PREFIX), commands.when_mentioned_or(config.BOT_PREFIX),
intents=intents, intents=intents,
activity=activity,
) )
# Get the modules of all cogs whose directory structure is ./cogs/<module_name> # Get the modules of all cogs whose directory structure is ./cogs/<module_name>
+9 -32
View File
@@ -32,8 +32,8 @@ class HighscoresData:
skeleton["tables"][boss] = {"message_id": 0} skeleton["tables"][boss] = {"message_id": 0}
boss_categories = {} boss_categories = {}
for category in categories: for category in categories:
rank_list = [] scores_list = {}
boss_categories[category] = rank_list boss_categories[category] = scores_list
skeleton["tables"][boss]["categories"] = boss_categories skeleton["tables"][boss]["categories"] = boss_categories
self._data[str(guild_id)] = skeleton self._data[str(guild_id)] = skeleton
@@ -66,40 +66,17 @@ class HighscoresData:
minutes = score.split(":")[0] minutes = score.split(":")[0]
seconds = score.split(":")[1] seconds = score.split(":")[1]
score_seconds = int(minutes) * 60 + float(seconds) score_seconds = int(minutes) * 60 + float(seconds)
score_tuple = (user, score, score_seconds) score_list = [score, score_seconds]
sort_index = 2
else:
score_tuple = (user, int(score))
sort_index = 1 sort_index = 1
else:
score_list = [int(score)]
sort_index = 0
# if user is in an existing tuple, delete it. # Will not ensure new score is better than old one. Allows for correcting mistakes.
users_scores: "list[tuple]" = [score_tuple]
for tup in scores:
if user == tup[0]:
# Add tup to users_scores, remove from scores
users_scores.append(tup)
# sort users_scores scores[user] = score_list
users_scores.sort(
key=lambda x: x[sort_index],
reverse=not ascending,
)
for index, tup in enumerate(users_scores): scores = dict(sorted(scores.items(), key=lambda x: x[1][sort_index], reverse=not ascending))
if index == 0:
# first score is the best score.
if tup not in scores:
scores.append(tup)
else:
# discard all other scores from scores list.
if tup in scores:
scores.remove(tup)
# sort scores.
scores.sort(
key=lambda x: x[sort_index],
reverse=not ascending,
)
self._data[str(guild_id)]["tables"][boss_name]["categories"][category] = scores self._data[str(guild_id)]["tables"][boss_name]["categories"][category] = scores
save_highscores_data(self._data) save_highscores_data(self._data)
+10 -9
View File
@@ -17,27 +17,28 @@ def format_highscore_message(boss_name: str, guild_id: int):
ret_string = f"**{boss_name}**\n```" ret_string = f"**{boss_name}**\n```"
# Gather all categories and add to string # Gather all categories and add to string
for key, value in highscores_data.get_categories_data(guild_id, boss_name): for category_name in highscores_data.get_table_categories(guild_id, boss_name):
ret_string += f"{key}".ljust(26, " ") ret_string += f"{category_name}".ljust(26, " ")
ret_string += "\n" ret_string += "\n"
highscore_size = highscores_data.get_config_highscore_size() highscore_size = highscores_data.get_config_highscore_size()
# list rankings in a single line. Start with first place for each category and then continue # list rankings in a single line. Start with first place for each category and then continue
for i in range(highscore_size): for i in range(highscore_size):
for key, value in highscores_data.get_categories_data(guild_id, boss_name): for category_name, category_data in highscores_data.get_categories_data(
if len(value) > i: guild_id, boss_name
score_pair = value[i] ):
if len(category_data) > i:
# pad username to max length. # pad username to max length.
username: str = score_pair[0].ljust( username: str = list(category_data.keys())[i].ljust(
highscores_data.get_guild_username_length(guild_id), " " highscores_data.get_guild_username_length(guild_id), " "
) )
score: str = str(score_pair[1]) # turns category data value into a string. Very janky.
score: str = str(list(category_data.values())[i][0])
# pad score to correct length # pad score to correct length
# MM:SS.ms is 7 characters long # MM:SS.ms is 7 characters long
if highscores_data.get_config_time_record(key): if highscores_data.get_config_time_record(category_name):
# if there are single digit minutes, add a space for formatting. # if there are single digit minutes, add a space for formatting.
if score.find(":") and len(score.split(":", maxsplit=1)[0]) < 2: if score.find(":") and len(score.split(":", maxsplit=1)[0]) < 2:
score = " " + score score = " " + score