Use reply message to target a specific member & Add aliases for macros (#26)

* Remove command message when using macros

* macro: Reply to the same message as the author invoking the command

* logfilereader: Increase size of empty logs

* meme: Add reply targets

* mod: Add reply targets

* mod_timed: Add reply targets

* macro: Add aliases for macros

* macro: Fix list_macros not listing any macros

* Apply black formatting
This commit is contained in:
TSRBerry 2023-04-02 13:56:49 +02:00 committed by GitHub
parent 9912df774d
commit 4ad2527a59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 371 additions and 67 deletions

View file

@ -227,7 +227,7 @@ class LogFileReader(Cog):
2) Ensure the following default logs are enabled: `Info`, `Warning`, `Error`, `Guest` and `Stub`.
3) Start a game up.
4) Play until your issue occurs.
5) Upload the latest log file which is larger than 2KB.""",
5) Upload the latest log file which is larger than 3KB.""",
inline=False,
)
else:

View file

@ -10,7 +10,10 @@ from robocop_ng.helpers.macros import (
add_macro,
edit_macro,
remove_macro,
get_macros,
get_macros_dict,
add_aliases,
remove_aliases,
clear_aliases,
)
@ -18,13 +21,19 @@ class Macro(Cog):
@commands.cooldown(3, 30, BucketType.member)
@commands.command(aliases=["m"])
async def macro(self, ctx: Context, target: Optional[discord.Member], key: str):
await ctx.message.delete()
if len(key) > 0:
text = get_macro(key)
if text is not None:
if target is not None:
await ctx.send(f"{target.mention}:\n{text}")
else:
await ctx.send(text)
if ctx.message.reference is not None:
await ctx.send(
text, reference=ctx.message.reference, mention_author=True
)
else:
await ctx.send(text)
else:
await ctx.send(
f"{ctx.author.mention}: The macro '{key}' doesn't exist."
@ -38,6 +47,19 @@ class Macro(Cog):
else:
await ctx.send(f"Error: Macro '{key}' already exists.")
@commands.check(check_if_staff)
@commands.command(name="aliasadd", aliases=["addalias", "add_alias"])
async def add_alias_macro(self, ctx: Context, existing_key: str, *new_keys: str):
if len(new_keys) == 0:
await ctx.send("Error: You need to add at least one alias.")
else:
if add_aliases(existing_key, list(new_keys)):
await ctx.send(
f"Added {len(new_keys)} aliases to macro '{existing_key}'!"
)
else:
await ctx.send(f"Error: No new and unique aliases found.")
@commands.check(check_if_staff)
@commands.command(name="macroedit", aliases=["me", "editmacro", "edit_macro"])
async def edit_macro(self, ctx: Context, key: str, *, text: str):
@ -46,6 +68,33 @@ class Macro(Cog):
else:
await ctx.send(f"Error: Macro '{key}' not found.")
@commands.check(check_if_staff)
@commands.command(
name="aliasremove",
aliases=[
"aliasdelete",
"delalias",
"aliasdel",
"removealias",
"remove_alias",
"delete_alias",
],
)
async def remove_alias_macro(
self, ctx: Context, existing_key: str, *remove_keys: str
):
if len(remove_keys) == 0:
await ctx.send("Error: You need to remove at least one alias.")
else:
if remove_aliases(existing_key, list(remove_keys)):
await ctx.send(
f"Removed {len(remove_keys)} aliases from macro '{existing_key}'!"
)
else:
await ctx.send(
f"Error: None of the specified aliases were found for macro '{existing_key}'."
)
@commands.check(check_if_staff)
@commands.command(
name="macroremove",
@ -65,12 +114,20 @@ class Macro(Cog):
else:
await ctx.send(f"Error: Macro '{key}' not found.")
@commands.check(check_if_staff)
@commands.command(name="aliasclear", aliases=["clearalias", "clear_alias"])
async def clear_alias_macro(self, ctx: Context, existing_key: str):
if clear_aliases(existing_key):
await ctx.send(f"Removed all aliases of macro '{existing_key}'!")
else:
await ctx.send(f"Error: No aliases found for macro '{existing_key}'.")
@commands.cooldown(3, 30, BucketType.channel)
@commands.command(name="macros", aliases=["ml", "listmacros", "list_macros"])
async def list_macros(self, ctx: Context):
macros = get_macros()
if len(macros) > 0:
macros = [f"- {key}\n" for key in sorted(macros.keys())]
macros = get_macros_dict()
if len(macros["macros"]) > 0:
macros = [f"- {key}\n" for key in sorted(macros["macros"].keys())]
message = "📝 **Macros**:\n"
for macro_key in macros:
message += macro_key
@ -78,6 +135,19 @@ class Macro(Cog):
else:
await ctx.send("Couldn't find any macros.")
@commands.cooldown(3, 30, BucketType.channel)
@commands.command(name="aliases", aliases=["listaliases", "list_aliases"])
async def list_aliases(self, ctx: Context, existing_key: str):
macros = get_macros_dict()
existing_key = existing_key.lower()
if existing_key in macros["aliases"].keys():
message = f"📝 **Aliases for '{existing_key}'**:\n"
for alias in sorted(macros["aliases"][existing_key]):
message += f"- {alias}\n"
await ctx.send(message)
else:
await ctx.send(f"Couldn't find any aliases for macro '{existing_key}'.")
async def setup(bot):
await bot.add_cog(Macro(bot))

View file

@ -2,6 +2,7 @@ import datetime
import math
import platform
import random
from typing import Optional
import discord
from discord.ext import commands
@ -28,42 +29,87 @@ class Meme(Cog):
@commands.check(check_if_staff_or_ot)
@commands.command(hidden=True, name="warm")
async def warm_member(self, ctx, user: discord.Member):
async def warm_member(self, ctx, user: Optional[discord.Member]):
"""Warms a user :3"""
celsius = random.randint(15, 100)
fahrenheit = self.c_to_f(celsius)
kelvin = self.c_to_k(celsius)
await ctx.send(
f"{user.mention} warmed."
f" User is now {celsius}°C "
f"({fahrenheit}°F, {kelvin}K)."
)
if user is None and ctx.message.reference is None:
celsius = random.randint(15, 20)
fahrenheit = self.c_to_f(celsius)
kelvin = self.c_to_k(celsius)
await ctx.send(
f"{ctx.author.mention} tries to warm themself."
f" User is now {celsius}°C "
f"({fahrenheit}°F, {kelvin}K).\n"
"You might have more success warming someone else :3"
)
else:
if user is None:
user = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
celsius = random.randint(15, 100)
fahrenheit = self.c_to_f(celsius)
kelvin = self.c_to_k(celsius)
await ctx.send(
f"{user.mention} warmed."
f" User is now {celsius}°C "
f"({fahrenheit}°F, {kelvin}K)."
)
@commands.check(check_if_staff_or_ot)
@commands.command(hidden=True, name="chill", aliases=["cold"])
async def chill_member(self, ctx, user: discord.Member):
async def chill_member(self, ctx, user: Optional[discord.Member]):
"""Chills a user >:3"""
celsius = random.randint(-50, 15)
fahrenheit = self.c_to_f(celsius)
kelvin = self.c_to_k(celsius)
await ctx.send(
f"{user.mention} chilled."
f" User is now {celsius}°C "
f"({fahrenheit}°F, {kelvin}K)."
)
if user is None and ctx.message.reference is None:
celsius = random.randint(-75, 10)
fahrenheit = self.c_to_f(celsius)
kelvin = self.c_to_k(celsius)
await ctx.send(
f"{ctx.author.mention} chills themself."
f" User is now {celsius}°C "
f"({fahrenheit}°F, {kelvin}K).\n"
"🧊 Don't be so hard on yourself. 😔"
)
else:
if user is None:
user = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
celsius = random.randint(-50, 15)
fahrenheit = self.c_to_f(celsius)
kelvin = self.c_to_k(celsius)
await ctx.send(
f"{user.mention} chilled."
f" User is now {celsius}°C "
f"({fahrenheit}°F, {kelvin}K)."
)
@commands.check(check_if_staff_or_ot)
@commands.command(hidden=True, aliases=["thank", "reswitchedgold"])
async def gild(self, ctx, user: discord.Member):
async def gild(self, ctx, user: Optional[discord.Member]):
"""Gives a star to a user"""
await ctx.send(f"{user.mention} gets a :star:, yay!")
if user is None and ctx.message.reference is None:
await ctx.send(f"No stars for you, {ctx.author.mention}!")
else:
if user is None:
user = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
await ctx.send(f"{user.mention} gets a :star:, yay!")
@commands.check(check_if_staff_or_ot)
@commands.command(
hidden=True, aliases=["reswitchedsilver", "silv3r", "reswitchedsilv3r"]
)
async def silver(self, ctx, user: discord.Member):
async def silver(self, ctx, user: Optional[discord.Member]):
"""Gives a user ReSwitched Silver™"""
if user is None and ctx.message.reference is None:
await ctx.send(f"{ctx.author.mention}, you can't reward yourself.")
else:
if user is None:
user = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
embed = discord.Embed(
title="ReSwitched Silver™!",
description=f"Here's your ReSwitched Silver™," f"{user.mention}!",
@ -131,23 +177,30 @@ class Meme(Cog):
@commands.check(check_if_staff_or_ot)
@commands.command(hidden=True, name="bam")
async def bam_member(self, ctx, target: discord.Member):
async def bam_member(self, ctx, target: Optional[discord.Member]):
"""Bams a user owo"""
if target == ctx.author:
if target.id == 181627658520625152:
if target is None and ctx.message.reference is None:
await ctx.reply("https://tenor.com/view/bonk-gif-26414884")
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
if target == ctx.author:
if target.id == 181627658520625152:
return await ctx.send(
"https://cdn.discordapp.com/attachments/286612533757083648/403080855402315796/rehedge.PNG"
)
return await ctx.send("hedgeberg#7337 is ̶n͢ow b̕&̡.̷ 👍̡")
elif target == self.bot.user:
return await ctx.send(
"https://cdn.discordapp.com/attachments/286612533757083648/403080855402315796/rehedge.PNG"
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
return await ctx.send("hedgeberg#7337 is ̶n͢ow b̕&̡.̷ 👍̡")
elif target == self.bot.user:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
safe_name = await commands.clean_content(escape_markdown=True).convert(
ctx, str(target)
)
await ctx.send(f"{safe_name} is ̶n͢ow b̕&̡.̷ 👍̡")
safe_name = await commands.clean_content(escape_markdown=True).convert(
ctx, str(target)
)
await ctx.send(f"{safe_name} is ̶n͢ow b̕&̡.̷ 👍̡")
@commands.command(hidden=True)
async def memebercount(self, ctx):

View file

@ -1,4 +1,5 @@
import io
from typing import Optional
import discord
from discord.ext import commands
@ -38,8 +39,17 @@ class Mod(Cog):
@commands.guild_only()
@commands.check(check_if_staff)
@commands.command()
async def mute(self, ctx, target: discord.Member, *, reason: str = ""):
async def mute(self, ctx, target: Optional[discord.Member], *, reason: str = ""):
"""Mutes a user, staff only."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
# Hedge-proofing the code
if target == ctx.author:
return await ctx.send("You can't do mod actions on yourself.")
@ -123,8 +133,17 @@ class Mod(Cog):
@commands.bot_has_permissions(kick_members=True)
@commands.check(check_if_staff)
@commands.command()
async def kick(self, ctx, target: discord.Member, *, reason: str = ""):
async def kick(self, ctx, target: Optional[discord.Member], *, reason: str = ""):
"""Kicks a user, staff only."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
# Hedge-proofing the code
if target == ctx.author:
return await ctx.send("You can't do mod actions on yourself.")
@ -184,8 +203,17 @@ class Mod(Cog):
@commands.bot_has_permissions(ban_members=True)
@commands.check(check_if_staff)
@commands.command(aliases=["yeet"])
async def ban(self, ctx, target: discord.Member, *, reason: str = ""):
async def ban(self, ctx, target: Optional[discord.Member], *, reason: str = ""):
"""Bans a user, staff only."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
# Hedge-proofing the code
if target == ctx.author:
if target.id == 181627658520625152:
@ -246,9 +274,18 @@ class Mod(Cog):
@commands.check(check_if_staff)
@commands.command()
async def bandel(
self, ctx, day_count: int, target: discord.Member, *, reason: str = ""
self, ctx, day_count: int, target: Optional[discord.Member], *, reason: str = ""
):
"""Bans a user for a given number of days, staff only."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
# Hedge-proofing the code
if target == ctx.author:
if target.id == 181627658520625152:
@ -488,13 +525,25 @@ class Mod(Cog):
@commands.guild_only()
@commands.check(check_if_staff)
@commands.command()
async def approve(self, ctx, target: discord.Member, role: str = "community"):
async def approve(
self, ctx, target: Optional[discord.Member], role: str = "community"
):
"""Add a role to a user (default: community), staff only."""
if role not in config.named_roles:
return await ctx.send(
"No such role! Available roles: " + ",".join(config.named_roles)
)
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
log_channel = self.bot.get_channel(config.modlog_channel)
target_role = ctx.guild.get_role(config.named_roles[role])
@ -514,13 +563,25 @@ class Mod(Cog):
@commands.guild_only()
@commands.check(check_if_staff)
@commands.command(aliases=["unapprove"])
async def revoke(self, ctx, target: discord.Member, role: str = "community"):
async def revoke(
self, ctx, target: Optional[discord.Member], role: str = "community"
):
"""Remove a role from a user (default: community), staff only."""
if role not in config.named_roles:
return await ctx.send(
"No such role! Available roles: " + ",".join(config.named_roles)
)
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
log_channel = self.bot.get_channel(config.modlog_channel)
target_role = ctx.guild.get_role(config.named_roles[role])
@ -555,8 +616,17 @@ class Mod(Cog):
@commands.guild_only()
@commands.check(check_if_staff)
@commands.command()
async def warn(self, ctx, target: discord.Member, *, reason: str = ""):
async def warn(self, ctx, target: Optional[discord.Member], *, reason: str = ""):
"""Warns a user, staff only."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
# Hedge-proofing the code
if target == ctx.author:
return await ctx.send("You can't do mod actions on yourself.")
@ -631,10 +701,19 @@ class Mod(Cog):
@commands.guild_only()
@commands.check(check_if_staff)
@commands.command(aliases=["setnick", "nick"])
async def nickname(self, ctx, target: discord.Member, *, nick: str = ""):
async def nickname(self, ctx, target: Optional[discord.Member], *, nick: str = ""):
"""Sets a user's nickname, staff only.
Just send .nickname <user> to wipe the nickname."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
try:
if nick:

View file

@ -1,4 +1,5 @@
from datetime import datetime
from typing import Optional
import discord
from discord.ext import commands
@ -23,9 +24,18 @@ class ModTimed(Cog):
@commands.check(check_if_staff)
@commands.command()
async def timeban(
self, ctx, target: discord.Member, duration: str, *, reason: str = ""
self, ctx, target: Optional[discord.Member], duration: str, *, reason: str = ""
):
"""Bans a user for a specified amount of time, staff only."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
# Hedge-proofing the code
if target == ctx.author:
return await ctx.send("You can't do mod actions on yourself.")
@ -89,9 +99,18 @@ class ModTimed(Cog):
@commands.check(check_if_staff)
@commands.command()
async def timemute(
self, ctx, target: discord.Member, duration: str, *, reason: str = ""
self, ctx, target: Optional[discord.Member], duration: str, *, reason: str = ""
):
"""Mutes a user for a specified amount of time, staff only."""
if target is None and ctx.message.reference is None:
return await ctx.send(
f"I'm sorry {ctx.author.mention}, I'm afraid I can't do that."
)
else:
if target is None:
target = ctx.channel.fetch_message(
ctx.message.reference.message_id
).author
# Hedge-proofing the code
if target == ctx.author:
return await ctx.send("You can't do mod actions on yourself.")

View file

@ -1,55 +1,138 @@
import json
import os
from typing import Optional
from typing import Optional, Union
MACROS_FILE = "data/macros.json"
def get_macros() -> dict[str, str]:
def get_macros_dict() -> dict[str, dict[str, Union[list[str], str]]]:
if os.path.isfile(MACROS_FILE):
with open(MACROS_FILE, "r") as f:
return json.load(f)
return {}
macros = json.load(f)
# Migration code
if "aliases" not in macros.keys():
new_macros = {"macros": macros, "aliases": {}}
unique_macros = set(new_macros["macros"].values())
for macro_text in unique_macros:
first_macro_key = ""
duplicate_num = 0
for key, macro in new_macros["macros"].copy().items():
if macro == macro_text and duplicate_num == 0:
first_macro_key = key
duplicate_num += 1
continue
elif macro == macro_text:
if first_macro_key not in new_macros["aliases"].keys():
new_macros["aliases"][first_macro_key] = []
new_macros["aliases"][first_macro_key].append(key)
del new_macros["macros"][key]
duplicate_num += 1
set_macros(new_macros)
return new_macros
return macros
return {"macros": {}, "aliases": {}}
def set_macros(contents: dict[str, str]):
def is_macro_key_available(
key: str, macros: dict[str, dict[str, Union[list[str], str]]] = None
) -> bool:
if macros is None:
macros = get_macros_dict()
if key in macros["macros"].keys():
return False
for aliases in macros["aliases"].values():
if key in aliases:
return False
return True
def set_macros(contents: dict[str, dict[str, Union[list[str], str]]]):
with open(MACROS_FILE, "w") as f:
json.dump(contents, f)
def get_macro(key: str) -> Optional[str]:
macros = get_macros()
macros = get_macros_dict()
key = key.lower()
if key in macros.keys():
return macros[key]
if key in macros["macros"].keys():
return macros["macros"][key]
for main_key, aliases in macros["aliases"].items():
if key in aliases:
return macros["macros"][main_key]
return None
def add_macro(key: str, message: str) -> bool:
macros = get_macros()
macros = get_macros_dict()
key = key.lower()
if key not in macros.keys():
macros[key] = message
if is_macro_key_available(key, macros):
macros["macros"][key] = message
set_macros(macros)
return True
return False
def add_aliases(key: str, aliases: list[str]) -> bool:
macros = get_macros_dict()
key = key.lower()
success = False
if key in macros["macros"].keys():
for alias in aliases:
alias = alias.lower()
if is_macro_key_available(alias, macros):
macros["aliases"][key].append(alias)
success = True
if success:
set_macros(macros)
return success
def edit_macro(key: str, message: str) -> bool:
macros = get_macros()
macros = get_macros_dict()
key = key.lower()
if key in macros.keys():
macros[key] = message
if key in macros["macros"].keys():
macros["macros"][key] = message
set_macros(macros)
return True
return False
def remove_aliases(key: str, aliases: list[str]) -> bool:
macros = get_macros_dict()
key = key.lower()
success = False
if key not in macros["aliases"].keys():
return False
for alias in aliases:
alias = alias.lower()
if alias in macros["aliases"][key]:
macros["aliases"][key].remove(alias)
if len(macros["aliases"][key]) == 0:
del macros["aliases"][key]
success = True
if success:
set_macros(macros)
return success
def remove_macro(key: str) -> bool:
macros = get_macros()
macros = get_macros_dict()
key = key.lower()
if key in macros.keys():
del macros[key]
if key in macros["macros"].keys():
del macros["macros"][key]
set_macros(macros)
return True
return False
def clear_aliases(key: str) -> bool:
macros = get_macros_dict()
key = key.lower()
if key in macros["macros"].keys() and key in macros["aliases"].keys():
del macros["aliases"][key]
set_macros(macros)
return True
return False