From 51c38634f680de45480d0cdd8e003eb75ff064d9 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 13:42:19 -0500 Subject: [PATCH 01/38] =?UTF-8?q?feat:=20=E2=9C=A8=20Allow=20users=20to=20?= =?UTF-8?q?upload=20files=20directly=20to=20importclases=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/channel.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/cogs/channel.py b/cogs/channel.py index 982dbdf..1e602f8 100644 --- a/cogs/channel.py +++ b/cogs/channel.py @@ -11,7 +11,7 @@ from nextcord.utils import find import re import nextcord -from nextcord import Interaction, SlashOption, PermissionOverwrite, Permissions, Colour, Embed +from nextcord import Interaction, SlashOption, PermissionOverwrite, Permissions, Colour, Embed, Attachment with open("config.yaml") as file: @@ -60,29 +60,27 @@ class SectionJson(TypedDict): JSON_SCHEMA = "https://raw.githubusercontent.com/EMU-Compsci-Discord/compsci-class-scraper/main/json-schema/output-v1.schema.json" -def read_class_json(file_name: str) -> SectionJson: +async def read_class_json(file: Attachment) -> SectionJson: """ - reads a json file containing classes + reads a json file Attachment containing classes """ - if not file_name.endswith('.json'): - raise Exception("File name must end with .json") + content_type, encoding = file.content_type.split("; ") - if re.search("^[a-zA-Z0-9_\-]+\.json$", file_name) is None: - raise Exception("File name can only contain letters, numbers, dashes and underscores") + if content_type != "application/json": + raise Exception(f"File must be a JSON file but was {content_type}") - file_path = Path("resources", file_name) + if encoding != "charset=utf-8": + raise Exception(f"File must be encoded in UTF-8 but was {encoding}") - if not file_path.is_file(): - raise Exception(f"File {file_path} does not exist") + file_contents = await file.read() - with open(file_path) as file: - data = json.load(file) + data = json.loads(file_contents) - if data["$schema"] != JSON_SCHEMA: - raise Exception(f"Incorrect JSON schema\nExpected: {JSON_SCHEMA}\nFound: {data['$schema']}") + if data["$schema"] != JSON_SCHEMA: + raise Exception(f"Incorrect JSON schema\nExpected: {JSON_SCHEMA}\nFound: {data['$schema']}") - return data + return data course_name_regex = re.compile('(COSC|MATH|STAT)[- ]([0-9]{3})', re.I) @@ -149,13 +147,13 @@ def __init__(self, bot): @nextcord.slash_command(name="importclasses") @has_permissions(administrator=True) - async def import_classes(self, interaction: Interaction, file_name: str = SlashOption(description="The name of the JSON file to parse.", required=True)): + async def import_classes(self, interaction: Interaction, file: Attachment = SlashOption(description="The name of the JSON file to parse.", required=True)): """ Import a JSON file and create channels and roles for each class. """ try: - json = read_class_json(file_name) + json = await read_class_json(file) except Exception as e: await interaction.response.send_message(f"Error: {e}", ephemeral=True) return From e281ba0d913bbdd0d5811bacc0927e7019a30e24 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 16:34:47 -0500 Subject: [PATCH 02/38] =?UTF-8?q?ci:=20=F0=9F=91=B7=20install=20pylint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pylintrc | 2 ++ .vscode/settings.json | 4 +++- requirements.txt | 33 +++++++++++++++++---------------- 3 files changed, 22 insertions(+), 17 deletions(-) create mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..3711eeb --- /dev/null +++ b/.pylintrc @@ -0,0 +1,2 @@ +[MAIN] +ignore=.venv diff --git a/.vscode/settings.json b/.vscode/settings.json index 3cb2271..f5aff9a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,6 @@ { "python.analysis.extraPaths": ["./cogs"], - "python.formatting.autopep8Args": ["--max-line-length", "120"] + "python.formatting.autopep8Args": ["--max-line-length", "120"], + "python.linting.pylintEnabled": true, + "python.linting.enabled": true } diff --git a/requirements.txt b/requirements.txt index b8de83d..db6c6bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,17 @@ -aiohttp -apscheduler -asyncio -nextcord -pyyaml -aiofiles -schedule -sklearn -pandas -nltk -numpy -trafilatura -inspiro -uwuify -RateMyProfessorAPI -mysql-connector \ No newline at end of file +aiohttp +apscheduler +asyncio +nextcord +pyyaml +aiofiles +schedule +sklearn +pandas +nltk +numpy +trafilatura +inspiro +uwuify +RateMyProfessorAPI +mysql-connector +pylint From 9ce5e9850e1c0afff4577118ca8d145eff6e808a Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 16:37:35 -0500 Subject: [PATCH 03/38] =?UTF-8?q?ci:=20=F0=9F=91=B7=20install=20autopep8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 1 + requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index f5aff9a..b8d1fd6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "python.analysis.extraPaths": ["./cogs"], + "python.formatting.provider": "autopep8", "python.formatting.autopep8Args": ["--max-line-length", "120"], "python.linting.pylintEnabled": true, "python.linting.enabled": true diff --git a/requirements.txt b/requirements.txt index db6c6bf..9b0fa65 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,3 +15,4 @@ uwuify RateMyProfessorAPI mysql-connector pylint +autopep8 From 5dd5dd110dca52baa938482770c52b96ee7196a8 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:08:52 -0500 Subject: [PATCH 04/38] =?UTF-8?q?ci:=20=F0=9F=91=B7=20move=20settings=20to?= =?UTF-8?q?=20pyproject.toml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pylintrc | 2 -- .vscode/settings.json | 1 - pyproject.toml | 5 +++++ 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 .pylintrc create mode 100644 pyproject.toml diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 3711eeb..0000000 --- a/.pylintrc +++ /dev/null @@ -1,2 +0,0 @@ -[MAIN] -ignore=.venv diff --git a/.vscode/settings.json b/.vscode/settings.json index b8d1fd6..5cddb8b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,6 @@ { "python.analysis.extraPaths": ["./cogs"], "python.formatting.provider": "autopep8", - "python.formatting.autopep8Args": ["--max-line-length", "120"], "python.linting.pylintEnabled": true, "python.linting.enabled": true } diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6a4e11e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,5 @@ +[tool.pylint.main] +ignore = [".venv"] + +[tool.autopep8] +max_line_length = 120 From a712c2010289cd3b058e5082769a26ea76aead0b Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:09:19 -0500 Subject: [PATCH 05/38] =?UTF-8?q?ci:=20=F0=9F=91=B7=20add=20extra=20args?= =?UTF-8?q?=20to=20pyproject.toml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 6a4e11e..ca22e52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,9 @@ [tool.pylint.main] ignore = [".venv"] +recursive = true [tool.autopep8] max_line_length = 120 +recursive = true +exit_code = true +in_place = true From d8018e3e9945a91561e805547951482aa2bf46a4 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:19:00 -0500 Subject: [PATCH 06/38] =?UTF-8?q?ci:=20=F0=9F=91=B7=20add=20ci=20with=20gi?= =?UTF-8?q?thub=20actions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 3 +++ .github/workflows/ci.yml | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.editorconfig b/.editorconfig index a882442..5b9fdad 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,3 +5,6 @@ end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 + +[*.yml] +indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..61a7f98 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + pylint: + runs-on: ubuntu-latest + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v3 + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Run pylint + run: pylint . + + autopep8: + runs-on: ubuntu-latest + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v3 + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Run autopep8 + run: autopep8 . From b3085009e4c6f5a2cddfa20efbb8b9a005523921 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:44:39 -0500 Subject: [PATCH 07/38] =?UTF-8?q?chore:=20=F0=9F=A7=91=E2=80=8D?= =?UTF-8?q?=F0=9F=92=BB=20recomend=20VSCode=20extentions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/extensions.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..c87ca2d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "ms-python.python", + "EditorConfig.EditorConfig", + "bungcip.better-toml", + "esbenp.prettier-vscode", + "vivaxy.vscode-conventional-commits", + "eamodio.gitlens" + ] +} From c8d54bcddcbbc7bab898cb68d2eab4396c4ae5e2 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:05:34 -0500 Subject: [PATCH 08/38] =?UTF-8?q?chore:=20=F0=9F=94=A5=20remove=20unneeded?= =?UTF-8?q?=20vscode=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5cddb8b..15fa23b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,4 @@ { - "python.analysis.extraPaths": ["./cogs"], "python.formatting.provider": "autopep8", "python.linting.pylintEnabled": true, "python.linting.enabled": true From 1f3cc08efa9c72ebe75d5bc4ff140f8e64615584 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:06:32 -0500 Subject: [PATCH 09/38] =?UTF-8?q?fix:=20=F0=9F=92=9A=20use=20diff=20mode?= =?UTF-8?q?=20for=20autopep8=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 +- pyproject.toml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61a7f98..30a2d55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,4 +34,4 @@ jobs: run: pip install -r requirements.txt - name: Run autopep8 - run: autopep8 . + run: autopep8 --diff . diff --git a/pyproject.toml b/pyproject.toml index ca22e52..ede52ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,4 +6,3 @@ recursive = true max_line_length = 120 recursive = true exit_code = true -in_place = true From a5fafee5c35cef3961adac0fd6c6fcfa882d6f64 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:18:38 -0500 Subject: [PATCH 10/38] =?UTF-8?q?style:=20=F0=9F=8E=A8=20format=20python?= =?UTF-8?q?=20code=20with=20autopep8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 214 ++++++++++++++++++--------------- cogs/fun.py | 17 +-- cogs/general.py | 6 +- cogs/help.py | 1 + cogs/quotes.py | 6 +- cogs/ratemyprofessor.py | 20 +-- cogs/template.py | 58 ++++----- noncommands/auto_code_block.py | 9 +- noncommands/quotes.py | 7 +- noncommands/summarizer.py | 35 +++--- 10 files changed, 199 insertions(+), 174 deletions(-) diff --git a/bot.py b/bot.py index a37c4f5..3ae89cb 100644 --- a/bot.py +++ b/bot.py @@ -1,99 +1,115 @@ -import os -import platform -import random -import sys -import nextcord -import yaml -from apscheduler.schedulers.asyncio import AsyncIOScheduler -from apscheduler.triggers.cron import CronTrigger -from nextcord.ext import commands, tasks -from nextcord.ext.commands import Bot - -from noncommands import auto_code_block,quotes - - -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) - -intents = nextcord.Intents.default().all() - -bot = Bot(intents=intents, command_prefix="!") - -scheduler = AsyncIOScheduler() -toSchedule = quotes.Quotes(bot) -autoCodeBlock = auto_code_block.AutoCodeBlock(bot) - -# The code in this even is executed when the bot is ready -@bot.event -async def on_ready(): - print(f"Logged in as {bot.user.name}") - print(f"nextcord.py API version: {nextcord.__version__}") - print(f"Python version: {platform.python_version()}") - print(f"Running on: {platform.system()} {platform.release()} ({os.name})") - print("-------------------") - await bot.change_presence(activity=nextcord.Game("/help")) - -# Removes the default help command of nextcord.py to be able to create our custom help command. -bot.remove_command("help") - -if __name__ == "__main__": - for file in os.listdir("./cogs"): - if file.endswith(".py"): - extension = file[:-3] - try: - bot.load_extension(f"cogs.{extension}") - print(f"Loaded extension '{extension}'") - except Exception as e: - exception = f"{type(e).__name__}: {e}" - print(f"Failed to load extension {extension}\n{exception}") - -# The code in this event is executed every time someone sends a message, with or without the prefix -@bot.event -async def on_message(message): - # Ignores if a command is being executed by a bot or by the bot itself - if message.author == bot.user or message.author.bot: - return - # Ignores if a command is being executed by a blacklisted user - - if message.author.id in config["blacklist"]: - return - - await autoCodeBlock.check_message(message) - - await bot.process_commands(message) - -# The code in this event is executed every time a command has been *successfully* executed -@bot.event -async def on_command_completion(ctx): - fullCommandName = ctx.command.qualified_name - split = fullCommandName.split(" ") - executedCommand = str(split[0]) - print( - f"Executed {executedCommand} command in {ctx.guild.name} (ID: {ctx.message.guild.id}) by {ctx.message.author} (ID: {ctx.message.author.id})") - -# The code in this event is executed every time a valid commands catches an error -@bot.event -async def on_command_error(context, error): - if isinstance(error, commands.CommandOnCooldown): - minutes, seconds = divmod(error.retry_after, 60) - hours, minutes = divmod(minutes, 60) - hours = hours % 24 - embed = nextcord.Embed( - title="Hey, please slow down!", - description=f"You can use this command again in {f'{round(hours)} hours' if round(hours) > 0 else ''} {f'{round(minutes)} minutes' if round(minutes) > 0 else ''} {f'{round(seconds)} seconds' if round(seconds) > 0 else ''}.", - color=config["error"] - ) - await context.send(embed=embed) - elif isinstance(error, commands.MissingPermissions): - embed = nextcord.Embed( - title="Error!", - description="You are missing the permission `" + ", ".join( - error.missing_perms) + "` to execute this command!", - color=config["error"] - ) - await context.send(embed=embed) - raise error - -scheduler.add_job(toSchedule.dailyQuote, CronTrigger(hour="8",minute="0",second="0",day_of_week="0-4",timezone="EST")) -scheduler.start() -bot.run(config["token"]) \ No newline at end of file +import os +import platform +import random +import sys +import nextcord +import yaml +from apscheduler.schedulers.asyncio import AsyncIOScheduler +from apscheduler.triggers.cron import CronTrigger +from nextcord.ext import commands, tasks +from nextcord.ext.commands import Bot + +from noncommands import auto_code_block, quotes + + +with open("config.yaml") as file: + config = yaml.load(file, Loader=yaml.FullLoader) + +intents = nextcord.Intents.default().all() + +bot = Bot(intents=intents, command_prefix="!") + +scheduler = AsyncIOScheduler() +toSchedule = quotes.Quotes(bot) +autoCodeBlock = auto_code_block.AutoCodeBlock(bot) + + +@bot.event +async def on_ready(): + """ + The code in this even is executed when the bot is ready + """ + + print(f"Logged in as {bot.user.name}") + print(f"nextcord.py API version: {nextcord.__version__}") + print(f"Python version: {platform.python_version()}") + print(f"Running on: {platform.system()} {platform.release()} ({os.name})") + print("-------------------") + await bot.change_presence(activity=nextcord.Game("/help")) + +# Removes the default help command of nextcord.py to be able to create our custom help command. +bot.remove_command("help") + +if __name__ == "__main__": + for file in os.listdir("./cogs"): + if file.endswith(".py"): + extension = file[:-3] + try: + bot.load_extension(f"cogs.{extension}") + print(f"Loaded extension '{extension}'") + except Exception as e: + exception = f"{type(e).__name__}: {e}" + print(f"Failed to load extension {extension}\n{exception}") + + +@bot.event +async def on_message(message): + """ + The code in this event is executed every time someone sends a message, with or without the prefix + """ + + # Ignores if a command is being executed by a bot or by the bot itself + if message.author == bot.user or message.author.bot: + return + # Ignores if a command is being executed by a blacklisted user + + if message.author.id in config["blacklist"]: + return + + await autoCodeBlock.check_message(message) + + await bot.process_commands(message) + + +@bot.event +async def on_command_completion(ctx): + """ + The code in this event is executed every time a command has been *successfully* executed + """ + fullCommandName = ctx.command.qualified_name + split = fullCommandName.split(" ") + executedCommand = str(split[0]) + print( + f"Executed {executedCommand} command in {ctx.guild.name} (ID: {ctx.message.guild.id}) by {ctx.message.author} (ID: {ctx.message.author.id})") + + +@bot.event +async def on_command_error(context, error): + """ + The code in this event is executed every time a valid commands catches an error + """ + + if isinstance(error, commands.CommandOnCooldown): + minutes, seconds = divmod(error.retry_after, 60) + hours, minutes = divmod(minutes, 60) + hours = hours % 24 + embed = nextcord.Embed( + title="Hey, please slow down!", + description=f"You can use this command again in {f'{round(hours)} hours' if round(hours) > 0 else ''} {f'{round(minutes)} minutes' if round(minutes) > 0 else ''} {f'{round(seconds)} seconds' if round(seconds) > 0 else ''}.", + color=config["error"] + ) + await context.send(embed=embed) + elif isinstance(error, commands.MissingPermissions): + embed = nextcord.Embed( + title="Error!", + description="You are missing the permission `" + ", ".join( + error.missing_perms) + "` to execute this command!", + color=config["error"] + ) + await context.send(embed=embed) + raise error + +scheduler.add_job(toSchedule.dailyQuote, + CronTrigger(hour="8", minute="0", second="0", day_of_week="0-4", timezone="EST")) +scheduler.start() +bot.run(config["token"]) diff --git a/cogs/fun.py b/cogs/fun.py index eda732d..e3829d1 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -26,7 +26,7 @@ class Fun(commands.Cog, name="fun"): def __init__(self, bot): self.bot = bot - + @nextcord.slash_command(name="dadjoke", description="Get one of the classics") async def dadjoke(self, interaction: Interaction, searchterm: str = SlashOption(description="A term to try and find a dadjoke about", default="", required=False)): """ @@ -40,7 +40,7 @@ async def dadjoke(self, interaction: Interaction, searchterm: str = SlashOption( await interaction.response.send_message(random.choice(json["results"])["joke"]) except: await interaction.response.send_message("I don't think I've heard a good one about that yet. Try something else.") - + @nextcord.slash_command(name="xkcd", description="Get an xkcd comic.") async def xkcd(self, interaction: Interaction, comicnumber: int = SlashOption(description="A specific xkcd comic, like '1' to get the first comic", default="", required=False)): """ @@ -55,7 +55,7 @@ async def xkcd(self, interaction: Interaction, comicnumber: int = SlashOption(de await interaction.response.send_message(r.json()['img']) except: await interaction.response.send_message("I can't find that xkcd comic, try another.") - + @nextcord.slash_command(name="iswanted", description="See if someone is on the FBI's most wanted list.") async def iswanted(self, interaction: Interaction, name: str = SlashOption(description="The name of the person you want to check", required=True)): """ @@ -68,7 +68,7 @@ async def iswanted(self, interaction: Interaction, name: str = SlashOption(descr await interaction.response.send_message(name + " might be wanted by the FBI:\n" + url) except: await interaction.response.send_message("No one with that name is currently wanted by the FBI") - + @nextcord.slash_command(name="eightball", description="Ask any yes/no question and get an answer.") async def eight_ball(self, interaction: Interaction, question: str = SlashOption(description="The question you want to ask", required=True)): """ @@ -109,7 +109,7 @@ async def randomfact(self, interaction: Interaction): color=config["error"] ) await interaction.response.send_message(embed=embed) - + @nextcord.slash_command(name="inspire", description="Get an inspirational poster courtesy of https://inspirobot.me/") async def inspire(self, interaction: Interaction): """ @@ -117,7 +117,7 @@ async def inspire(self, interaction: Interaction): """ quote = inspirobot.generate() await interaction.response.send_message(quote.url) - + @nextcord.slash_command(name="wisdom", description="Get some wisdom courtesy of https://inspirobot.me/") async def wisdom(self, interaction: Interaction): """ @@ -127,7 +127,7 @@ async def wisdom(self, interaction: Interaction): res = "" for quote in flow: res += quote.text + "\n" - + await interaction.response.send_message(res) @nextcord.slash_command(name="advice", description="Get some advice.") @@ -138,5 +138,6 @@ async def advice(self, interaction: Interaction): r = requests.get("https://api.adviceslip.com/advice") await interaction.response.send_message(r.json()['slip']['advice']) + def setup(bot): - bot.add_cog(Fun(bot)) \ No newline at end of file + bot.add_cog(Fun(bot)) diff --git a/cogs/general.py b/cogs/general.py index 7a093b4..5cff6a0 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -15,6 +15,7 @@ with open("config.yaml") as file: config = yaml.load(file, Loader=yaml.FullLoader) + class general(commands.Cog, name="general"): def __init__(self, bot): self.bot = bot @@ -110,7 +111,7 @@ async def ping(self, interaction: Interaction): embed.set_footer( text=f"Pong request by {interaction.user}" ) - await interaction.response.send_message(embed=embed) + await interaction.response.send_message(embed=embed) @nextcord.slash_command(name="invite", description="Get the invite link of the bot to be able to invite it to another server.") async def invite(self, interaction: Interaction): @@ -119,7 +120,6 @@ async def invite(self, interaction: Interaction): """ await interaction.response.send_message(f"Invite me by clicking here: https://discordapp.com/oauth2/authorize?&client_id={config['application_id']}&scope=bot&permissions=8") - @nextcord.slash_command(name="tldrchannel", description="Get a TLDR of X number of past messages on the channel.") async def tldrchannel(self, interaction: Interaction, number: int = SlashOption(description="The number of past messages to summarize", required=True, min_value=5, max_value=200)): """ @@ -132,7 +132,7 @@ async def tldrchannel(self, interaction: Interaction, number: int = SlashOption( embed = summarizer.getSummaryText(config, text) await interaction.response.send_message(embed=embed) - + @nextcord.slash_command(name="tldr", description="Get a TLDR of a web page.") async def tldr(self, interaction: Interaction, url: str = SlashOption(description="The URL of the web page to summarize", required=True)): """ diff --git a/cogs/help.py b/cogs/help.py index 9019706..6e34e83 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -11,6 +11,7 @@ with open("config.yaml") as file: config = yaml.load(file, Loader=yaml.FullLoader) + class Help(commands.Cog, name="help"): def __init__(self, bot): self.bot = bot diff --git a/cogs/quotes.py b/cogs/quotes.py index d9380b9..222fbfc 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -12,7 +12,7 @@ with open("config.yaml") as file: config = yaml.load(file, Loader=yaml.FullLoader) -# Here we name the cog and create a new class for the cog. + class Quotes(commands.Cog, name="quotes"): def __init__(self, bot): self.bot = bot @@ -36,7 +36,7 @@ async def newquote(self, interaction: Interaction, quote: str = SlashOption(desc newquote = await quoteClass.newquote(quote) await interaction.response.send_message("Quote submitted! Quote: " + newquote) - -# And then we finally add the cog to the bot so that it can load, unload, reload and use it's content. + + def setup(bot): bot.add_cog(Quotes(bot)) diff --git a/cogs/ratemyprofessor.py b/cogs/ratemyprofessor.py index fbefaee..c10721e 100644 --- a/cogs/ratemyprofessor.py +++ b/cogs/ratemyprofessor.py @@ -13,6 +13,7 @@ with open("config.yaml") as file: config = yaml.load(file, Loader=yaml.FullLoader) + class RateMyProfessor(commands.Cog, name="rate my professor"): def __init__(self, bot): self.bot = bot @@ -33,16 +34,20 @@ async def rmp(self, interaction: nextcord.Interaction, professorname: str = Slas EMU = ratemyprofessor.get_school_by_name("Eastern Michigan University") prof = ratemyprofessor.get_professor_by_school_and_name(EMU, professorname) - ratingsBest = sorted([rating for rating in prof.get_ratings() if rating.comment], key=lambda rating: (rating.rating, rating.date)) + ratingsBest = sorted([rating for rating in prof.get_ratings() if rating.comment], + key=lambda rating: (rating.rating, rating.date)) bestRating = ratingsBest[-1] - ratingsWorst = sorted([rating for rating in prof.get_ratings() if rating.comment], key=lambda rating: (-rating.rating, rating.date)) + ratingsWorst = sorted([rating for rating in prof.get_ratings() if rating.comment], + key=lambda rating: (-rating.rating, rating.date)) worstRating = ratingsWorst[-1] profEmbed = self.buildProfEmbed(prof) - bestembed = self.buildRatingEmbed(nextcord.Embed(title=f"Best Rating for {prof.name}", color=config["success"]), bestRating) - worstembed = self.buildRatingEmbed(nextcord.Embed(title=f"Worst Rating for {prof.name}",color=config["success"]), worstRating) - + bestembed = self.buildRatingEmbed(nextcord.Embed(title=f"Best Rating for {prof.name}", color=config["success"]), + bestRating) + worstembed = self.buildRatingEmbed(nextcord.Embed(title=f"Worst Rating for {prof.name}", color=config["success"]), + worstRating) + await interaction.response.send_message(embed=profEmbed) await interaction.followup.send(embed=bestembed) await interaction.followup.send(embed=worstembed) @@ -93,7 +98,7 @@ def buildRatingEmbed(self, embed, rating): ) return embed - + def buildProfEmbed(self, prof): embed = nextcord.Embed( title=prof, @@ -102,7 +107,7 @@ def buildProfEmbed(self, prof): if prof.name in self.profImages: embed.set_image(url=self.profImages[prof.name]) - + embed.add_field( name="Department", value=prof.department, @@ -141,5 +146,6 @@ def buildProfEmbed(self, prof): return embed + def setup(bot): bot.add_cog(RateMyProfessor(bot)) diff --git a/cogs/template.py b/cogs/template.py index 4276dc1..e28ec36 100644 --- a/cogs/template.py +++ b/cogs/template.py @@ -1,29 +1,29 @@ -# import os -# import sys -# import yaml -# import nextcord -# from typing import Optional -# from nextcord.ext import commands -# from nextcord import Interaction, SlashOption, ChannelType -# from nextcord.abc import GuildChannel - - -# with open("config.yaml") as file: -# config = yaml.load(file, Loader=yaml.FullLoader) - -# # Here we name the cog and create a new class for the cog. -# class Template(commands.Cog, name="template"): -# def __init__(self, bot): -# self.bot = bot - - # # Here you can just add your own commands, you'll always need to provide "self" as first parameter. - # @nextcord.slash_command(name="template", description="This is a testing command that does nothing.") - # async def testcommand(self, context): - # """ - # [No Arguments] This is a testing command that does nothing. - # """ - # await context.send("I'll tell you when you're older. Move along now, child.") - -# # And then we finally add the cog to the bot so that it can load, unload, reload and use it's content. -# def setup(bot): -# bot.add_cog(Template(bot)) +# import os +# import sys +# import yaml +# import nextcord +# from typing import Optional +# from nextcord.ext import commands +# from nextcord import Interaction, SlashOption, ChannelType +# from nextcord.abc import GuildChannel +# +# +# with open("config.yaml") as file: +# config = yaml.load(file, Loader=yaml.FullLoader) +# +# +# class Template(commands.Cog, name="template"): # Here we name the cog and create a new class for the cog. +# def __init__(self, bot): +# self.bot = bot +# +# # Here you can just add your own commands, you'll always need to provide "self" as first parameter. +# @nextcord.slash_command(name="template", description="This is a testing command that does nothing.") +# async def testcommand(self, context): +# """ +# [No Arguments] This is a testing command that does nothing. +# """ +# await context.send("I'll tell you when you're older. Move along now, child.") +# +# +# def setup(bot): # And then we finally add the cog to the bot so that it can load, unload, reload and use it's content. +# bot.add_cog(Template(bot)) diff --git a/noncommands/auto_code_block.py b/noncommands/auto_code_block.py index a9a8e9d..fb25c38 100644 --- a/noncommands/auto_code_block.py +++ b/noncommands/auto_code_block.py @@ -1,6 +1,7 @@ import re import asyncio + class AutoCodeBlock: def __init__(self, bot): self.bot = bot @@ -9,7 +10,7 @@ async def check_message(self, message): message_text = message.content if self.looks_like_unformatted_code(message_text): probable_code = message_text.replace("```", "") - + reply = "It seems like that message might contain some unformatted code, I did my best to format it for you. If this is unwanted, react to this message within 2 minutes." reply += "\n```java\n" reply += probable_code @@ -29,10 +30,6 @@ def check(reaction, user): except asyncio.exceptions.TimeoutError: await msg.clear_reactions() pass - + def looks_like_unformatted_code(self, text): return re.search('\{*.\}', text) and ("```" not in text or "```\n" in text) - - - - diff --git a/noncommands/quotes.py b/noncommands/quotes.py index 649baf3..caed79b 100644 --- a/noncommands/quotes.py +++ b/noncommands/quotes.py @@ -7,9 +7,10 @@ with open("config.yaml") as file: config = yaml.load(file, Loader=yaml.FullLoader) + class Quotes: def __init__(self, bot): - self.bot=bot + self.bot = bot async def dailyQuote(self): channel = self.bot.get_channel(707293854507991172) @@ -54,5 +55,5 @@ async def newquote(self, quote): mydb.commit() mycursor.close() mydb.close() - - return quote \ No newline at end of file + + return quote diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index 67c3e8c..4cb9cb7 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -4,7 +4,7 @@ import nltk import re import numpy as np -from nltk.corpus import stopwords +from nltk.corpus import stopwords from nltk.tokenize import word_tokenize from trafilatura import bare_extraction import trafilatura @@ -13,6 +13,7 @@ nltk.download('punkt') nltk.download('stopwords') + def scoreSent(sent, scoreMatrix, scoreCol): score = 0 for word in sent.split(" "): @@ -28,21 +29,22 @@ def filterStopwords(sent): return " ".join([w for w in word_tokens if w not in stop_words]) + def getSummarySpread(filePath, numSent): - + f = open(filePath, "r") text = f.read() text = " ".join(text.split()) for i in range(100): text = text.replace("[" + str(i) + "]", "") - + doc = nltk.tokenize.sent_tokenize(text) docFilt = [filterStopwords(s) for s in doc] vectorizer = CountVectorizer() bag_of_words = vectorizer.fit_transform(docFilt) - svd = TruncatedSVD(n_components = numSent) + svd = TruncatedSVD(n_components=numSent) lsa = svd.fit_transform(bag_of_words) col = ["topic" + str(i) for i in range(numSent)] @@ -53,7 +55,7 @@ def getSummarySpread(filePath, numSent): topic_encoded_df["docFilt"] = docFilt topic_encoded_df["doc"] = doc dictionary = vectorizer.get_feature_names_out() - encoding_matrix=pd.DataFrame(svd.components_,index=col,columns=dictionary).T + encoding_matrix = pd.DataFrame(svd.components_, index=col, columns=dictionary).T for i in range(numSent): encoding_matrix[absCol[i]] = np.abs(encoding_matrix[col[i]]) @@ -61,7 +63,6 @@ def getSummarySpread(filePath, numSent): for c in absCol: cl[c] = [] - for c in absCol: for s in doc: cl[c].append([s, scoreSent(s, encoding_matrix, c)]) @@ -70,13 +71,14 @@ def getSummarySpread(filePath, numSent): s = [d for d in sorted(cl[c], key=lambda x: x[1]) if d[0] not in [f[0] for f in chosen]][::-1] chosen.append(s[0]) + def getSummaryMono(text, numSent): text = " ".join(text.split()) for i in range(100): text = text.replace("[" + str(i) + "]", "") - + doc = nltk.tokenize.sent_tokenize(text) docFilt = [filterStopwords(s) for s in doc] @@ -84,7 +86,7 @@ def getSummaryMono(text, numSent): vectorizer = CountVectorizer() bag_of_words = vectorizer.fit_transform(docFilt) - svd = TruncatedSVD(n_components = 1) + svd = TruncatedSVD(n_components=1) lsa = svd.fit_transform(bag_of_words) col = ["topic1"] @@ -96,7 +98,7 @@ def getSummaryMono(text, numSent): topic_encoded_df["doc"] = doc dictionary = vectorizer.get_feature_names_out() - encoding_matrix=pd.DataFrame(svd.components_,index=col,columns=dictionary).T + encoding_matrix = pd.DataFrame(svd.components_, index=col, columns=dictionary).T for i in range(len(col)): encoding_matrix[absCol[i]] = np.abs(encoding_matrix[col[i]]) @@ -109,7 +111,7 @@ def getSummaryMono(text, numSent): for s in doc: cl[c].append([s, scoreSent(s, encoding_matrix, c)]) chosen = [] - + for i in range(numSent): for c in absCol: s = [d for d in sorted(cl[c], key=lambda x: x[1]) if d[0] not in [f[0] for f in chosen]][::-1] @@ -126,18 +128,19 @@ def getSummaryUrl(config, url): color=config["success"] ) embed.add_field( - name = "Title:", - value = article["title"], - inline = True + name="Title:", + value=article["title"], + inline=True ) embed.add_field( name="Summary:", value="\n".join(getSummaryMono(article["text"], numSent)), - inline = False + inline=False ) return embed + def getSummaryText(config, text): numSent = 5 embed = nextcord.Embed( @@ -146,7 +149,7 @@ def getSummaryText(config, text): embed.add_field( name="Summary:", value="\n".join(getSummaryMono(text, numSent)), - inline = False + inline=False ) - return embed \ No newline at end of file + return embed From 2b909f8d0ec945e092d4dfd55e6bfd26047bbf5e Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:20:10 -0500 Subject: [PATCH 11/38] =?UTF-8?q?chore:=20=F0=9F=A7=91=E2=80=8D?= =?UTF-8?q?=F0=9F=92=BB=20change=20editor=20cofig=20to=20reflect=20indenta?= =?UTF-8?q?tion=20in=20markdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 5b9fdad..de71f36 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,3 +8,6 @@ indent_size = 4 [*.yml] indent_size = 2 + +[*.md] +indent_size = 2 From ad613b29ce71880e987685378c241ab8a7af07f2 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:37:03 -0500 Subject: [PATCH 12/38] =?UTF-8?q?refactor:=20=F0=9F=94=A5=20remove=20unuse?= =?UTF-8?q?d=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 4 +-- cogs/channel.py | 1 - cogs/fun.py | 13 ++-------- cogs/general.py | 11 ++------ cogs/help.py | 54 ++++++++++++++++++--------------------- cogs/quotes.py | 7 +---- cogs/ratemyprofessor.py | 8 +----- noncommands/summarizer.py | 1 - 8 files changed, 32 insertions(+), 67 deletions(-) diff --git a/bot.py b/bot.py index 3ae89cb..cfbf72a 100644 --- a/bot.py +++ b/bot.py @@ -1,12 +1,10 @@ import os import platform -import random -import sys import nextcord import yaml from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.triggers.cron import CronTrigger -from nextcord.ext import commands, tasks +from nextcord.ext import commands from nextcord.ext.commands import Bot from noncommands import auto_code_block, quotes diff --git a/cogs/channel.py b/cogs/channel.py index 1e602f8..2ff617f 100644 --- a/cogs/channel.py +++ b/cogs/channel.py @@ -1,6 +1,5 @@ import asyncio from collections import OrderedDict -from pathlib import Path from string import ascii_lowercase import sys from typing import Coroutine, TypedDict, Generator diff --git a/cogs/fun.py b/cogs/fun.py index e3829d1..c073976 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -1,22 +1,13 @@ -import asyncio -import os + import random -import sys import aiohttp -import aiofiles -import hashlib import yaml import requests -import uuid import inspirobot -import uwuify -import json import nextcord -from typing import Optional from nextcord.ext import commands -from nextcord import Interaction, SlashOption, ChannelType -from nextcord.abc import GuildChannel +from nextcord import Interaction, SlashOption with open("config.yaml") as file: diff --git a/cogs/general.py b/cogs/general.py index 5cff6a0..5349610 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -1,16 +1,9 @@ -import os import platform -import sys -import json import yaml -import random -from nextcord.ext import commands -from noncommands import summarizer, quotes +from noncommands import summarizer import nextcord -from typing import Optional from nextcord.ext import commands -from nextcord import Interaction, SlashOption, ChannelType -from nextcord.abc import GuildChannel +from nextcord import Interaction, SlashOption with open("config.yaml") as file: config = yaml.load(file, Loader=yaml.FullLoader) diff --git a/cogs/help.py b/cogs/help.py index 6e34e83..96121b6 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -1,29 +1,25 @@ -import os -import sys -import yaml -import nextcord -from typing import Optional -from nextcord.ext import commands -from nextcord import Interaction, SlashOption, ChannelType -from nextcord.abc import GuildChannel - - -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) - - -class Help(commands.Cog, name="help"): - def __init__(self, bot): - self.bot = bot - - @nextcord.slash_command(name="help", description="How do I find out what all the commands are?") - async def help(self, interaction: Interaction): - """ - How do I find out what all the commands are? - """ - - await interaction.response.send_message("This bot uses slash commands! Type a `/` into the chat, click my icon, and you should see all the commands I can take!") - - -def setup(bot): - bot.add_cog(Help(bot)) +import yaml +import nextcord +from nextcord.ext import commands +from nextcord import Interaction + + +with open("config.yaml") as file: + config = yaml.load(file, Loader=yaml.FullLoader) + + +class Help(commands.Cog, name="help"): + def __init__(self, bot): + self.bot = bot + + @nextcord.slash_command(name="help", description="How do I find out what all the commands are?") + async def help(self, interaction: Interaction): + """ + How do I find out what all the commands are? + """ + + await interaction.response.send_message("This bot uses slash commands! Type a `/` into the chat, click my icon, and you should see all the commands I can take!") + + +def setup(bot): + bot.add_cog(Help(bot)) diff --git a/cogs/quotes.py b/cogs/quotes.py index 222fbfc..6f4c4a2 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -1,13 +1,8 @@ -import os -import sys import yaml -from nextcord.ext import commands from noncommands import quotes import nextcord -from typing import Optional from nextcord.ext import commands -from nextcord import Interaction, SlashOption, ChannelType -from nextcord.abc import GuildChannel +from nextcord import Interaction, SlashOption with open("config.yaml") as file: config = yaml.load(file, Loader=yaml.FullLoader) diff --git a/cogs/ratemyprofessor.py b/cogs/ratemyprofessor.py index c10721e..9c30822 100644 --- a/cogs/ratemyprofessor.py +++ b/cogs/ratemyprofessor.py @@ -1,13 +1,7 @@ -import os -import sys import yaml -from nextcord.ext import commands -import ratemyprofessor import nextcord -from typing import Optional from nextcord.ext import commands -from nextcord import Interaction, SlashOption, ChannelType -from nextcord.abc import GuildChannel +from nextcord import SlashOption with open("config.yaml") as file: diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index 4cb9cb7..fe90f99 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -2,7 +2,6 @@ from sklearn.decomposition import TruncatedSVD import pandas as pd import nltk -import re import numpy as np from nltk.corpus import stopwords from nltk.tokenize import word_tokenize From 31e142f268786ab2444c419277f6530f54d04e62 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:44:38 -0500 Subject: [PATCH 13/38] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20use=20si?= =?UTF-8?q?ngal=20declaration=20for=20gitignoring=20=5F=5Fpycache=5F=5F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 4a51de0..e6a44ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Byte-compiled / optimized / DLL files -__pycache__/ +*/__pycache__/ *.py[cod] *$py.class @@ -12,9 +12,7 @@ build/ develop-eggs/ dist/ downloads/ -cogs/__pycache__ .vscode/ -noncommands/__pycache__ eggs/ .eggs/ lib/ @@ -144,14 +142,6 @@ cython_debug/ .idea/* *.pyc *.pyc -/cogs/__pycache__/fun.cpython-37.pyc -/cogs/__pycache__/general.cpython-37.pyc -/cogs/__pycache__/help.cpython-37.pyc -/cogs/__pycache__/moderation.cpython-37.pyc -/cogs/__pycache__/owner.cpython-37.pyc -/cogs/__pycache__/template.cpython-37.pyc -/noncommands/__pycache__/imchecker.cpython-37.pyc -/noncommands/__pycache__/reminderLoop.cpython-37.pyc newperson.png *.pyc */*.pyc From ec1bfbeaa26bdabbd9368011a239032132c09438 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:51:54 -0500 Subject: [PATCH 14/38] =?UTF-8?q?ci:=20=F0=9F=92=9A=20disable=20pylint=20l?= =?UTF-8?q?ine=20length=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index ede52ff..e3541b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,11 @@ ignore = [".venv"] recursive = true +[tool.pylint.messages_control] +disable = [ + "line-too-long", # disable because we use autopep8 +] + [tool.autopep8] max_line_length = 120 recursive = true From a4f7e018b7a196768fa515566edfd4e3994b0ce3 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:59:14 -0500 Subject: [PATCH 15/38] =?UTF-8?q?fix:=20=F0=9F=9A=A8=20reorder=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/channel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/channel.py b/cogs/channel.py index 2ff617f..c980505 100644 --- a/cogs/channel.py +++ b/cogs/channel.py @@ -4,11 +4,11 @@ import sys from typing import Coroutine, TypedDict, Generator import json +import re import yaml from nextcord.ext.commands import Cog from nextcord.ext.application_checks import has_permissions from nextcord.utils import find -import re import nextcord from nextcord import Interaction, SlashOption, PermissionOverwrite, Permissions, Colour, Embed, Attachment From 567404e7e96df99578456bde7f7a9f54b210e9b6 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 18:59:40 -0500 Subject: [PATCH 16/38] =?UTF-8?q?refactor:=20=F0=9F=9A=A8=20rename=20varia?= =?UTF-8?q?ble?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/quotes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cogs/quotes.py b/cogs/quotes.py index 6f4c4a2..dccc02b 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -18,8 +18,8 @@ async def quote(self, interaction: Interaction, keyword: str = SlashOption(descr """ [(Optional) Search text] Searches CS quotes by keyword, or search one at random. """ - quoteClass = quotes.Quotes(self.bot) - random_quote = await quoteClass.quote(keyword) + quote_class = quotes.Quotes(self.bot) + random_quote = await quote_class.quote(keyword) await interaction.response.send_message(random_quote) @nextcord.slash_command(name="newquote", description="Creates a new quote to be put into the list of CS quotes.") @@ -27,8 +27,8 @@ async def newquote(self, interaction: Interaction, quote: str = SlashOption(desc """ [(Required) Quote] Creates a new quote to be put into the list of CS quotes. """ - quoteClass = quotes.Quotes(self.bot) - newquote = await quoteClass.newquote(quote) + quote_class = quotes.Quotes(self.bot) + newquote = await quote_class.newquote(quote) await interaction.response.send_message("Quote submitted! Quote: " + newquote) From 003c338140e82d5ef7054e0abe7a75a512c47f4a Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 19:02:51 -0500 Subject: [PATCH 17/38] =?UTF-8?q?fix:=20=F0=9F=90=9B=20use=20new=20name=20?= =?UTF-8?q?for=20scikit-learn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- noncommands/summarizer.py | 4 ++-- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index fe90f99..57fe3dd 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -1,5 +1,5 @@ -from sklearn.feature_extraction.text import CountVectorizer -from sklearn.decomposition import TruncatedSVD +from scikit-learn.feature_extraction.text import CountVectorizer +from scikit-learn.decomposition import TruncatedSVD import pandas as pd import nltk import numpy as np diff --git a/requirements.txt b/requirements.txt index 9b0fa65..afbecd1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ nextcord pyyaml aiofiles schedule -sklearn +scikit-learn pandas nltk numpy From 710ea391dd0ec447562f5c7159f2fa553614e438 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 19:33:01 -0500 Subject: [PATCH 18/38] =?UTF-8?q?build:=20=F0=9F=94=A5=20remove=20unused?= =?UTF-8?q?=20dependencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index afbecd1..6226c30 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,8 +2,6 @@ aiohttp apscheduler asyncio nextcord -pyyaml -aiofiles schedule scikit-learn pandas @@ -11,7 +9,6 @@ nltk numpy trafilatura inspiro -uwuify RateMyProfessorAPI mysql-connector pylint From 366aa3921705163aadf0c17292ab7056c34c9e2f Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 29 Dec 2022 22:39:44 -0500 Subject: [PATCH 19/38] =?UTF-8?q?feat:=20=E2=9C=A8=20add=20=5F=5Finit=5F?= =?UTF-8?q?=5F=20files=20change=20config=20to=20toml=20and=20move=20consta?= =?UTF-8?q?nts=20to=20constant=20file=20and=20fix=20some=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- README.md | 25 +++++++++-------------- __init__.py | 0 bot.py | 8 +++----- cogs/__init__.py | 0 cogs/channel.py | 5 ----- cogs/fun.py | 10 ++++------ cogs/general.py | 12 +++++------ cogs/help.py | 5 ----- cogs/quotes.py | 6 +----- cogs/ratemyprofessor.py | 12 +++++------ cogs/template.py | 5 +---- config template.yaml | 11 ---------- config_template.toml | 12 +++++++++++ constants.py | 42 +++++++++++++++++++++++++++++++++++++++ noncommands/__init__.py | 0 noncommands/quotes.py | 29 ++++++++++++++------------- noncommands/summarizer.py | 11 ++++++---- 18 files changed, 105 insertions(+), 90 deletions(-) create mode 100644 __init__.py create mode 100644 cogs/__init__.py delete mode 100644 config template.yaml create mode 100644 config_template.toml create mode 100644 constants.py create mode 100644 noncommands/__init__.py diff --git a/.gitignore b/.gitignore index e6a44ae..d2993d5 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ share/python-wheels/ *.egg-info/ .installed.cfg *.egg -config.yaml +config.toml MANIFEST # PyInstaller diff --git a/README.md b/README.md index fafd4db..dccc849 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ You should see something similar to this result if you are using Windows Command Command Line Output -You can set up a python virtual environment that uses python 3.9 by running this command on windows +You can set up a python virtual environment by running this command on windows ```pwsh -&"C:\Program Files\Python39\python.exe" -m venv .venv +python -m venv .venv ``` ### 2. Getting a Discord Bot @@ -86,25 +86,18 @@ Click the Administrator Box, so it looks as shown: ### 4. Config File -Now go to your IDE or Text Editor, and make a copy of `config template.yaml`. Save the copy as `config.yaml`. This will be the bots config file, and is important to running on discord. +Now go to your IDE or Text Editor, and make a copy of `config_template.toml`. Save the copy as `config.toml`. This will be the bots config file, and is important to running on discord. DO NOT WRITE ON THE TEMPLATE -```yaml -token: "BOT_TOKEN" -application_id: "APPLICATION_ID" -owners: - - OWNER_ID -blacklist: - - 000000000000000000 -main_color: 0xD75BF4 -error: 0xE02B2B -success: 0x42F56C -warning: 0xF59E42 -info: 0x4299F5 +```toml +token = "BOT_TOKEN" +application_id = "APPLICATION_ID" +owners = ["OWNER_ID"] +blacklist = [] ``` -On the `config.yaml` file, you will be changing four lines: +On the `config.toml` file, you will be changing four lines: - `token` - `application_id` diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot.py b/bot.py index cfbf72a..54cb9ce 100644 --- a/bot.py +++ b/bot.py @@ -1,7 +1,6 @@ import os import platform import nextcord -import yaml from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.triggers.cron import CronTrigger from nextcord.ext import commands @@ -9,9 +8,8 @@ from noncommands import auto_code_block, quotes +from constants import ERROR_COLOR, config -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) intents = nextcord.Intents.default().all() @@ -94,7 +92,7 @@ async def on_command_error(context, error): embed = nextcord.Embed( title="Hey, please slow down!", description=f"You can use this command again in {f'{round(hours)} hours' if round(hours) > 0 else ''} {f'{round(minutes)} minutes' if round(minutes) > 0 else ''} {f'{round(seconds)} seconds' if round(seconds) > 0 else ''}.", - color=config["error"] + color=ERROR_COLOR ) await context.send(embed=embed) elif isinstance(error, commands.MissingPermissions): @@ -102,7 +100,7 @@ async def on_command_error(context, error): title="Error!", description="You are missing the permission `" + ", ".join( error.missing_perms) + "` to execute this command!", - color=config["error"] + color=ERROR_COLOR ) await context.send(embed=embed) raise error diff --git a/cogs/__init__.py b/cogs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cogs/channel.py b/cogs/channel.py index c980505..204bdff 100644 --- a/cogs/channel.py +++ b/cogs/channel.py @@ -5,7 +5,6 @@ from typing import Coroutine, TypedDict, Generator import json import re -import yaml from nextcord.ext.commands import Cog from nextcord.ext.application_checks import has_permissions from nextcord.utils import find @@ -13,10 +12,6 @@ from nextcord import Interaction, SlashOption, PermissionOverwrite, Permissions, Colour, Embed, Attachment -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) - - # classes we do not want to create channels for course_blacklist = ['106', '146', '388'] diff --git a/cogs/fun.py b/cogs/fun.py index c073976..1f2e6e5 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -1,7 +1,6 @@ import random import aiohttp -import yaml import requests import inspirobot @@ -10,8 +9,7 @@ from nextcord import Interaction, SlashOption -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) +from ..constants import ERROR_COLOR, MAIN_COLOR, SUCCESS_COLOR class Fun(commands.Cog, name="fun"): @@ -73,7 +71,7 @@ async def eight_ball(self, interaction: Interaction, question: str = SlashOption embed = nextcord.Embed( title=f"**My Answer to '{question}':**", description=f"{answers[random.randint(0, len(answers) - 1)]}", - color=config["success"] + color=SUCCESS_COLOR ) embed.set_footer( text=f"Question asked by: {interaction.user}" @@ -91,13 +89,13 @@ async def randomfact(self, interaction: Interaction): async with session.get("https://uselessfacts.jsph.pl/random.json?language=en") as request: if request.status == 200: data = await request.json() - embed = nextcord.Embed(description=data["text"], color=config["main_color"]) + embed = nextcord.Embed(description=data["text"], color=MAIN_COLOR) await interaction.response.send_message(embed=embed) else: embed = nextcord.Embed( title="Error!", description="There is something wrong with the API, please try again later", - color=config["error"] + color=ERROR_COLOR ) await interaction.response.send_message(embed=embed) diff --git a/cogs/general.py b/cogs/general.py index 5349610..f404cc6 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -1,12 +1,10 @@ import platform -import yaml -from noncommands import summarizer +from ..noncommands import summarizer import nextcord from nextcord.ext import commands from nextcord import Interaction, SlashOption -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) +from ..constants import config, SUCCESS_COLOR class general(commands.Cog, name="general"): @@ -20,7 +18,7 @@ async def info(self, interaction: Interaction): """ embed = nextcord.Embed( description="The server's most helpful member.", - color=config["success"] + color=SUCCESS_COLOR ) embed.set_author( name="Bot Information" @@ -60,7 +58,7 @@ async def serverinfo(self, interaction: Interaction): embed = nextcord.Embed( title="**Server Name:**", description=f"{server}", - color=config["success"] + color=SUCCESS_COLOR ) if server.icon != None: @@ -94,7 +92,7 @@ async def ping(self, interaction: Interaction): [No Arguments] Check if the bot is alive. """ embed = nextcord.Embed( - color=config["success"] + color=SUCCESS_COLOR ) embed.add_field( name="Pong!", diff --git a/cogs/help.py b/cogs/help.py index 96121b6..b5c1180 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -1,13 +1,8 @@ -import yaml import nextcord from nextcord.ext import commands from nextcord import Interaction -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) - - class Help(commands.Cog, name="help"): def __init__(self, bot): self.bot = bot diff --git a/cogs/quotes.py b/cogs/quotes.py index dccc02b..48f7a9f 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -1,12 +1,8 @@ -import yaml -from noncommands import quotes +from ..noncommands import quotes import nextcord from nextcord.ext import commands from nextcord import Interaction, SlashOption -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) - class Quotes(commands.Cog, name="quotes"): def __init__(self, bot): diff --git a/cogs/ratemyprofessor.py b/cogs/ratemyprofessor.py index 9c30822..fccf0fe 100644 --- a/cogs/ratemyprofessor.py +++ b/cogs/ratemyprofessor.py @@ -1,11 +1,9 @@ -import yaml +import ratemyprofessor import nextcord from nextcord.ext import commands from nextcord import SlashOption - -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) +from ..constants import SUCCESS_COLOR class RateMyProfessor(commands.Cog, name="rate my professor"): @@ -37,9 +35,9 @@ async def rmp(self, interaction: nextcord.Interaction, professorname: str = Slas worstRating = ratingsWorst[-1] profEmbed = self.buildProfEmbed(prof) - bestembed = self.buildRatingEmbed(nextcord.Embed(title=f"Best Rating for {prof.name}", color=config["success"]), + bestembed = self.buildRatingEmbed(nextcord.Embed(title=f"Best Rating for {prof.name}", color=SUCCESS_COLOR), bestRating) - worstembed = self.buildRatingEmbed(nextcord.Embed(title=f"Worst Rating for {prof.name}", color=config["success"]), + worstembed = self.buildRatingEmbed(nextcord.Embed(title=f"Worst Rating for {prof.name}", color=SUCCESS_COLOR), worstRating) await interaction.response.send_message(embed=profEmbed) @@ -96,7 +94,7 @@ def buildRatingEmbed(self, embed, rating): def buildProfEmbed(self, prof): embed = nextcord.Embed( title=prof, - color=config["success"] + color=SUCCESS_COLOR ) if prof.name in self.profImages: diff --git a/cogs/template.py b/cogs/template.py index e28ec36..a7e2af6 100644 --- a/cogs/template.py +++ b/cogs/template.py @@ -1,15 +1,12 @@ # import os # import sys -# import yaml # import nextcord # from typing import Optional # from nextcord.ext import commands # from nextcord import Interaction, SlashOption, ChannelType # from nextcord.abc import GuildChannel # -# -# with open("config.yaml") as file: -# config = yaml.load(file, Loader=yaml.FullLoader) +# from ..constants import config # # # class Template(commands.Cog, name="template"): # Here we name the cog and create a new class for the cog. diff --git a/config template.yaml b/config template.yaml deleted file mode 100644 index 0822fcb..0000000 --- a/config template.yaml +++ /dev/null @@ -1,11 +0,0 @@ -token: "BOT_TOKEN" -application_id: "APPLICATION_ID" -owners: - - OWNER_ID -blacklist: - - 000000000000000000 -main_color: 0xD75BF4 -error: 0xE02B2B -success: 0x42F56C -warning: 0xF59E42 -info: 0x4299F5 diff --git a/config_template.toml b/config_template.toml new file mode 100644 index 0000000..80c4aea --- /dev/null +++ b/config_template.toml @@ -0,0 +1,12 @@ +# Fill in the your bot's token application ID and owner ID +token = "BOT_TOKEN" +application_id = "APPLICATION_ID" +owners = ["OWNER_ID"] # TODO are we using this? +blacklist = [] + +# Uncomment the following lines to enable the database +# [db] +# host = "DATABASE_HOSTENAME" +# user = "DATABASE_USERNAME" +# password = "DATABASE_PASSWORD" +# database = "DATABASE_NAME" diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..848d8e4 --- /dev/null +++ b/constants.py @@ -0,0 +1,42 @@ +""" +Various constants used throughout the bot. +""" + +from typing import Optional, TypedDict +import tomllib +from nextcord import Color + +MAIN_COLOR = Color(0xD75BF4) +ERROR_COLOR = Color(0xE02B2B) +SUCCESS_COLOR = Color(0x42F56C) +WARNING_COLOR = Color(0xF59E42) +INFO_COLOR = Color(0x4299F5) + + +class DBConfig(TypedDict): + """ + The database config from the config file. + """ + + host: str + user: str + password: str + database: str + + +class Config(TypedDict): + """ + The config file. + """ + + token: str + application_id: str + owners: list[int] + blacklist: list[int] + db: Optional[DBConfig] + + +config: Config + +with open("config.toml", "rb") as f: + config = tomllib.load(f) diff --git a/noncommands/__init__.py b/noncommands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/noncommands/quotes.py b/noncommands/quotes.py index caed79b..e6bf719 100644 --- a/noncommands/quotes.py +++ b/noncommands/quotes.py @@ -1,11 +1,6 @@ -import json -import random -import yaml -import os import mysql.connector -with open("config.yaml") as file: - config = yaml.load(file, Loader=yaml.FullLoader) +from ..constants import config class Quotes: @@ -18,11 +13,14 @@ async def dailyQuote(self): await channel.send("Daily Quote:\n" + dailyquote) async def quote(self, keywords): + if config["db"] is None: + return "Database not configured" + mydb = mysql.connector.connect( - host=config["dbhost"], - user=config["dbuser"], - password=config["dbpassword"], - database=config["databasename"], + host=config["db"]["host"], + user=config["db"]["user"], + password=config["db"]["password"], + database=config["db"]["database"], autocommit=True, use_unicode=True ) @@ -40,11 +38,14 @@ async def quote(self, keywords): return quote[0] async def newquote(self, quote): + if config["db"] is None: + return "Database not configured" + mydb = mysql.connector.connect( - host=config["dbhost"], - user=config["dbuser"], - password=config["dbpassword"], - database=config["databasename"], + host=config["db"]["host"], + user=config["db"]["user"], + password=config["db"]["password"], + database=config["db"]["database"], autocommit=True, use_unicode=True ) diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index 57fe3dd..f4cdcc2 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -1,5 +1,5 @@ -from scikit-learn.feature_extraction.text import CountVectorizer -from scikit-learn.decomposition import TruncatedSVD +from sklearn.feature_extraction.text import CountVectorizer +from sklearn.decomposition import TruncatedSVD import pandas as pd import nltk import numpy as np @@ -9,6 +9,9 @@ import trafilatura import nextcord + +from ..constants import SUCCESS_COLOR + nltk.download('punkt') nltk.download('stopwords') @@ -124,7 +127,7 @@ def getSummaryUrl(config, url): downloaded = trafilatura.fetch_url(url) article = bare_extraction(downloaded) embed = nextcord.Embed( - color=config["success"] + color=SUCCESS_COLOR ) embed.add_field( name="Title:", @@ -143,7 +146,7 @@ def getSummaryUrl(config, url): def getSummaryText(config, text): numSent = 5 embed = nextcord.Embed( - color=config["success"] + color=SUCCESS_COLOR ) embed.add_field( name="Summary:", From 2cefdc13eb853da12055262ebcefa27b78e5c827 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:11:53 -0500 Subject: [PATCH 20/38] =?UTF-8?q?fix:=20=F0=9F=90=9B=20fix=20relitive=20im?= =?UTF-8?q?port=20paths?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __init__.py | 0 cogs/fun.py | 2 +- cogs/general.py | 4 ++-- cogs/quotes.py | 2 +- cogs/ratemyprofessor.py | 2 +- cogs/template.py | 2 +- noncommands/quotes.py | 2 +- noncommands/summarizer.py | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) delete mode 100644 __init__.py diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/cogs/fun.py b/cogs/fun.py index 1f2e6e5..6b0e29b 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -9,7 +9,7 @@ from nextcord import Interaction, SlashOption -from ..constants import ERROR_COLOR, MAIN_COLOR, SUCCESS_COLOR +from constants import ERROR_COLOR, MAIN_COLOR, SUCCESS_COLOR class Fun(commands.Cog, name="fun"): diff --git a/cogs/general.py b/cogs/general.py index f404cc6..61316b3 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -1,10 +1,10 @@ import platform -from ..noncommands import summarizer +from noncommands import summarizer import nextcord from nextcord.ext import commands from nextcord import Interaction, SlashOption -from ..constants import config, SUCCESS_COLOR +from constants import config, SUCCESS_COLOR class general(commands.Cog, name="general"): diff --git a/cogs/quotes.py b/cogs/quotes.py index 48f7a9f..c3305ee 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -1,4 +1,4 @@ -from ..noncommands import quotes +from noncommands import quotes import nextcord from nextcord.ext import commands from nextcord import Interaction, SlashOption diff --git a/cogs/ratemyprofessor.py b/cogs/ratemyprofessor.py index fccf0fe..8a2912a 100644 --- a/cogs/ratemyprofessor.py +++ b/cogs/ratemyprofessor.py @@ -3,7 +3,7 @@ from nextcord.ext import commands from nextcord import SlashOption -from ..constants import SUCCESS_COLOR +from constants import SUCCESS_COLOR class RateMyProfessor(commands.Cog, name="rate my professor"): diff --git a/cogs/template.py b/cogs/template.py index a7e2af6..85d0a86 100644 --- a/cogs/template.py +++ b/cogs/template.py @@ -6,7 +6,7 @@ # from nextcord import Interaction, SlashOption, ChannelType # from nextcord.abc import GuildChannel # -# from ..constants import config +# from constants import config # # # class Template(commands.Cog, name="template"): # Here we name the cog and create a new class for the cog. diff --git a/noncommands/quotes.py b/noncommands/quotes.py index e6bf719..0687058 100644 --- a/noncommands/quotes.py +++ b/noncommands/quotes.py @@ -1,6 +1,6 @@ import mysql.connector -from ..constants import config +from constants import config class Quotes: diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index f4cdcc2..f3d545d 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -10,7 +10,7 @@ import nextcord -from ..constants import SUCCESS_COLOR +from constants import SUCCESS_COLOR nltk.download('punkt') nltk.download('stopwords') From a241e3ed73f4ecaf030e42af66a3272deab55636 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:12:31 -0500 Subject: [PATCH 21/38] =?UTF-8?q?fix:=20=F0=9F=90=9B=20ignore=20`=5F`=20fi?= =?UTF-8?q?les=20in=20cogs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 54cb9ce..570f823 100644 --- a/bot.py +++ b/bot.py @@ -38,7 +38,7 @@ async def on_ready(): if __name__ == "__main__": for file in os.listdir("./cogs"): - if file.endswith(".py"): + if file.endswith(".py") and not file.startswith("_"): extension = file[:-3] try: bot.load_extension(f"cogs.{extension}") From 3679616dc77a8f1c54f12fa90c6a5a82fd72beff Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:32:15 -0500 Subject: [PATCH 22/38] =?UTF-8?q?feat:=20=E2=9C=A8=20improve=20code=20rege?= =?UTF-8?q?x?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no longer messes with messages that contain triple backtick, now can see multi-line codeblocks --- noncommands/auto_code_block.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/noncommands/auto_code_block.py b/noncommands/auto_code_block.py index fb25c38..aa3a51f 100644 --- a/noncommands/auto_code_block.py +++ b/noncommands/auto_code_block.py @@ -1,6 +1,8 @@ import re import asyncio +CODE_REGEX = re.compile(r"{.*;.*}", re.DOTALL) + class AutoCodeBlock: def __init__(self, bot): @@ -9,11 +11,9 @@ def __init__(self, bot): async def check_message(self, message): message_text = message.content if self.looks_like_unformatted_code(message_text): - probable_code = message_text.replace("```", "") - reply = "It seems like that message might contain some unformatted code, I did my best to format it for you. If this is unwanted, react to this message within 2 minutes." reply += "\n```java\n" - reply += probable_code + reply += message_text reply += "\n```\n" reply += "(If you are curious how to do this, check out https://www.codegrepper.com/code-examples/whatever/discord+syntax+highlighting)" reply += f'\nOriginal Message sent by: {message.author.mention}' @@ -32,4 +32,4 @@ def check(reaction, user): pass def looks_like_unformatted_code(self, text): - return re.search('\{*.\}', text) and ("```" not in text or "```\n" in text) + return CODE_REGEX.search(text) and "```" not in text From e518ba3e99ea5e6ebf1d5a2bc435a480d6655920 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:33:52 -0500 Subject: [PATCH 23/38] =?UTF-8?q?docs:=20=F0=9F=92=A1=20add=20docstring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- noncommands/auto_code_block.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/noncommands/auto_code_block.py b/noncommands/auto_code_block.py index aa3a51f..c05a59d 100644 --- a/noncommands/auto_code_block.py +++ b/noncommands/auto_code_block.py @@ -32,4 +32,7 @@ def check(reaction, user): pass def looks_like_unformatted_code(self, text): + """ + Returns True if the text looks like it might contain unformatted code. + """ return CODE_REGEX.search(text) and "```" not in text From 2ff06f27ae5c31c24e6e024cdfdef36f19d8d284 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:35:06 -0500 Subject: [PATCH 24/38] =?UTF-8?q?refactor:=20=F0=9F=9A=A8=20remove=20unuse?= =?UTF-8?q?d=20argument?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/general.py | 2 +- noncommands/summarizer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/general.py b/cogs/general.py index 61316b3..31daca1 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -120,7 +120,7 @@ async def tldrchannel(self, interaction: Interaction, number: int = SlashOption( messages = await interaction.channel.history(limit=number).flatten() text = ". ".join([m.content for m in messages]) text = text.replace(".. ", ". ") - embed = summarizer.getSummaryText(config, text) + embed = summarizer.getSummaryText(text) await interaction.response.send_message(embed=embed) diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index f3d545d..0239268 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -143,7 +143,7 @@ def getSummaryUrl(config, url): return embed -def getSummaryText(config, text): +def getSummaryText(text): numSent = 5 embed = nextcord.Embed( color=SUCCESS_COLOR From b72767a0784b209a93d36e42eceadd5f113aa868 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:37:19 -0500 Subject: [PATCH 25/38] =?UTF-8?q?style:=20=F0=9F=9A=A8=20remove=20extra=20?= =?UTF-8?q?no-op?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- noncommands/auto_code_block.py | 1 - 1 file changed, 1 deletion(-) diff --git a/noncommands/auto_code_block.py b/noncommands/auto_code_block.py index c05a59d..f727d1e 100644 --- a/noncommands/auto_code_block.py +++ b/noncommands/auto_code_block.py @@ -29,7 +29,6 @@ def check(reaction, user): await msg.delete() except asyncio.exceptions.TimeoutError: await msg.clear_reactions() - pass def looks_like_unformatted_code(self, text): """ From a063755b9266eb95b296a1b6c66f33f0337953a0 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:39:20 -0500 Subject: [PATCH 26/38] =?UTF-8?q?refactor:=20=F0=9F=9A=9A=20use=20snake=20?= =?UTF-8?q?case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/general.py | 4 ++-- noncommands/summarizer.py | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cogs/general.py b/cogs/general.py index 31daca1..1165715 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -120,7 +120,7 @@ async def tldrchannel(self, interaction: Interaction, number: int = SlashOption( messages = await interaction.channel.history(limit=number).flatten() text = ". ".join([m.content for m in messages]) text = text.replace(".. ", ". ") - embed = summarizer.getSummaryText(text) + embed = summarizer.get_summary_text(text) await interaction.response.send_message(embed=embed) @@ -130,7 +130,7 @@ async def tldr(self, interaction: Interaction, url: str = SlashOption(descriptio [URL] Get a TLDR a web page. """ try: - await interaction.response.send_message(embed=summarizer.getSummaryUrl(config, url)) + await interaction.response.send_message(embed=summarizer.get_summary_url(config, url)) except: await interaction.response.send_message("There's something odd about that link. Either they won't let me read it or you sent it wrongly.") diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index 0239268..f16d035 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -16,7 +16,7 @@ nltk.download('stopwords') -def scoreSent(sent, scoreMatrix, scoreCol): +def score_sent(sent, scoreMatrix, scoreCol): score = 0 for word in sent.split(" "): if word in scoreMatrix.index: @@ -25,14 +25,14 @@ def scoreSent(sent, scoreMatrix, scoreCol): return score/len(sent) -def filterStopwords(sent): +def filter_stopwords(sent): stop_words = set(stopwords.words('english')) word_tokens = word_tokenize(sent) return " ".join([w for w in word_tokens if w not in stop_words]) -def getSummarySpread(filePath, numSent): +def get_summary_spread(filePath, numSent): f = open(filePath, "r") text = f.read() @@ -42,7 +42,7 @@ def getSummarySpread(filePath, numSent): text = text.replace("[" + str(i) + "]", "") doc = nltk.tokenize.sent_tokenize(text) - docFilt = [filterStopwords(s) for s in doc] + docFilt = [filter_stopwords(s) for s in doc] vectorizer = CountVectorizer() bag_of_words = vectorizer.fit_transform(docFilt) @@ -67,14 +67,14 @@ def getSummarySpread(filePath, numSent): for c in absCol: for s in doc: - cl[c].append([s, scoreSent(s, encoding_matrix, c)]) + cl[c].append([s, score_sent(s, encoding_matrix, c)]) chosen = [] for c in absCol: s = [d for d in sorted(cl[c], key=lambda x: x[1]) if d[0] not in [f[0] for f in chosen]][::-1] chosen.append(s[0]) -def getSummaryMono(text, numSent): +def get_summary_mono(text, numSent): text = " ".join(text.split()) @@ -83,7 +83,7 @@ def getSummaryMono(text, numSent): doc = nltk.tokenize.sent_tokenize(text) - docFilt = [filterStopwords(s) for s in doc] + docFilt = [filter_stopwords(s) for s in doc] vectorizer = CountVectorizer() bag_of_words = vectorizer.fit_transform(docFilt) @@ -111,7 +111,7 @@ def getSummaryMono(text, numSent): for c in absCol: for s in doc: - cl[c].append([s, scoreSent(s, encoding_matrix, c)]) + cl[c].append([s, score_sent(s, encoding_matrix, c)]) chosen = [] for i in range(numSent): @@ -122,7 +122,7 @@ def getSummaryMono(text, numSent): return [i[0] for i in chosen] -def getSummaryUrl(config, url): +def get_summary_url(config, url): numSent = 5 downloaded = trafilatura.fetch_url(url) article = bare_extraction(downloaded) @@ -136,21 +136,21 @@ def getSummaryUrl(config, url): ) embed.add_field( name="Summary:", - value="\n".join(getSummaryMono(article["text"], numSent)), + value="\n".join(get_summary_mono(article["text"], numSent)), inline=False ) return embed -def getSummaryText(text): +def get_summary_text(text): numSent = 5 embed = nextcord.Embed( color=SUCCESS_COLOR ) embed.add_field( name="Summary:", - value="\n".join(getSummaryMono(text, numSent)), + value="\n".join(get_summary_mono(text, numSent)), inline=False ) From ccae18875abb77aeb36b5ce9484ec33f4459130a Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:39:32 -0500 Subject: [PATCH 27/38] =?UTF-8?q?refactor:=20=F0=9F=9A=A8=20remove=20unuse?= =?UTF-8?q?d=20argument?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/general.py | 2 +- noncommands/summarizer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/general.py b/cogs/general.py index 1165715..883d8dc 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -130,7 +130,7 @@ async def tldr(self, interaction: Interaction, url: str = SlashOption(descriptio [URL] Get a TLDR a web page. """ try: - await interaction.response.send_message(embed=summarizer.get_summary_url(config, url)) + await interaction.response.send_message(embed=summarizer.get_summary_url(url)) except: await interaction.response.send_message("There's something odd about that link. Either they won't let me read it or you sent it wrongly.") diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index f16d035..fa47d8b 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -122,7 +122,7 @@ def get_summary_mono(text, numSent): return [i[0] for i in chosen] -def get_summary_url(config, url): +def get_summary_url(url): numSent = 5 downloaded = trafilatura.fetch_url(url) article = bare_extraction(downloaded) From 34647208e26c31a8d5863c6cd7e7599d5d62fe94 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:54:35 -0500 Subject: [PATCH 28/38] =?UTF-8?q?build:=20=F0=9F=94=A7=20add=20pebble=20ho?= =?UTF-8?q?st=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pebble-python-config.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 pebble-python-config.json diff --git a/pebble-python-config.json b/pebble-python-config.json new file mode 100644 index 0000000..b718b60 --- /dev/null +++ b/pebble-python-config.json @@ -0,0 +1,5 @@ +{ + "main": "bot.py", + "requirementsFile": "requirements.txt", + "pythonVersion": "3.11" +} From 5d4ac2908c63deba4ba53b2436fcd65ce90f0e9b Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:02:37 -0500 Subject: [PATCH 29/38] =?UTF-8?q?docs:=20=F0=9F=92=A1=20add=20module=20lev?= =?UTF-8?q?el=20doc=20strings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 5 +++++ cogs/channel.py | 5 +++++ cogs/fun.py | 4 ++++ cogs/general.py | 5 +++++ cogs/help.py | 5 +++++ cogs/quotes.py | 5 +++++ cogs/ratemyprofessor.py | 5 +++++ cogs/template.py | 5 +++++ 8 files changed, 39 insertions(+) diff --git a/bot.py b/bot.py index 570f823..72d6903 100644 --- a/bot.py +++ b/bot.py @@ -1,3 +1,8 @@ +""" +This is the main file that runs the bot. +""" + + import os import platform import nextcord diff --git a/cogs/channel.py b/cogs/channel.py index 204bdff..2e2d87e 100644 --- a/cogs/channel.py +++ b/cogs/channel.py @@ -1,3 +1,8 @@ +""" +This cog adds commands related to the creation and deletion of class channels. +""" + + import asyncio from collections import OrderedDict from string import ascii_lowercase diff --git a/cogs/fun.py b/cogs/fun.py index 6b0e29b..7e08677 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -1,3 +1,7 @@ +""" +This cog add fun little random things. +""" + import random import aiohttp diff --git a/cogs/general.py b/cogs/general.py index 883d8dc..37a896a 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -1,3 +1,8 @@ +""" +This cog adds meta commands having to do with the bot itself. +""" + + import platform from noncommands import summarizer import nextcord diff --git a/cogs/help.py b/cogs/help.py index b5c1180..a22157c 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -1,3 +1,8 @@ +""" +This cog adds a help command. +""" + + import nextcord from nextcord.ext import commands from nextcord import Interaction diff --git a/cogs/quotes.py b/cogs/quotes.py index c3305ee..98d859d 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -1,3 +1,8 @@ +""" +This cog adds commands for getting and creating quotes. +""" + + from noncommands import quotes import nextcord from nextcord.ext import commands diff --git a/cogs/ratemyprofessor.py b/cogs/ratemyprofessor.py index 8a2912a..a441f93 100644 --- a/cogs/ratemyprofessor.py +++ b/cogs/ratemyprofessor.py @@ -1,3 +1,8 @@ +""" +This cog adds a command for accessing ratemyprofessor +""" + + import ratemyprofessor import nextcord from nextcord.ext import commands diff --git a/cogs/template.py b/cogs/template.py index 85d0a86..01dcec9 100644 --- a/cogs/template.py +++ b/cogs/template.py @@ -1,3 +1,8 @@ +# """ +# This is a template for a new cog. +# """ +# +# # import os # import sys # import nextcord From 209e0da9b630d8b49bde660643a8244ff35eea9d Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:07:26 -0500 Subject: [PATCH 30/38] =?UTF-8?q?refactor:=20=F0=9F=9A=9A=20use=20snake=5F?= =?UTF-8?q?case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bot.py b/bot.py index 72d6903..3da8d9b 100644 --- a/bot.py +++ b/bot.py @@ -77,11 +77,11 @@ async def on_command_completion(ctx): """ The code in this event is executed every time a command has been *successfully* executed """ - fullCommandName = ctx.command.qualified_name - split = fullCommandName.split(" ") - executedCommand = str(split[0]) + full_command_name = ctx.command.qualified_name + split = full_command_name.split(" ") + executed_command = str(split[0]) print( - f"Executed {executedCommand} command in {ctx.guild.name} (ID: {ctx.message.guild.id}) by {ctx.message.author} (ID: {ctx.message.author.id})") + f"Executed {executed_command} command in {ctx.guild.name} (ID: {ctx.message.guild.id}) by {ctx.message.author} (ID: {ctx.message.author.id})") @bot.event From d8e42e5c2f598db6f6aaaf44d01e114d1aee60d4 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:13:44 -0500 Subject: [PATCH 31/38] =?UTF-8?q?chore:=20=F0=9F=9A=A8=20ignore=20warning?= =?UTF-8?q?=20about=20catching=20all=20eceptions=20at=20the=20top=20level?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 3da8d9b..29969ac 100644 --- a/bot.py +++ b/bot.py @@ -48,7 +48,7 @@ async def on_ready(): try: bot.load_extension(f"cogs.{extension}") print(f"Loaded extension '{extension}'") - except Exception as e: + except Exception as e: # pylint: disable=broad-except; because we want to catch all errors exception = f"{type(e).__name__}: {e}" print(f"Failed to load extension {extension}\n{exception}") From 8863ea6bd4ec738f168ac0cf0d31808d972fee00 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:38:45 -0500 Subject: [PATCH 32/38] =?UTF-8?q?refactor:=20=F0=9F=9A=A8=20fix=20some=20p?= =?UTF-8?q?ylint=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 2 +- cogs/channel.py | 21 ++++++++++++++------- pyproject.toml | 1 + 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/bot.py b/bot.py index 29969ac..3da8d9b 100644 --- a/bot.py +++ b/bot.py @@ -48,7 +48,7 @@ async def on_ready(): try: bot.load_extension(f"cogs.{extension}") print(f"Loaded extension '{extension}'") - except Exception as e: # pylint: disable=broad-except; because we want to catch all errors + except Exception as e: exception = f"{type(e).__name__}: {e}" print(f"Failed to load extension {extension}\n{exception}") diff --git a/cogs/channel.py b/cogs/channel.py index 2e2d87e..7ca6b18 100644 --- a/cogs/channel.py +++ b/cogs/channel.py @@ -97,7 +97,7 @@ async def create_category(category_name, interaction: Interaction): } try: return await guild.create_category(category_name, overwrites=overwrites) - except: + except Exception: print("Issue with ", category_name, ". Error: ", sys.exc_info()[0]) @@ -111,13 +111,16 @@ async def create_channel(channel_name: str, category: nextcord.CategoryChannel, async def create_role(interaction: Interaction, role_name: str, permissions: Permissions = Permissions.none(), color=Colour.default()): """ - creates a role with specified permissions, with specifed name. + creates a role with specified permissions, with specified name. """ return await interaction.guild.create_role(name=role_name, permissions=permissions, colour=color) async def create_role_for_category(interaction: Interaction, category: nextcord.CategoryChannel, term: str): + """ + creates a role for a category and returns role object + """ role_name = f"{category.name.replace('-', ' ')} {term}" role = await create_role(interaction, role_name, color=nextcord.Colour.blue()) # gives basic permissions to a role for its assigned channel @@ -141,6 +144,10 @@ def reaction_emoji() -> Generator[str, None, None]: class ChannelManager(Cog, name="channelmanager"): + """ + This cog adds commands related to the creation and deletion of class channels. + """ + def __init__(self, bot): self.bot = bot @@ -152,9 +159,9 @@ async def import_classes(self, interaction: Interaction, file: Attachment = Slas """ try: - json = await read_class_json(file) - except Exception as e: - await interaction.response.send_message(f"Error: {e}", ephemeral=True) + json_data = await read_class_json(file) + except Exception as exception: + await interaction.response.send_message(f"Error: {exception}", ephemeral=True) return await interaction.response.defer() @@ -165,7 +172,7 @@ async def import_classes(self, interaction: Interaction, file: Attachment = Slas courses_by_category_name: OrderedDict[str, list[Section]] = OrderedDict() - for section in json["classes"]: + for section in json_data["classes"]: # first 3 numbers only (not L1,L2,L3) course_number = section["course"][0:3] @@ -217,7 +224,7 @@ async def import_classes(self, interaction: Interaction, file: Attachment = Slas coroutines.append(create_channel(channel_name, category, interaction, description)) channels_count += 1 - coroutines.append(create_role_for_category(interaction, category, json["term"])) + coroutines.append(create_role_for_category(interaction, category, json_data["term"])) roles_count += 1 coroutines.append( diff --git a/pyproject.toml b/pyproject.toml index e3541b0..e2a2bad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ recursive = true [tool.pylint.messages_control] disable = [ "line-too-long", # disable because we use autopep8 + "broad-except", # because in many cases we want the program to continue even if there is an exception ] [tool.autopep8] From 1701f38e02b29be796268487ab568be5023b8c35 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:41:20 -0500 Subject: [PATCH 33/38] =?UTF-8?q?docs:=20=F0=9F=9A=A8=20add=20docstring=20?= =?UTF-8?q?to=20cogs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/fun.py | 4 ++++ cogs/general.py | 4 ++++ cogs/help.py | 4 ++++ cogs/quotes.py | 4 ++++ cogs/ratemyprofessor.py | 4 ++++ cogs/template.py | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/cogs/fun.py b/cogs/fun.py index 7e08677..bca436a 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -17,6 +17,10 @@ class Fun(commands.Cog, name="fun"): + """ + This cog add fun little random things. + """ + def __init__(self, bot): self.bot = bot diff --git a/cogs/general.py b/cogs/general.py index 37a896a..bbd85a8 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -13,6 +13,10 @@ class general(commands.Cog, name="general"): + """ + This cog adds meta commands having to do with the bot itself. + """ + def __init__(self, bot): self.bot = bot diff --git a/cogs/help.py b/cogs/help.py index a22157c..8b822ad 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -9,6 +9,10 @@ class Help(commands.Cog, name="help"): + """ + This cog adds a help command. + """ + def __init__(self, bot): self.bot = bot diff --git a/cogs/quotes.py b/cogs/quotes.py index 98d859d..5fd04b6 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -10,6 +10,10 @@ class Quotes(commands.Cog, name="quotes"): + """ + This cog adds commands for getting and creating quotes. + """ + def __init__(self, bot): self.bot = bot diff --git a/cogs/ratemyprofessor.py b/cogs/ratemyprofessor.py index a441f93..cfbcc8a 100644 --- a/cogs/ratemyprofessor.py +++ b/cogs/ratemyprofessor.py @@ -12,6 +12,10 @@ class RateMyProfessor(commands.Cog, name="rate my professor"): + """ + This cog adds a command for accessing ratemyprofessor + """ + def __init__(self, bot): self.bot = bot self.profImages = { diff --git a/cogs/template.py b/cogs/template.py index 01dcec9..8abcc8e 100644 --- a/cogs/template.py +++ b/cogs/template.py @@ -15,6 +15,10 @@ # # # class Template(commands.Cog, name="template"): # Here we name the cog and create a new class for the cog. +# """ +# This is a template for a new cog. +# """ +# # def __init__(self, bot): # self.bot = bot # From 36f14953bfa5b22b8cdf84eb9cce71be011400ff Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:44:00 -0500 Subject: [PATCH 34/38] =?UTF-8?q?docs:=20=F0=9F=92=A1=20add=20docstrings?= =?UTF-8?q?=20to=20cog=20setup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/channel.py | 4 +++- cogs/fun.py | 3 +++ cogs/general.py | 3 +++ cogs/help.py | 3 +++ cogs/quotes.py | 3 +++ cogs/template.py | 5 ++++- 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/cogs/channel.py b/cogs/channel.py index 7ca6b18..8b23417 100644 --- a/cogs/channel.py +++ b/cogs/channel.py @@ -322,6 +322,8 @@ async def carl_class_roles(self, interaction: Interaction): await interaction.followup.send(embed=embed) -# And then we finally add the cog to the bot so that it can load, unload, reload and use it's content. def setup(bot): + """ + Add the cog to the bot so that it can load, unload, reload and use it's content. + """ bot.add_cog(ChannelManager(bot)) diff --git a/cogs/fun.py b/cogs/fun.py index bca436a..8cb5467 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -137,4 +137,7 @@ async def advice(self, interaction: Interaction): def setup(bot): + """ + Add the cog to the bot so that it can load, unload, reload and use it's content. + """ bot.add_cog(Fun(bot)) diff --git a/cogs/general.py b/cogs/general.py index bbd85a8..8e5e3e1 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -145,4 +145,7 @@ async def tldr(self, interaction: Interaction, url: str = SlashOption(descriptio def setup(bot): + """ + Add the cog to the bot so that it can load, unload, reload and use it's content. + """ bot.add_cog(general(bot)) diff --git a/cogs/help.py b/cogs/help.py index 8b822ad..e677e3d 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -26,4 +26,7 @@ async def help(self, interaction: Interaction): def setup(bot): + """ + Add the cog to the bot so that it can load, unload, reload and use it's content. + """ bot.add_cog(Help(bot)) diff --git a/cogs/quotes.py b/cogs/quotes.py index 5fd04b6..2fc3b56 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -39,4 +39,7 @@ async def newquote(self, interaction: Interaction, quote: str = SlashOption(desc def setup(bot): + """ + Add the cog to the bot so that it can load, unload, reload and use it's content. + """ bot.add_cog(Quotes(bot)) diff --git a/cogs/template.py b/cogs/template.py index 8abcc8e..319f79d 100644 --- a/cogs/template.py +++ b/cogs/template.py @@ -31,5 +31,8 @@ # await context.send("I'll tell you when you're older. Move along now, child.") # # -# def setup(bot): # And then we finally add the cog to the bot so that it can load, unload, reload and use it's content. +# def setup(bot): +# """ +# Add the cog to the bot so that it can load, unload, reload and use it's content. +# """ # bot.add_cog(Template(bot)) From 5224fa67aa7c331df0e70216186bbce3faae45ed Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:47:07 -0500 Subject: [PATCH 35/38] =?UTF-8?q?refactor:=20=F0=9F=9A=A8=20import=203rd?= =?UTF-8?q?=20party=20code=20before=20relitive=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 1 - cogs/general.py | 2 +- cogs/quotes.py | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index 3da8d9b..1deed6f 100644 --- a/bot.py +++ b/bot.py @@ -12,7 +12,6 @@ from nextcord.ext.commands import Bot from noncommands import auto_code_block, quotes - from constants import ERROR_COLOR, config diff --git a/cogs/general.py b/cogs/general.py index 8e5e3e1..2233777 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -4,11 +4,11 @@ import platform -from noncommands import summarizer import nextcord from nextcord.ext import commands from nextcord import Interaction, SlashOption +from noncommands import summarizer from constants import config, SUCCESS_COLOR diff --git a/cogs/quotes.py b/cogs/quotes.py index 2fc3b56..a18147a 100644 --- a/cogs/quotes.py +++ b/cogs/quotes.py @@ -3,11 +3,12 @@ """ -from noncommands import quotes import nextcord from nextcord.ext import commands from nextcord import Interaction, SlashOption +from noncommands import quotes + class Quotes(commands.Cog, name="quotes"): """ From 09ad8cde10e151ee5adc1c188ca35cc8b43961d6 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:58:33 -0500 Subject: [PATCH 36/38] =?UTF-8?q?refactor:=20=F0=9F=9A=A8=20snake=5Fcase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/ratemyprofessor.py | 51 +++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/cogs/ratemyprofessor.py b/cogs/ratemyprofessor.py index cfbcc8a..87bd7a0 100644 --- a/cogs/ratemyprofessor.py +++ b/cogs/ratemyprofessor.py @@ -10,6 +10,14 @@ from constants import SUCCESS_COLOR +PROF_IMAGES = { + "William Sverdlik": "https://www.emich.edu/computer-science/images/faculty/w-sverdlik.jpg", + "Zenia Bahorski": "https://www.emich.edu/computer-science/images/faculty/zbahorski.jpg", + "Andrii Kashliev": "https://www.emich.edu/computer-science/images/faculty/andreii-kashliev.jpg", + "Krish Narayanan": "https://www.emich.edu/computer-science/images/faculty/k-narayanan.jpg", + "Siyuan Jiang": "https://www.emich.edu/computer-science/images/faculty/s-jiang.jpg", +} + class RateMyProfessor(commands.Cog, name="rate my professor"): """ @@ -18,13 +26,6 @@ class RateMyProfessor(commands.Cog, name="rate my professor"): def __init__(self, bot): self.bot = bot - self.profImages = { - "William Sverdlik": "https://www.emich.edu/computer-science/images/faculty/w-sverdlik.jpg", - "Zenia Bahorski": "https://www.emich.edu/computer-science/images/faculty/zbahorski.jpg", - "Andrii Kashliev": "https://www.emich.edu/computer-science/images/faculty/andreii-kashliev.jpg", - "Krish Narayanan": "https://www.emich.edu/computer-science/images/faculty/k-narayanan.jpg", - "Siyuan Jiang": "https://www.emich.edu/computer-science/images/faculty/s-jiang.jpg", - } @nextcord.slash_command(name="rmp", description="Check out what RateMyProfessor has to say about a professor!") async def rmp(self, interaction: nextcord.Interaction, professorname: str = SlashOption(name="professorname", description="The name of the professor you want to look up", required=True)): @@ -35,27 +36,27 @@ async def rmp(self, interaction: nextcord.Interaction, professorname: str = Slas EMU = ratemyprofessor.get_school_by_name("Eastern Michigan University") prof = ratemyprofessor.get_professor_by_school_and_name(EMU, professorname) - ratingsBest = sorted([rating for rating in prof.get_ratings() if rating.comment], - key=lambda rating: (rating.rating, rating.date)) - bestRating = ratingsBest[-1] + ratings_best = sorted([rating for rating in prof.get_ratings() if rating.comment], + key=lambda rating: (rating.rating, rating.date)) + best_rating = ratings_best[-1] - ratingsWorst = sorted([rating for rating in prof.get_ratings() if rating.comment], - key=lambda rating: (-rating.rating, rating.date)) - worstRating = ratingsWorst[-1] + ratings_worst = sorted([rating for rating in prof.get_ratings() if rating.comment], + key=lambda rating: (-rating.rating, rating.date)) + worst_rating = ratings_worst[-1] - profEmbed = self.buildProfEmbed(prof) - bestembed = self.buildRatingEmbed(nextcord.Embed(title=f"Best Rating for {prof.name}", color=SUCCESS_COLOR), - bestRating) - worstembed = self.buildRatingEmbed(nextcord.Embed(title=f"Worst Rating for {prof.name}", color=SUCCESS_COLOR), - worstRating) + prof_embed = self.build_prof_embed(prof) + best_embed = self.build_rating_embed(nextcord.Embed(title=f"Best Rating for {prof.name}", color=SUCCESS_COLOR), + best_rating) + worst_embed = self.build_rating_embed(nextcord.Embed(title=f"Worst Rating for {prof.name}", color=SUCCESS_COLOR), + worst_rating) - await interaction.response.send_message(embed=profEmbed) - await interaction.followup.send(embed=bestembed) - await interaction.followup.send(embed=worstembed) + await interaction.response.send_message(embed=prof_embed) + await interaction.followup.send(embed=best_embed) + await interaction.followup.send(embed=worst_embed) except: await interaction.response.send_message(f"Could not find professor '{professorname}'. Try only using a last name or check your spelling!") - def buildRatingEmbed(self, embed, rating): + def build_rating_embed(self, embed, rating): if rating.rating: embed.add_field( name="Rating", @@ -100,14 +101,14 @@ def buildRatingEmbed(self, embed, rating): return embed - def buildProfEmbed(self, prof): + def build_prof_embed(self, prof): embed = nextcord.Embed( title=prof, color=SUCCESS_COLOR ) - if prof.name in self.profImages: - embed.set_image(url=self.profImages[prof.name]) + if prof.name in PROF_IMAGES: + embed.set_image(url=PROF_IMAGES[prof.name]) embed.add_field( name="Department", From 68397accd1ef4d6f07a3a9fccf2f923853cdced6 Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Fri, 30 Dec 2022 15:04:45 -0500 Subject: [PATCH 37/38] =?UTF-8?q?refactor:=20=F0=9F=9A=A8=20snake=5Fcase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 2 +- cogs/general.py | 4 +-- noncommands/quotes.py | 2 +- noncommands/summarizer.py | 62 +++++++++++++++++++-------------------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/bot.py b/bot.py index 1deed6f..331f3b7 100644 --- a/bot.py +++ b/bot.py @@ -109,7 +109,7 @@ async def on_command_error(context, error): await context.send(embed=embed) raise error -scheduler.add_job(toSchedule.dailyQuote, +scheduler.add_job(toSchedule.daily_quote, CronTrigger(hour="8", minute="0", second="0", day_of_week="0-4", timezone="EST")) scheduler.start() bot.run(config["token"]) diff --git a/cogs/general.py b/cogs/general.py index 2233777..eb1b7ca 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -12,7 +12,7 @@ from constants import config, SUCCESS_COLOR -class general(commands.Cog, name="general"): +class General(commands.Cog, name="general"): """ This cog adds meta commands having to do with the bot itself. """ @@ -148,4 +148,4 @@ def setup(bot): """ Add the cog to the bot so that it can load, unload, reload and use it's content. """ - bot.add_cog(general(bot)) + bot.add_cog(General(bot)) diff --git a/noncommands/quotes.py b/noncommands/quotes.py index 0687058..9d974c3 100644 --- a/noncommands/quotes.py +++ b/noncommands/quotes.py @@ -7,7 +7,7 @@ class Quotes: def __init__(self, bot): self.bot = bot - async def dailyQuote(self): + async def daily_quote(self): channel = self.bot.get_channel(707293854507991172) dailyquote = await Quotes.quote(self.bot, "") await channel.send("Daily Quote:\n" + dailyquote) diff --git a/noncommands/summarizer.py b/noncommands/summarizer.py index fa47d8b..b0cc890 100644 --- a/noncommands/summarizer.py +++ b/noncommands/summarizer.py @@ -16,12 +16,12 @@ nltk.download('stopwords') -def score_sent(sent, scoreMatrix, scoreCol): +def score_sent(sent, score_matrix, score_col): score = 0 for word in sent.split(" "): - if word in scoreMatrix.index: - filt = scoreMatrix.filter(items=[word], axis='index') - score += filt[scoreCol].values[0] + if word in score_matrix.index: + filt = score_matrix.filter(items=[word], axis='index') + score += filt[score_col].values[0] return score/len(sent) @@ -32,9 +32,9 @@ def filter_stopwords(sent): return " ".join([w for w in word_tokens if w not in stop_words]) -def get_summary_spread(filePath, numSent): +def get_summary_spread(file_path, num_sent): - f = open(filePath, "r") + f = open(file_path, "r") text = f.read() text = " ".join(text.split()) @@ -42,39 +42,39 @@ def get_summary_spread(filePath, numSent): text = text.replace("[" + str(i) + "]", "") doc = nltk.tokenize.sent_tokenize(text) - docFilt = [filter_stopwords(s) for s in doc] + doc_filt = [filter_stopwords(s) for s in doc] vectorizer = CountVectorizer() - bag_of_words = vectorizer.fit_transform(docFilt) + bag_of_words = vectorizer.fit_transform(doc_filt) - svd = TruncatedSVD(n_components=numSent) + svd = TruncatedSVD(n_components=num_sent) lsa = svd.fit_transform(bag_of_words) - col = ["topic" + str(i) for i in range(numSent)] + col = ["topic" + str(i) for i in range(num_sent)] - absCol = ["abs_topic" + str(i) for i in range(numSent)] + abs_col = ["abs_topic" + str(i) for i in range(num_sent)] topic_encoded_df = pd.DataFrame(lsa, columns=col) - topic_encoded_df["docFilt"] = docFilt + topic_encoded_df["docFilt"] = doc_filt topic_encoded_df["doc"] = doc dictionary = vectorizer.get_feature_names_out() encoding_matrix = pd.DataFrame(svd.components_, index=col, columns=dictionary).T - for i in range(numSent): - encoding_matrix[absCol[i]] = np.abs(encoding_matrix[col[i]]) + for i in range(num_sent): + encoding_matrix[abs_col[i]] = np.abs(encoding_matrix[col[i]]) cl = dict() - for c in absCol: + for c in abs_col: cl[c] = [] - for c in absCol: + for c in abs_col: for s in doc: cl[c].append([s, score_sent(s, encoding_matrix, c)]) chosen = [] - for c in absCol: + for c in abs_col: s = [d for d in sorted(cl[c], key=lambda x: x[1]) if d[0] not in [f[0] for f in chosen]][::-1] chosen.append(s[0]) -def get_summary_mono(text, numSent): +def get_summary_mono(text, num_sent): text = " ".join(text.split()) @@ -83,39 +83,39 @@ def get_summary_mono(text, numSent): doc = nltk.tokenize.sent_tokenize(text) - docFilt = [filter_stopwords(s) for s in doc] + doc_filt = [filter_stopwords(s) for s in doc] vectorizer = CountVectorizer() - bag_of_words = vectorizer.fit_transform(docFilt) + bag_of_words = vectorizer.fit_transform(doc_filt) svd = TruncatedSVD(n_components=1) lsa = svd.fit_transform(bag_of_words) col = ["topic1"] - absCol = ["abs_topic1"] + abs_col = ["abs_topic1"] topic_encoded_df = pd.DataFrame(lsa, columns=col) - topic_encoded_df["docFilt"] = docFilt + topic_encoded_df["docFilt"] = doc_filt topic_encoded_df["doc"] = doc dictionary = vectorizer.get_feature_names_out() encoding_matrix = pd.DataFrame(svd.components_, index=col, columns=dictionary).T for i in range(len(col)): - encoding_matrix[absCol[i]] = np.abs(encoding_matrix[col[i]]) + encoding_matrix[abs_col[i]] = np.abs(encoding_matrix[col[i]]) cl = dict() - for c in absCol: + for c in abs_col: cl[c] = [] - for c in absCol: + for c in abs_col: for s in doc: cl[c].append([s, score_sent(s, encoding_matrix, c)]) chosen = [] - for i in range(numSent): - for c in absCol: + for i in range(num_sent): + for c in abs_col: s = [d for d in sorted(cl[c], key=lambda x: x[1]) if d[0] not in [f[0] for f in chosen]][::-1] chosen.append(s[0]) @@ -123,7 +123,7 @@ def get_summary_mono(text, numSent): def get_summary_url(url): - numSent = 5 + num_sent = 5 downloaded = trafilatura.fetch_url(url) article = bare_extraction(downloaded) embed = nextcord.Embed( @@ -136,7 +136,7 @@ def get_summary_url(url): ) embed.add_field( name="Summary:", - value="\n".join(get_summary_mono(article["text"], numSent)), + value="\n".join(get_summary_mono(article["text"], num_sent)), inline=False ) @@ -144,13 +144,13 @@ def get_summary_url(url): def get_summary_text(text): - numSent = 5 + num_sent = 5 embed = nextcord.Embed( color=SUCCESS_COLOR ) embed.add_field( name="Summary:", - value="\n".join(get_summary_mono(text, numSent)), + value="\n".join(get_summary_mono(text, num_sent)), inline=False ) From b3b55757c075b0356b91c22db91fa8148f64daff Mon Sep 17 00:00:00 2001 From: Nate Stringham <44071655+nstringham@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:39:19 -0500 Subject: [PATCH 38/38] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20use=20`i?= =?UTF-8?q?s`=20instead=20of=20`=3D=3D`=20for=20None?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/general.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/general.py b/cogs/general.py index eb1b7ca..092505f 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -70,7 +70,7 @@ async def serverinfo(self, interaction: Interaction): color=SUCCESS_COLOR ) - if server.icon != None: + if server.icon is not None: embed.set_thumbnail( url=server.icon.url )