Merge branch 'master' of https://github.com/aveao/robocop-ng
This commit is contained in:
commit
0718b97ba9
6 changed files with 203 additions and 21 deletions
17
README.md
17
README.md
|
@ -14,13 +14,11 @@ Based on https://gitlab.com/ao/dpybotbase
|
||||||
- [x] Verification: Actual verification system
|
- [x] Verification: Actual verification system
|
||||||
- [x] Verification: Reset command
|
- [x] Verification: Reset command
|
||||||
- [ ] Verification: Using log module from akbbot for logging attempts and removing old attempts
|
- [ ] Verification: Using log module from akbbot for logging attempts and removing old attempts
|
||||||
- [ ] Logging: joins
|
- [x] Logging: joins
|
||||||
- [ ] Logging: leaves
|
- [x] Logging: leaves
|
||||||
- [ ] Logging: role changes
|
- [x] Logging: role changes
|
||||||
- [ ] Logging: message edits
|
- [x] Logging: bans
|
||||||
- [ ] Logging: message deletes
|
- [x] Logging: kicks
|
||||||
- [ ] Logging: bans
|
|
||||||
- [ ] Logging: kicks
|
|
||||||
- [x] Moderation: ban
|
- [x] Moderation: ban
|
||||||
- [x] Moderation: silentban
|
- [x] Moderation: silentban
|
||||||
- [x] Moderation: kick
|
- [x] Moderation: kick
|
||||||
|
@ -32,8 +30,8 @@ Based on https://gitlab.com/ao/dpybotbase
|
||||||
- [ ] Moderation: mute-unmute
|
- [ ] Moderation: mute-unmute
|
||||||
- [ ] Moderation: mutetime
|
- [ ] Moderation: mutetime
|
||||||
- [x] Moderation: playing
|
- [x] Moderation: playing
|
||||||
- [ ] Moderation: botnickname
|
- [x] Moderation: botnickname
|
||||||
- [ ] Moderation: nickname
|
- [x] Moderation: nickname
|
||||||
- [ ] Moderation: clear/purge
|
- [ ] Moderation: clear/purge
|
||||||
- [ ] Moderation: probate-unprobate
|
- [ ] Moderation: probate-unprobate
|
||||||
- [ ] Moderation: watch-unwatch (using log module from akbbot)
|
- [ ] Moderation: watch-unwatch (using log module from akbbot)
|
||||||
|
@ -42,6 +40,7 @@ Based on https://gitlab.com/ao/dpybotbase
|
||||||
- [ ] Warns: listwarns-listwarnsid
|
- [ ] Warns: listwarns-listwarnsid
|
||||||
- [ ] Warns: clearwarns-clearwarnsid
|
- [ ] Warns: clearwarns-clearwarnsid
|
||||||
- [ ] Modmail
|
- [ ] Modmail
|
||||||
|
- [ ] Submiterr
|
||||||
- [ ] Moderation: User notes
|
- [ ] Moderation: User notes
|
||||||
- [x] .serr and .err
|
- [x] .serr and .err
|
||||||
- [x] Meme commands and pegaswitch (honestly the easiest part)
|
- [x] Meme commands and pegaswitch (honestly the easiest part)
|
||||||
|
|
|
@ -101,7 +101,7 @@ class Common:
|
||||||
|
|
||||||
def escape_message(self, text: str):
|
def escape_message(self, text: str):
|
||||||
"""Escapes unfun stuff from messages"""
|
"""Escapes unfun stuff from messages"""
|
||||||
return text.replace("@", "@ ").replace("#", "# ")
|
return str(text).replace("@", "@ ").replace("<#", "# ")
|
||||||
|
|
||||||
# This function is based on https://stackoverflow.com/a/35435419/3286892
|
# This function is based on https://stackoverflow.com/a/35435419/3286892
|
||||||
# by link2110 (https://stackoverflow.com/users/5890923/link2110)
|
# by link2110 (https://stackoverflow.com/users/5890923/link2110)
|
||||||
|
|
150
cogs/logs.py
Normal file
150
cogs/logs.py
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
import discord
|
||||||
|
import json
|
||||||
|
from discord.ext import commands
|
||||||
|
from sys import argv
|
||||||
|
from datetime import datetime
|
||||||
|
import config
|
||||||
|
|
||||||
|
|
||||||
|
class Logs:
|
||||||
|
"""
|
||||||
|
Logs join and leave messages, bans and unbans, and member changes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
async def on_member_join(self, member):
|
||||||
|
await self.bot.wait_until_ready()
|
||||||
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
|
# We use this a lot, might as well get it once
|
||||||
|
escaped_name = self.bot.escape_message(member)
|
||||||
|
|
||||||
|
# Check if user account is older than 15 minutes
|
||||||
|
age = member.joined_at - member.created_at
|
||||||
|
if age < config.min_age:
|
||||||
|
try:
|
||||||
|
await member.send("Your account is too new to join ReSwitched."
|
||||||
|
" Please try again later.")
|
||||||
|
sent = True
|
||||||
|
except discord.errors.Forbidden:
|
||||||
|
sent = False
|
||||||
|
await member.kick(reason="Too new")
|
||||||
|
msg = f"🚨 **Account too new**: {member.mention} | "\
|
||||||
|
f"{escaped_name}\n"\
|
||||||
|
f"🗓 __Creation__: {member.created_at}\n"\
|
||||||
|
f"🕓 Account age: {age}\n"\
|
||||||
|
f"🏷 __User ID__: {member.id}"
|
||||||
|
if not sent:
|
||||||
|
msg += "\nThe user has disabled direct messages,"\
|
||||||
|
" so the reason was not sent."
|
||||||
|
await log_channel.send(msg)
|
||||||
|
return
|
||||||
|
msg = f"✅ **Join**: {member.mention} | "\
|
||||||
|
f"{escaped_name}\n"\
|
||||||
|
f"🗓 __Creation__: {member.created_at}\n"\
|
||||||
|
f"🕓 Account age: {age}\n"\
|
||||||
|
f"🏷 __User ID__: {member.id}"
|
||||||
|
|
||||||
|
# Real hell zone.
|
||||||
|
with open("data/warnsv2.json", "r") as f:
|
||||||
|
warns = json.load(f)
|
||||||
|
try:
|
||||||
|
if len(warns[member.id]["warns"]) == 0:
|
||||||
|
await log_channel.send(msg)
|
||||||
|
else:
|
||||||
|
embed = discord.Embed(color=discord.Color.dark_red(),
|
||||||
|
title=f"Warns for {escaped_name}")
|
||||||
|
embed.set_thumbnail(url=member.avatar_url)
|
||||||
|
for idx, warn in enumerate(warns[member.id]["warns"]):
|
||||||
|
embed.add_field(name=f"{idx + 1}: {warn['timestamp']}",
|
||||||
|
value=f"Issuer: {warn['issuer_name']}"
|
||||||
|
f"\nReason: {warn['reason']}")
|
||||||
|
await log_channel.send(msg, embed=embed)
|
||||||
|
except KeyError: # if the user is not in the file
|
||||||
|
await log_channel.send(msg)
|
||||||
|
|
||||||
|
async def on_member_remove(self, member):
|
||||||
|
await self.bot.wait_until_ready()
|
||||||
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
|
msg = f"⬅️ **Leave**: {member.mention} | "\
|
||||||
|
f"{self.bot.escape_message(member)}\n"\
|
||||||
|
f"🏷 __User ID__: {member.id}"
|
||||||
|
await log_channel.send(msg)
|
||||||
|
|
||||||
|
async def on_member_ban(self, member):
|
||||||
|
await self.bot.wait_until_ready()
|
||||||
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
|
msg = f"⛔ **Ban**: {member.mention} | "\
|
||||||
|
f"{self.bot.escape_message(member)}\n"\
|
||||||
|
f"🏷 __User ID__: {member.id}"
|
||||||
|
await log_channel.send(msg)
|
||||||
|
|
||||||
|
async def on_member_unban(self, server, user):
|
||||||
|
await self.bot.wait_until_ready()
|
||||||
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
|
msg = f"⚠️ **Unban**: {user.mention} | "\
|
||||||
|
f"{self.bot.escape_message(user)}\n"\
|
||||||
|
f"🏷 __User ID__: {user.id}"
|
||||||
|
# if user.id in self.bot.timebans:
|
||||||
|
# msg += "\nTimeban removed."
|
||||||
|
# self.bot.timebans.pop(user.id)
|
||||||
|
# with open("data/timebans.json", "r") as f:
|
||||||
|
# timebans = json.load(f)
|
||||||
|
# if user.id in timebans:
|
||||||
|
# timebans.pop(user.id)
|
||||||
|
# with open("data/timebans.json", "w") as f:
|
||||||
|
# json.dump(timebans, f)
|
||||||
|
await log_channel.send(msg)
|
||||||
|
|
||||||
|
async def on_member_update(self, member_before, member_after):
|
||||||
|
await self.bot.wait_until_ready()
|
||||||
|
msg = ""
|
||||||
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
|
if member_before.roles != member_after.roles:
|
||||||
|
# role removal
|
||||||
|
role_removal = []
|
||||||
|
for index, role in enumerate(member_before.roles):
|
||||||
|
if role not in member_after.roles:
|
||||||
|
role_removal.append(role)
|
||||||
|
# role addition
|
||||||
|
role_addition = []
|
||||||
|
for index, role in enumerate(member_after.roles):
|
||||||
|
if role not in member_before.roles:
|
||||||
|
role_addition.append(role)
|
||||||
|
|
||||||
|
if len(role_addition) != 0 or len(role_removal) != 0:
|
||||||
|
msg += "\n👑 __Role change__: "
|
||||||
|
roles = []
|
||||||
|
for role in role_removal:
|
||||||
|
roles.append("_~~" + role.name + "~~_")
|
||||||
|
for role in role_addition:
|
||||||
|
roles.append("__**" + role.name + "**__")
|
||||||
|
for index, role in enumerate(member_after.roles):
|
||||||
|
if role.name == "@everyone":
|
||||||
|
continue
|
||||||
|
if role not in role_removal and role not in role_addition:
|
||||||
|
roles.append(role.name)
|
||||||
|
msg += ", ".join(roles)
|
||||||
|
|
||||||
|
if member_before.name != member_after.name:
|
||||||
|
msg += "\n📝 __Username change__: "\
|
||||||
|
f"{self.bot.escape_message(member_before)} → "\
|
||||||
|
f"{self.bot.escape_message(member_after)}"
|
||||||
|
if member_before.nick != member_after.nick:
|
||||||
|
if not member_before.nick:
|
||||||
|
msg += "\n🏷 __Nickname addition__"
|
||||||
|
elif not member_after.nick:
|
||||||
|
msg += "\n🏷 __Nickname removal__"
|
||||||
|
else:
|
||||||
|
msg += "\n🏷 __Nickname change__"
|
||||||
|
msg += f": {self.bot.escape_message(member_before.nick)} → "\
|
||||||
|
f"{self.bot.escape_message(member_after.nick)}"
|
||||||
|
if msg:
|
||||||
|
msg = f"ℹ️ **Member update**: {member_after.mention} | "\
|
||||||
|
f"{self.bot.escape_message(member_after)}{msg}"
|
||||||
|
await log_channel.send(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Logs(bot))
|
40
cogs/mod.py
40
cogs/mod.py
|
@ -49,8 +49,8 @@ class ModCog:
|
||||||
", it is recommended to use `.ban <user> [reason]`"\
|
", it is recommended to use `.ban <user> [reason]`"\
|
||||||
" as the reason is automatically sent to the user."
|
" as the reason is automatically sent to the user."
|
||||||
|
|
||||||
modlog_channel = self.bot.get_channel(config.modlog_channel)
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
await modlog_channel.send(chan_message)
|
await log_channel.send(chan_message)
|
||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@commands.bot_has_permissions(ban_members=True)
|
@commands.bot_has_permissions(ban_members=True)
|
||||||
|
@ -88,8 +88,8 @@ class ModCog:
|
||||||
", it is recommended to use `.ban <user> [reason]`"\
|
", it is recommended to use `.ban <user> [reason]`"\
|
||||||
" as the reason is automatically sent to the user."
|
" as the reason is automatically sent to the user."
|
||||||
|
|
||||||
modlog_channel = self.bot.get_channel(config.modlog_channel)
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
await modlog_channel.send(chan_message)
|
await log_channel.send(chan_message)
|
||||||
await ctx.send(f"{safe_name} is now b&. 👍")
|
await ctx.send(f"{safe_name} is now b&. 👍")
|
||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
|
@ -116,8 +116,8 @@ class ModCog:
|
||||||
", it is recommended to use `.ban <user> [reason]`"\
|
", it is recommended to use `.ban <user> [reason]`"\
|
||||||
" as the reason is automatically sent to the user."
|
" as the reason is automatically sent to the user."
|
||||||
|
|
||||||
modlog_channel = self.bot.get_channel(config.modlog_channel)
|
log_channel = self.bot.get_channel(config.log_channel)
|
||||||
await modlog_channel.send(chan_message)
|
await log_channel.send(chan_message)
|
||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@commands.check(check_if_staff)
|
@commands.check(check_if_staff)
|
||||||
|
@ -142,7 +142,7 @@ class ModCog:
|
||||||
@commands.check(check_if_staff)
|
@commands.check(check_if_staff)
|
||||||
@commands.command(aliases=["setplaying", "setgame"])
|
@commands.command(aliases=["setplaying", "setgame"])
|
||||||
async def playing(self, ctx, *, game: str = ""):
|
async def playing(self, ctx, *, game: str = ""):
|
||||||
"""Sets the currently played game name, staff only.
|
"""Sets the bot's currently played game name, staff only.
|
||||||
|
|
||||||
Just send .playing to wipe the playing state."""
|
Just send .playing to wipe the playing state."""
|
||||||
if game:
|
if game:
|
||||||
|
@ -150,6 +150,32 @@ class ModCog:
|
||||||
else:
|
else:
|
||||||
await self.bot.change_presence(activity=None)
|
await self.bot.change_presence(activity=None)
|
||||||
|
|
||||||
|
@commands.guild_only()
|
||||||
|
@commands.check(check_if_staff)
|
||||||
|
@commands.command(aliases=["setbotnick", "botnick", "robotnick"])
|
||||||
|
async def botnickname(self, ctx, *, nick: str = ""):
|
||||||
|
"""Sets the bot's nickname, staff only.
|
||||||
|
|
||||||
|
Just send .botnickname to wipe the nickname."""
|
||||||
|
|
||||||
|
if nick:
|
||||||
|
await ctx.guild.me.edit(nick=nick, reason=str(ctx.author))
|
||||||
|
else:
|
||||||
|
await ctx.guild.me.edit(nick=None, reason=str(ctx.author))
|
||||||
|
|
||||||
|
@commands.guild_only()
|
||||||
|
@commands.check(check_if_staff)
|
||||||
|
@commands.command(aliases=["setnick", "nick"])
|
||||||
|
async def nickname(self, ctx, target: discord.Member, *, nick: str = ""):
|
||||||
|
"""Sets a user's nickname, staff only.
|
||||||
|
|
||||||
|
Just send .nickname <user> to wipe the nickname."""
|
||||||
|
|
||||||
|
if nick:
|
||||||
|
await target.edit(nick=nick, reason=str(ctx.author))
|
||||||
|
else:
|
||||||
|
await target.edit(nick=None, reason=str(ctx.author))
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
bot.add_cog(ModCog(bot))
|
bot.add_cog(ModCog(bot))
|
||||||
|
|
|
@ -1,28 +1,34 @@
|
||||||
|
import datetime
|
||||||
|
|
||||||
# Basic bot config
|
# Basic bot config
|
||||||
prefixes = [".", "!"]
|
prefixes = [".", "!"]
|
||||||
token = "token-goes-here"
|
token = "token-goes-here"
|
||||||
bot_description = "An attempt to rewrite the bot used in ReSwitched"
|
bot_description = "An attempt to rewrite the bot used in ReSwitched"
|
||||||
|
|
||||||
|
source_url = "https://github.com/aveao/robocop-ng"
|
||||||
|
rules_url = "https://reswitched.team/discord/"
|
||||||
|
|
||||||
# The bot description to be used in .robocop embed
|
# The bot description to be used in .robocop embed
|
||||||
embed_desc = "Robocop-NG is developed by [Ave](https://github.com/aveao)"\
|
embed_desc = "Robocop-NG is developed by [Ave](https://github.com/aveao)"\
|
||||||
" and [tomGER](https://github.com/tumGER), and is a rewrite "\
|
" and [tomGER](https://github.com/tumGER), and is a rewrite "\
|
||||||
"of Robocop.\nRobocop is based on Kurisu by 916253 and ihaveamac."
|
"of Robocop.\nRobocop is based on Kurisu by 916253 and ihaveamac."
|
||||||
|
|
||||||
|
|
||||||
|
# Minimum account age required to join the discord
|
||||||
|
min_age = datetime.timedelta(minutes=15)
|
||||||
|
|
||||||
guild_whitelist = [
|
guild_whitelist = [
|
||||||
526372255052201993, # NotSwitched discord
|
526372255052201993, # NotSwitched discord
|
||||||
269333940928512010 # ReSwitched discord
|
269333940928512010 # ReSwitched discord
|
||||||
]
|
]
|
||||||
|
|
||||||
source_url = "https://github.com/aveao/robocop-ng"
|
|
||||||
rules_url = "https://reswitched.team/discord/"
|
|
||||||
|
|
||||||
bot_manager_role_id = 526372554081042462 # Bot management role in NotSwitched
|
bot_manager_role_id = 526372554081042462 # Bot management role in NotSwitched
|
||||||
staff_role_ids = [526384077679624192, # Team role in NotSwitched
|
staff_role_ids = [526384077679624192, # Team role in NotSwitched
|
||||||
526372582455508992, # Mod role in NotSwitched
|
526372582455508992, # Mod role in NotSwitched
|
||||||
526372554081042462, # Bot management role in NotSwitched
|
526372554081042462, # Bot management role in NotSwitched
|
||||||
526383985430102016] # Wizard role in NotSwitched
|
526383985430102016] # Wizard role in NotSwitched
|
||||||
|
|
||||||
modlog_channel = 526377735908491284 # Log channel in NotSwitched
|
log_channel = 526377735908491284 # Log channel in NotSwitched
|
||||||
welcome_channel = 526372470752673792 # rules-info channel in NotSwitched
|
welcome_channel = 526372470752673792 # rules-info channel in NotSwitched
|
||||||
participant_role = 526378358129557506 # participant role in NotSwitched
|
participant_role = 526378358129557506 # participant role in NotSwitched
|
||||||
community_role = 526378381839695872 # community role in NotSwitched
|
community_role = 526378381839695872 # community role in NotSwitched
|
||||||
|
|
1
data/warnsv2.json
Normal file
1
data/warnsv2.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
Loading…
Reference in a new issue