From 2357c835a64e57432acf3fe43835584c1397af9e Mon Sep 17 00:00:00 2001 From: Vegard Berg Date: Thu, 21 Jul 2022 21:27:47 +0200 Subject: [PATCH] Made Pylint happy. --- Heimdallr.py | 16 ++-- commands/infractions.py | 162 +++++++++++++++++++++++++++------------- commands/quote.py | 72 ++++++++++++------ database.py | 5 +- poetry.lock | 101 ++++++++++++++++++++++++- pyproject.toml | 12 +++ 6 files changed, 279 insertions(+), 89 deletions(-) diff --git a/Heimdallr.py b/Heimdallr.py index 69e95fa..930f291 100644 --- a/Heimdallr.py +++ b/Heimdallr.py @@ -1,27 +1,21 @@ -import re +from os import getenv + from naff import ( Client, Intents, listen, slash_command, InteractionContext, - slash_option, - OptionTypes, ) from naff.api.events.discord import MessageCreate -from naff.models.discord.enums import ButtonStyles, Permissions from naff.models.discord.embed import ( Embed, - EmbedAttachment, EmbedAuthor, EmbedField, EmbedFooter, - EmbedProvider, ) -from naff.models.discord.components import ActionRow, Button, Select, SelectOption from dotenv import load_dotenv -from os import getenv bot = Client(intents=Intents.ALL, debug_scope=387153131378835456) @@ -42,6 +36,7 @@ async def ping_command(ctx: InteractionContext): ctx.ephemeral = True await ctx.send("Pong!") + @slash_command(name="bot-info", description="Get info about the bot") async def bot_info_command(ctx: InteractionContext): await ctx.send( @@ -49,7 +44,7 @@ async def bot_info_command(ctx: InteractionContext): embed=Embed( title=f"{bot.user.username}", description=f"This bot is owned by {bot.owner}", - color=0x00ff00, + color=0x00FF00, timestamp=bot.user.created_at, url=bot.user.avatar.as_url(), author=EmbedAuthor( @@ -65,7 +60,7 @@ async def bot_info_command(ctx: InteractionContext): name="**Extensions**", value=f"{len(bot.extensions)}", ) - ] + ], ), ) @@ -75,4 +70,3 @@ if __name__ == "__main__": bot.load_extension("commands.quote") bot.load_extension("commands.infractions") bot.start(getenv("DISCORD_TOKEN")) - diff --git a/commands/infractions.py b/commands/infractions.py index 82a8cd8..ebf4f85 100644 --- a/commands/infractions.py +++ b/commands/infractions.py @@ -7,8 +7,6 @@ from naff import ( OptionTypes, InteractionContext, Embed, - EmbedAttachment, - EmbedAuthor, EmbedField, Permissions, Member, @@ -17,7 +15,9 @@ from naff import ( Button, ButtonStyles, ) -from database import Infractions as InfractionsModel, GuildSettings as GuildSettingsModel +from database import ( + Infractions as InfractionsModel, +) class Infractions(Extension): @@ -39,7 +39,7 @@ class Infractions(Extension): return embeds: List[Embed] = [] - for infraction in infractions: + for infraction in infractions: # pylint: disable=not-an-iterable embed = Embed( title="Infraction", description=f"{infraction.reason}", @@ -53,12 +53,21 @@ class Infractions(Extension): ], ) embeds.append(embed) - - await ctx.send(embed=embeds, ephemeral=True) - - @slash_command(name="user-infractions", description="View a user's infractions", dm_permission=False, default_member_permissions=Permissions.KICK_MEMBERS) - @slash_option(name="user", description="User to view", required=True, opt_type=OptionTypes.USER) + await ctx.send(embed=embeds, ephemeral=True) + + @slash_command( + name="user-infractions", + description="View a user's infractions", + dm_permission=False, + default_member_permissions=Permissions.KICK_MEMBERS, + ) + @slash_option( + name="user", + description="User to view", + required=True, + opt_type=OptionTypes.USER, + ) async def user_infractions(self, ctx: InteractionContext, user: Member): await ctx.defer(ephemeral=False) infractions: List[InfractionsModel] = InfractionsModel.select().where( @@ -71,16 +80,16 @@ class Infractions(Extension): return embeds: List[Embed] = [] - for infraction in infractions: - issuer = await self.client.fetch_member(guild_id=ctx.guild, user_id=infraction.given_by) + for infraction in infractions: # pylint: disable=not-an-iterable + issuer = await self.client.fetch_member( + guild_id=ctx.guild, user_id=infraction.given_by + ) embed = Embed( - title=f"Infraction for user {user.display_name} ({user.username}#{user.discriminator}, {user.id})", + title=f"Infraction for user {user.display_name} ({user.username}#{user.discriminator}, {user.id})", # pylint: disable=line-too-long description=f"{infraction.reason}", color=infraction_colour(infraction.weight), fields=[ - EmbedField( - name="**ID**", value=f"{infraction.id}" - ), + EmbedField(name="**ID**", value=f"{infraction.id}"), EmbedField( name="**Received**", value=f"", @@ -90,15 +99,49 @@ class Infractions(Extension): ], ) embeds.append(embed) - + await ctx.send(embed=embeds, ephemeral=False) - @slash_command(name="warn", description="Warn a user", dm_permission=False, default_member_permissions=Permissions.KICK_MEMBERS) - @slash_option(name="user", description="User to warn", required=True, opt_type=OptionTypes.USER) - @slash_option(name="reason", description="Reason for warning", required=False, opt_type=OptionTypes.STRING) - @slash_option(name="weight", description="Severity of warning", required=False, opt_type=OptionTypes.NUMBER, min_value=0.0, max_value=10.0) - @slash_option(name="silent", description="Silent warning (will not notify user)", required=False, opt_type=OptionTypes.BOOLEAN) - async def warn_user(self, ctx: InteractionContext, user: Member, reason: str = None, weight: float = None, silent: bool = None): + @slash_command( + name="warn", + description="Warn a user", + dm_permission=False, + default_member_permissions=Permissions.KICK_MEMBERS, + ) + @slash_option( + name="user", + description="User to warn", + required=True, + opt_type=OptionTypes.USER, + ) + @slash_option( + name="reason", + description="Reason for warning", + required=False, + opt_type=OptionTypes.STRING, + ) + @slash_option( + name="weight", + description="Severity of warning", + required=False, + opt_type=OptionTypes.NUMBER, + min_value=0.0, + max_value=10.0, + ) + @slash_option( + name="silent", + description="Silent warning (will not notify user)", + required=False, + opt_type=OptionTypes.BOOLEAN, + ) + async def warn_user( + self, + ctx: InteractionContext, + user: Member, + reason: str = None, + weight: float = None, + silent: bool = None, + ): await ctx.defer(ephemeral=False) if weight is None: weight = 1.0 @@ -124,55 +167,75 @@ class Infractions(Extension): color=infraction_colour(weight), fields=[ EmbedField(name="**Severity**", value=f"{weight}"), - EmbedField(name="**Issued at**", value=f""), + EmbedField( + name="**Issued at**", + value=f"", # pylint: disable=no-member + ), ], ) ) - except Exception: + except Exception: # pylint: disable=broad-except warning_msg = None - - await ctx.send(f"Warned {user.display_name} ({user.username}#{user.discriminator}, {user.id}) for \"{reason}\" with severity {weight}", ephemeral=True) + await ctx.send( + f'Warned {user.display_name} ({user.username}#{user.discriminator}, {user.id}) for "{reason}" with severity {weight}', # pylint: disable=line-too-long + ephemeral=True, + ) if not silent and warning_msg is None: - await ctx.send(f"{user.mention} has been warned, but I couldn't DM them.", ephemeral=True) + await ctx.send( + f"{user.mention} has been warned, but I couldn't DM them.", + ephemeral=True, + ) - - @slash_command(name="remove-infraction", description="Remove an infraction", dm_permission=False, default_member_permissions=Permissions.KICK_MEMBERS) - @slash_option(name="infraction-id", description="ID of infraction to remove", required=True, opt_type=OptionTypes.INTEGER) + @slash_command( + name="remove-infraction", + description="Remove an infraction", + dm_permission=False, + default_member_permissions=Permissions.KICK_MEMBERS, + ) + @slash_option( + name="infraction-id", + description="ID of infraction to remove", + required=True, + opt_type=OptionTypes.INTEGER, + ) async def remove_infraction(self, ctx: InteractionContext, infraction_id: int): await ctx.defer(ephemeral=True) - infraction: InfractionsModel = InfractionsModel.get_or_none(InfractionsModel.id == infraction_id) + infraction: InfractionsModel = InfractionsModel.get_or_none( + InfractionsModel.id == infraction_id + ) if infraction is None: await ctx.send("That infraction doesn't exist.", ephemeral=True) return - elif infraction.guild_id != int(ctx.guild_id): + if infraction.guild_id != int(ctx.guild_id): await ctx.send("That infraction doesn't exist.", ephemeral=True) return - components = [ActionRow( + # pylint: disable=unexpected-keyword-arg + components = [ + ActionRow( Button( custom_id=f"remove-infraction:remove:{infraction.id}", - style= ButtonStyles.DANGER, + style=ButtonStyles.DANGER, label="Remove infraction", ), Button( custom_id=f"remove-infraction:cancel:{infraction.id}", - style= ButtonStyles.SECONDARY, + style=ButtonStyles.SECONDARY, label="Cancel", ), - )] + ) + ] - msg = await ctx.send( + await ctx.send( content="Remove this infraction? (times out in 60 seconds)", embed=Embed( title="Infraction", description=f"{infraction.reason}", color=infraction_colour(infraction.weight), fields=[ - EmbedField( - name="**ID**", value=f"{infraction.id}" - ), + EmbedField(name="**ID**", value=f"{infraction.id}"), EmbedField( name="**Received**", value=f"", @@ -182,11 +245,13 @@ class Infractions(Extension): ], ), ephemeral=True, - components=components + components=components, ) try: - used_comp = await self.client.wait_for_component(components=components, timeout=60) + used_comp = await self.client.wait_for_component( + components=components, timeout=60 + ) except TimeoutError: await ctx.send("Timed out.", ephemeral=True) return @@ -195,28 +260,23 @@ class Infractions(Extension): if group != "remove-infraction" or action == "cancel": await used_comp.context.send("Cancelled.", ephemeral=True) return - + if action == "remove" and inf_id == str(infraction.id): infraction.delete_instance() await used_comp.context.send("Removed.", ephemeral=True) return - - - - def infraction_colour(w: float) -> int: if w < 0.5: return 0xBCBCBC - elif w < 1.0: + if w < 1.0: return 0xFF7711 - else: - return 0xFF2211 + + return 0xFF2211 def setup(client): InfractionsModel.create_table() Infractions(client) logging.info("Infractions extension loaded.") - diff --git a/commands/quote.py b/commands/quote.py index cf733de..6723e8e 100644 --- a/commands/quote.py +++ b/commands/quote.py @@ -1,27 +1,42 @@ -from naff import Extension, listen, slash_command, slash_option, context_menu, CommandTypes, events, InteractionContext, OptionTypes, Client -from naff.models.discord.enums import ButtonStyles, Permissions -from naff.models.discord.embed import Embed, EmbedAuthor, EmbedField, EmbedFooter -from naff.models.discord.components import ActionRow, Button - import re import logging +from naff import ( + Extension, + slash_command, + slash_option, + InteractionContext, + OptionTypes, + Client, +) +from naff.models.discord.enums import ButtonStyles, Permissions +from naff.models.discord.embed import Embed, EmbedAuthor, EmbedField +from naff.models.discord.components import ActionRow, Button + + class QuoteExtension(Extension): def __init__(self, client: Client): self.client = client @slash_command(name="quote", description="Quote a message", dm_permission=False) - @slash_option(name="url", description="Message URL", required=True, opt_type=OptionTypes.STRING) + @slash_option( + name="url", + description="Message URL", + required=True, + opt_type=OptionTypes.STRING, + ) async def quote_command(self, ctx: InteractionContext, url: str): - url_match = re.match(r"https?://discord(?:app)?\.com/channels/(\d+)/(\d+)/(\d+)", url) + url_match = re.match( + r"https?://discord(?:app)?\.com/channels/(\d+)/(\d+)/(\d+)", url + ) if url_match is None: ctx.ephemeral = True await ctx.send("Invalid URL") return - - guild_id, channel_id, message_id = url_match.groups() - + + _, channel_id, message_id = url_match.groups() + chan = await self.client.fetch_channel(channel_id) msg = await chan.fetch_message(message_id) @@ -31,27 +46,40 @@ class QuoteExtension(Extension): print(msg) return - if not (ctx.author.channel_permissions(chan) & (Permissions.VIEW_CHANNEL | Permissions.READ_MESSAGE_HISTORY)) \ - == (Permissions.VIEW_CHANNEL | Permissions.READ_MESSAGE_HISTORY): + if not ( + ctx.author.channel_permissions(chan) + & (Permissions.VIEW_CHANNEL | Permissions.READ_MESSAGE_HISTORY) + ) == (Permissions.VIEW_CHANNEL | Permissions.READ_MESSAGE_HISTORY): ctx.ephemeral = True - await ctx.send("You don't have permission to view this message", ephemeral=True) + await ctx.send( + "You don't have permission to view this message", ephemeral=True + ) return - author_embed = EmbedAuthor(name=msg.author.display_name, icon_url=msg.author.display_avatar.as_url()) + author_embed = EmbedAuthor( + name=msg.author.display_name, icon_url=msg.author.display_avatar.as_url() + ) embed = Embed( - #title=msg.author.display_name, + # title=msg.author.display_name, author=author_embed, - description=msg.content, - color=0x00ff00, - timestamp=msg.created_at, - url=url) + description=msg.content, + color=0x00FF00, + timestamp=msg.created_at, + url=url, + ) if len(msg.attachments) == 1 and msg.attachments[0].width is not None: embed.set_image(url=msg.attachments[0].url) elif len(msg.attachments) > 1: - field = EmbedField(name="**Attachments**", value="\n".join([f"• [{a.filename}]({a.url})" for a in msg.attachments])) - embed.fields.append(field) + field = EmbedField( + name="**Attachments**", + value="\n".join( + [f"• [{a.filename}]({a.url})" for a in msg.attachments] + ), + ) + embed.fields.append(field) # pylint: disable=E1101 + # pylint: disable=E1123 components: list[ActionRow] = [ ActionRow( Button( @@ -68,5 +96,3 @@ class QuoteExtension(Extension): def setup(bot): QuoteExtension(bot) logging.info("Quote extension loaded") - - diff --git a/database.py b/database.py index a198d50..00df1e1 100644 --- a/database.py +++ b/database.py @@ -1,9 +1,9 @@ -from typing import Text +import datetime + from peewee import ( SqliteDatabase, Model, BigIntegerField, - IntegerField, CharField, TextField, DateTimeField, @@ -13,7 +13,6 @@ from peewee import ( CompositeKey, ForeignKeyField, ) -import datetime db = SqliteDatabase("heimdallr.db") diff --git a/poetry.lock b/poetry.lock index 9e02ee5..e40bdeb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -29,6 +29,18 @@ python-versions = ">=3.6" [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "astroid" +version = "2.11.7" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +wrapt = ">=1.11,<2" + [[package]] name = "async-timeout" version = "4.0.2" @@ -102,6 +114,17 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "dill" +version = "0.3.5.1" +description = "serialize all of python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + [[package]] name = "discord-typings" version = "0.5.1" @@ -129,6 +152,36 @@ category = "main" optional = false python-versions = ">=3.5" +[[package]] +name = "isort" +version = "5.10.1" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.6.1,<4.0" + +[package.extras] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +requirements_deprecated_finder = ["pipreqs", "pip-api"] +colors = ["colorama (>=0.4.3,<0.5.0)"] +plugins = ["setuptools"] + +[[package]] +name = "lazy-object-proxy" +version = "1.7.1" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" + [[package]] name = "multidict" version = "6.0.2" @@ -201,6 +254,28 @@ python-versions = ">=3.7" docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] +[[package]] +name = "pylint" +version = "2.14.5" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.7.2" + +[package.dependencies] +astroid = ">=2.11.6,<=2.12.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = ">=0.2" +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + [[package]] name = "python-dotenv" version = "0.20.0" @@ -220,6 +295,14 @@ category = "main" optional = false python-versions = ">=3.7" +[[package]] +name = "tomlkit" +version = "0.11.1" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + [[package]] name = "typing-extensions" version = "4.3.0" @@ -228,6 +311,14 @@ category = "main" optional = false python-versions = ">=3.7" +[[package]] +name = "wrapt" +version = "1.14.1" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + [[package]] name = "yarl" version = "1.7.2" @@ -243,11 +334,12 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.10" -content-hash = "e627f4aee5fb3f13166070bf9a9744284a6b3e5e004838e99ff592c4cd35eda5" +content-hash = "3917de69112df241cadc7031034f6654e92f81df42f7bf627192ab88325e7e92" [metadata.files] aiohttp = [] aiosignal = [] +astroid = [] async-timeout = [] attrs = [ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, @@ -260,12 +352,16 @@ colorama = [ {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, ] +dill = [] discord-typings = [] frozenlist = [] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] +isort = [] +lazy-object-proxy = [] +mccabe = [] multidict = [ {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, @@ -333,9 +429,12 @@ orjson = [] pathspec = [] peewee = [] platformdirs = [] +pylint = [] python-dotenv = [] tomli = [] +tomlkit = [] typing-extensions = [] +wrapt = [] yarl = [ {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95"}, {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b"}, diff --git a/pyproject.toml b/pyproject.toml index 47b2af7..b4f103c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,18 @@ python-dotenv = "^0.20.0" [tool.poetry.dev-dependencies] black = "^22.6.0" +pylint = "^2.14.5" + +[tool.pylint.main] +fail-under = 8 +py-version = "3.10" + +[tool.pylint.basic] +argument-naming-style = "snake_case" +attr-naming-style = "snake_case" + +[tool.pylint."messages control"] +disable = ["C0103", "C0114", "C0115", "C0116", "R0903", "R0913"] [build-system] requires = ["poetry-core>=1.0.0"]