initial commit.

This commit is contained in:
Seraphim R. Pardee 2024-01-17 00:20:44 -05:00
commit df167f832c
33 changed files with 4105 additions and 0 deletions

48
README Normal file
View File

@ -0,0 +1,48 @@
diakonos
========
diakonos is a repository of in-house cogs for self-hosted RedBot instances. It gets its name from the Greek word for "deacon", "διάκονος."
Requirements
------------
diakonos has been tested and modified to ensure compatibility with:
- Python 3.11
- Red-DiscordBot 3.5.5
diakonos requires the following Python packages:
- feedparser
- beautifulsoup4
Installation
------------
For feature parity with our instances, the following internal RedBot cogs need to be enabled with the following command:
```
.load admin alias cleanup customcom downloader economy general mod modlog mutes trivia warnings
```
The following cogs from the following sources:
- `avatar` from https://github.com/skeith/MayuYukirin
- `compliment` from https://github.com/TrustyJAID/Trusty-cogs
- `dictionary` from https://github.com/aikaterna/aikaterna-cogs
- `disboardreminder` from https://github.com/phenom4n4n/phen-cogs
- `errorlogs` from https://github.com/Tobotimus/Tobo-Cogs
- `extendedmodlog` from https://github.com/TrustyJAID/Trusty-cogs
- `forcemention` from https://github.com/phenom4n4n/phen-cogs
- `hangman` from https://github.com/Flame442/FlameCogs
- `hunting` from https://github.com/vertyco/vrt-cogs
- `levelup` from https://github.com/vertyco/vrt-cogs
- `msgvote` from https://github.com/flapjax/FlapJack-Cogs
- `reactpoll` from https://github.com/flapjax/FlapJack-Cogs
- `rekt` from https://github.com/TrustyJAID/Trusty-cogs
- `remindme` from https://github.com/PhasecoreX/PCXCogs
- `say` from https://github.com/laggron42/Laggrons-Dumb-Cogs
- `seen` from https://github.com/aikaterna/aikaterna-cogs
- `smartreact` from https://github.com/flapjax/FlapJack-Cogs
- `starboard` from https://github.com/TrustyJAID/Trusty-cogs
- `userinfo` from https://github.com/flaree/flare-cogs
- `uwu` from https://github.com/PhasecoreX/PCXCogs
- `wikipedia` from https://github.com/PhasecoreX/PCXCogs
For the remaining cogs, provided within this repository:
```
.load autorole cherubim reactrole rss stickyroles
```

19
autorole/LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2017 TrustyJAID
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

14
autorole/__init__.py Normal file
View File

@ -0,0 +1,14 @@
import json
from pathlib import Path
from .autorole import Autorole
with open(Path(__file__).parent / "info.json") as fp:
__red_end_user_data_statement__ = json.load(fp)["end_user_data_statement"]
def setup(bot):
n = Autorole(bot)
bot.add_cog(n)
# bot.add_listener(n._roler, "on_member_join")
# bot.add_listener(n._verify_json, "on_error")

470
autorole/autorole.py Normal file
View File

@ -0,0 +1,470 @@
import logging
import random
import string
from typing import Optional, cast
import discord
from redbot import VersionInfo, version_info
from redbot.core import Config, checks, commands
from redbot.core.i18n import Translator, cog_i18n
default_settings = {
"ENABLED": False,
"ROLE": [],
"AGREE_CHANNEL": None,
"AGREE_MSG": None,
"AGREE_KEY": None,
"DELETE_KEY": False,
}
log = logging.getLogger("red.Trusty-cogs.autorole")
_ = Translator("Autorole", __file__)
listener = getattr(commands.Cog, "listener", None) # red 3.0 backwards compatibility support
if listener is None: # thanks Sinbad
def listener(name=None):
return lambda x: x
@cog_i18n(_)
class Autorole(commands.Cog):
"""
Autorole commands. Rewritten for V3 from
https://github.com/Lunar-Dust/Dusty-Cogs/blob/master/autorole/autorole.py
"""
__author__ = ["Lunar-Dust", "TrustyJAID"]
__version__ = "1.3.2"
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, 45463543548)
self.config.register_guild(**default_settings)
self.users = {}
def format_help_for_context(self, ctx: commands.Context) -> str:
"""
Thanks Sinbad!
"""
pre_processed = super().format_help_for_context(ctx)
return f"{pre_processed}\n\nCog Version: {self.__version__}"
async def red_delete_data_for_user(self, **kwargs):
"""
Nothing to delete
"""
return
async def _no_perms(self, channel: Optional[discord.TextChannel] = None) -> None:
m = _(
"It appears that you haven't given this "
"bot enough permissions to use autorole. "
'The bot requires the "Manage Roles" and '
'the "Manage Messages" permissions in'
"order to use autorole. You can change the "
'permissions in the "Roles" tab of the '
"guild settings."
)
if channel is None:
log.info(m)
return
if channel.permissions_for(channel.guild.me).send_messages:
await channel.send(m)
else:
log.info(m + _("\n I also don't have permission to speak in #") + channel.name)
async def get_colour(self, channel: discord.TextChannel) -> discord.Colour:
try:
return await self.bot.get_embed_colour(channel)
except AttributeError:
if await self.bot.db.guild(channel.guild).use_bot_color():
return channel.guild.me.colour
else:
return await self.bot.db.color()
@commands.Cog.listener()
async def on_message(self, message: discord.Message) -> None:
guild = message.guild
if not guild:
return
if version_info >= VersionInfo.from_str("3.4.0"):
if await self.bot.cog_disabled_in_guild(self, guild):
return
user = cast(discord.Member, message.author)
channel = message.channel
agree_channel = cast(
discord.TextChannel, guild.get_channel(await self.config.guild(guild).AGREE_CHANNEL())
)
if guild is None:
return
if agree_channel is None:
return
if channel.id != agree_channel.id:
return
if user.bot:
return
if user.id in self.users:
if not guild.me.guild_permissions.manage_roles:
await self._no_perms(agree_channel)
return
if self.users[user.id]["key"].lower() in message.content.lower():
perms = agree_channel.permissions_for(guild.me)
roles_id = await self.config.guild(guild).ROLE()
roles = [role for role in guild.roles if role.id in roles_id]
for role in roles:
await user.add_roles(role, reason=_("Agreed to the rules"))
if perms.manage_messages and await self.config.guild(guild).DELETE_KEY():
try:
await message.delete()
except Exception:
pass
if self.users[user.id]["message"].guild:
try:
await self.users[user.id]["message"].delete()
except Exception:
pass
elif perms.add_reactions:
await message.add_reaction("")
del self.users[user.id]
async def _agree_maker(self, member: discord.Member) -> None:
guild = member.guild
self.last_guild = guild
# await self._verify_json(None)
key = await self.config.guild(guild).AGREE_KEY()
if key is None:
key = "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
# <3 Stackoverflow http://stackoverflow.com/questions/2257441/random-string-generation-with-upper-case-letters-and-digits-in-python/23728630#23728630
ch = cast(
discord.TextChannel, guild.get_channel(await self.config.guild(guild).AGREE_CHANNEL())
)
msg = await self.config.guild(guild).AGREE_MSG()
if msg is None:
msg = "{mention} please enter {key} in {channel}"
try:
msg = msg.format(
key=key,
member=member,
name=member.name,
mention=member.mention,
guild=guild.name,
channel=ch.mention,
)
except Exception:
log.error("Error formatting agreement message", exc_info=True)
try:
msg = await member.send(msg)
except discord.Forbidden:
msg = await ch.send(msg)
except discord.HTTPException:
return
self.users[member.id] = {"key": key, "message": msg}
async def _auto_give(self, member: discord.Member) -> None:
guild = member.guild
roles_id = await self.config.guild(guild).ROLE()
roles = [role for role in guild.roles if role.id in roles_id]
if not guild.me.guild_permissions.manage_roles:
await self._no_perms()
return
for role in roles:
await member.add_roles(role, reason=_("Joined the server"))
@commands.Cog.listener()
async def on_member_join(self, member: discord.Member) -> None:
if "h0nde" in member.name or "h0nda" in member.name:
await member.ban(reason="Anti-spam measure.")
guild = member.guild
if await self.config.guild(guild).ENABLED():
if await self.config.guild(guild).AGREE_CHANNEL() is not None:
await self._agree_maker(member)
elif member.guild.name != "BibleBot": # Immediately give the new user the role
await self._auto_give(member)
@commands.Cog.listener()
async def on_member_update(self, before: discord.Member, after: discord.Member) -> None:
if before.guild.name == "BibleBot":
if before.pending == True and after.pending == False:
await after.add_roles(before.guild.get_role(366901317924290562))
@commands.guild_only()
@commands.group(name="autorole")
@commands.bot_has_permissions(manage_roles=True)
async def autorole(self, ctx: commands.Context) -> None:
"""
Change settings for autorole
Requires the manage roles permission
"""
pass
@autorole.command(name="info")
async def autorole_info(self, ctx: commands.Context) -> None:
"""
Display current autorole info
"""
guild = ctx.message.guild
enabled = await self.config.guild(guild).ENABLED()
roles = await self.config.guild(guild).ROLE()
msg = await self.config.guild(guild).AGREE_MSG()
key = await self.config.guild(guild).AGREE_KEY()
ch_id = await self.config.guild(guild).AGREE_CHANNEL()
delete = await self.config.guild(guild).DELETE_KEY()
channel = guild.get_channel(ch_id)
chn_name = channel.name if channel is not None else "None"
chn_mention = channel.mention if channel is not None else "None"
role_name_str = ", ".join(role.mention for role in guild.roles if role.id in roles)
if not role_name_str:
role_name_str = "None"
if ctx.channel.permissions_for(ctx.me).embed_links:
embed = discord.Embed(colour=await self.get_colour(ctx.channel))
embed.set_author(name=_("Autorole settings for ") + guild.name)
embed.add_field(name=_("Current autorole state: "), value=str(enabled))
embed.add_field(name=_("Current Roles: "), value=str(role_name_str))
if msg:
embed.add_field(name=_("Agreement message: "), value=str(msg))
if key:
embed.add_field(name=_("Agreement key: "), value=str(key))
if channel:
embed.add_field(name=_("Agreement channel: "), value=str(chn_mention))
await ctx.send(embed=embed)
else:
send_msg = (
"```"
+ _("Current autorole state: ")
+ f"{enabled}\n"
+ _("Current Roles: ")
+ f"{role_name_str}\n"
+ _("Agreement message: ")
+ f"{msg}\n"
+ _("Agreement key: ")
+ f"{key}\n"
+ _("Delete Agreement: ")
+ f"{delete}\n"
+ _("Agreement channel: ")
+ f"{chn_name}"
+ "```"
)
await ctx.send(send_msg)
@autorole.command()
@checks.admin_or_permissions(manage_roles=True)
async def toggle(self, ctx: commands.Context) -> None:
"""
Enables/Disables autorole
"""
guild = ctx.message.guild
if await self.config.guild(guild).ROLE() is None:
msg = _("You haven't set a " "role to give to new users!")
await ctx.send(msg)
else:
if await self.config.guild(guild).ENABLED():
await self.config.guild(guild).ENABLED.set(False)
await ctx.send(_("Autorole is now disabled."))
else:
await self.config.guild(guild).ENABLED.set(True)
await ctx.send(_("Autorole is now enabled."))
@autorole.command(name="add", aliases=["role"])
@checks.admin_or_permissions(manage_roles=True)
async def role(self, ctx: commands.Context, *, role: discord.Role) -> None:
"""
Add a role for autorole to assign.
You can use this command multiple times to add multiple roles.
"""
guild = ctx.message.guild
roles = await self.config.guild(guild).ROLE()
if ctx.author.top_role < role:
msg = _(
" is higher than your highest role. "
"You can't assign autoroles higher than your own"
)
await ctx.send(role.name + msg)
if role.id in roles:
await ctx.send(role.name + _(" is already in the autorole list."))
return
if guild.me.top_role < role:
msg = _(" is higher than my highest role" " in the Discord hierarchy.")
await ctx.send(role.name + msg)
return
roles.append(role.id)
await self.config.guild(guild).ROLE.set(roles)
await ctx.send(role.name + _(" role added to the autorole."))
@autorole.command()
@checks.admin_or_permissions(manage_roles=True)
async def remove(self, ctx: commands.Context, *, role: discord.Role) -> None:
"""
Remove a role from the autorole.
"""
guild = ctx.message.guild
roles = await self.config.guild(guild).ROLE()
if role.id not in roles:
await ctx.send(role.name + _(" is not in the autorole list."))
return
roles.remove(role.id)
await self.config.guild(guild).ROLE.set(roles)
await ctx.send(role.name + _(" role removed from the autorole."))
@autorole.group()
@checks.admin_or_permissions(manage_roles=True)
async def agreement(self, ctx: commands.Context) -> None:
"""
Set the channel and message that will be used for accepting the rules.
`channel` is the channel they must type the key in to get the role.
`key` is the message they must type to gain access and must be in quotes.
`msg` is the message DM'd to them when they join.
`{key}` must be included in the message so a user knows what to type in the channel.
Optional additions to the message include:
`{channel}` Mentions the channel where they must include the agreement message.
`{mention}` Mentions the user incase they have DM permissions turned off this should be used.
`{name}` Says the member name if you don't want to ping them.
`{guild}` Says the servers current name.
Entering nothing will disable these.
"""
pass
@agreement.command(name="channel")
@checks.admin_or_permissions(manage_roles=True)
async def set_agreement_channel(
self, ctx: commands.Context, channel: discord.TextChannel = None
) -> None:
"""
Set the agreement channel
Entering nothing will clear this.
"""
guild = ctx.message.guild
if await self.config.guild(guild).ROLE() == []:
await ctx.send(_("No roles have been set for autorole."))
return
if not await self.config.guild(guild).ENABLED():
await ctx.send(_("Autorole has been disabled, enable it first."))
return
if channel is None:
await self.config.guild(guild).AGREE_CHANNEL.set(None)
await ctx.send(_("Agreement channel cleared"))
else:
await self.config.guild(guild).AGREE_CHANNEL.set(channel.id)
await ctx.send(_("Agreement channel set to ") + channel.mention)
@agreement.command(name="delete")
@checks.admin_or_permissions(manage_roles=True)
async def set_agreement_delete(self, ctx: commands.Context) -> None:
"""
Toggle automatically deleting the agreement message.
"""
delete_key = await self.config.guild(ctx.guild).DELETE_KEY()
await self.config.guild(ctx.guild).DELETE_KEY.set(not delete_key)
if delete_key:
await ctx.send(_("No longer automatically deleting agreement key."))
else:
await ctx.send(_("Automatically deleting agreement key."))
@agreement.command(name="key")
@checks.admin_or_permissions(manage_roles=True)
async def set_agreement_key(self, ctx: commands.Context, *, key: str = None) -> None:
"""
Set the agreement key
Entering nothing will clear this.
"""
guild = ctx.message.guild
if await self.config.guild(guild).ROLE() == []:
await ctx.send(_("No roles have been set for autorole."))
return
if not await self.config.guild(guild).ENABLED():
await ctx.send(_("Autorole has been disabled, enable it first."))
return
if key is None:
await self.config.guild(guild).AGREE_KEY.set(None)
await ctx.send(_("Agreement key cleared"))
else:
await self.config.guild(guild).AGREE_KEY.set(key)
await ctx.send(_("Agreement key set to ") + key)
@agreement.command(name="message", aliases=["msg"])
@checks.admin_or_permissions(manage_roles=True)
async def set_agreement_msg(self, ctx: commands.Context, *, message: str = None) -> None:
"""
Set the agreement message
`{key}` must be included in the message so a user knows what to type in the channel.
Optional additions to the message include:
`{channel}` Mentions the channel where they must include the agreement message.
`{mention}` Mentions the user incase they have DM permissions turned off this should be used.
`{name}` Says the member name if you don't want to ping them.
`{guild}` Says the servers current name.
Entering nothing will clear this.
"""
guild = ctx.message.guild
if await self.config.guild(guild).ROLE() == []:
await ctx.send(_("No roles have been set for autorole."))
return
if not await self.config.guild(guild).ENABLED():
await ctx.send(_("Autorole has been disabled, enable it first."))
return
if message is None:
await self.config.guild(guild).AGREE_MSG.set(None)
await ctx.send(_("Agreement message cleared"))
else:
await self.config.guild(guild).AGREE_MSG.set(message)
await ctx.send(_("Agreement message set to ") + message)
@agreement.command(name="setup")
@checks.admin_or_permissions(manage_roles=True)
async def agreement_setup(
self,
ctx: commands.Context,
channel: discord.TextChannel = None,
key: str = None,
*,
msg: str = None,
) -> None:
"""
Set the channel and message that will be used for accepting the rules.
`channel` is the channel they must type the key in to get the role.
`key` is the message they must type to gain access and must be in quotes.
`msg` is the message DM'd to them when they join.
`{key}` must be included in the message so a user knows what to type in the channel.
Optional additions to the message include:
`{channel}` Mentions the channel where they must include the agreement message.
`{mention}` Mentions the user incase they have DM permissions turned off this should be used.
`{name}` Says the member name if you don't want to ping them.
`{guild}` Says the servers current name.
Entering nothing will disable this.
"""
guild = ctx.message.guild
if await self.config.guild(guild).ROLE() == []:
await ctx.send(_("No roles have been set for autorole."))
return
if not await self.config.guild(guild).ENABLED():
await ctx.send(_("Autorole has been disabled, enable it first."))
return
if channel is None:
await self.config.guild(guild).AGREE_CHANNEL.set(None)
await self.config.guild(guild).AGREE_MSG.set(None)
await self.config.guild(guild).AGREE_KEY.set(None)
await ctx.send(_("Agreement channel cleared"))
else:
await self.config.guild(guild).AGREE_CHANNEL.set(channel.id)
await self.config.guild(guild).AGREE_MSG.set(msg)
await self.config.guild(guild).AGREE_KEY.set(key)
await ctx.send(_("Agreement channel set to ") + channel.mention)

27
autorole/info.json Normal file
View File

@ -0,0 +1,27 @@
{
"author" : [
"Lunar Dust",
"TrustyJAID"
],
"description" : "Automatically apply roles when a user joins the server.",
"disabled" : false,
"end_user_data_statement" : "This cog does not persistently store data or metadata about users.",
"hidden" : true,
"install_msg" : "Thanks for installing.",
"max_bot_version" : "0.0.0",
"min_bot_version" : "3.1.8",
"min_python_version" : [
3,
7,
2
],
"name" : "Autorole",
"permissions" : [
"manage_roles"
],
"required_cogs" : {},
"requirements" : [],
"short" : "Automatically apply a role to new users",
"tags" : [],
"type" : "COG"
}

View File

@ -0,0 +1,249 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2018-12-20 10:32-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: redgettext 2.1\n"
#: autorole.py:20
#, docstring
msgid ""
"\n"
" Autorole commands. Rewritten for V3 from \n"
" https://github.com/Lunar-Dust/Dusty-Cogs/blob/master/autorole/autorole.py\n"
" "
msgstr ""
#: autorole.py:32
msgid "It appears that you haven't given this bot enough permissions to use autorole. The bot requires the \"Manage Roles\" and the \"Manage Messages\" permissions inorder to use autorole. You can change the permissions in the \"Roles\" tab of the guild settings."
msgstr ""
#: autorole.py:45
msgid ""
"\n"
" I also don't have permission to speak in #"
msgstr ""
#: autorole.py:79
msgid "Agreed to the rules"
msgstr ""
#: autorole.py:125
msgid "Joined the server"
msgstr ""
#: autorole.py:139
#, docstring
msgid ""
"\n"
" Change settings for autorole\n"
"\n"
" Requires the manage roles permission\n"
" "
msgstr ""
#: autorole.py:159
msgid "Autorole settings for "
msgstr ""
#: autorole.py:160 autorole.py:172
msgid "Current autorole state: "
msgstr ""
#: autorole.py:161 autorole.py:173
msgid "Current Roles: "
msgstr ""
#: autorole.py:163 autorole.py:174
msgid "Agreement message: "
msgstr ""
#: autorole.py:165 autorole.py:175
msgid "Agreement key: "
msgstr ""
#: autorole.py:167 autorole.py:176
msgid "Agreement channel: "
msgstr ""
#: autorole.py:183
#, docstring
msgid ""
"\n"
" Enables/Disables autorole\n"
" "
msgstr ""
#: autorole.py:188
msgid "You haven't set a role to give to new users!"
msgstr ""
#: autorole.py:194
msgid "Autorole is now disabled."
msgstr ""
#: autorole.py:197
msgid "Autorole is now enabled."
msgstr ""
#: autorole.py:202
#, docstring
msgid ""
"\n"
" Add a role for autorole to assign.\n"
" \n"
" You can use this command multiple times to add multiple roles.\n"
" "
msgstr ""
#: autorole.py:210
msgid " is higher than your highest role. You can't assign autoroles higher than your own"
msgstr ""
#: autorole.py:214
msgid " is already in the autorole list."
msgstr ""
#: autorole.py:217
msgid " is higher than my highest role in the Discord hierarchy."
msgstr ""
#: autorole.py:223
msgid " role added to the autorole."
msgstr ""
#: autorole.py:228
#, docstring
msgid ""
"\n"
" Remove a role from the autorole.\n"
" "
msgstr ""
#: autorole.py:234
msgid " is not in the autorole list."
msgstr ""
#: autorole.py:238
msgid " role removed from the autorole."
msgstr ""
#: autorole.py:244
#, docstring
msgid ""
"\n"
" Set the channel and message that will be used for accepting the rules.\n"
" \n"
" `channel` is the channel they must type the key in to get the role.\n"
" `key` is the message they must type to gain access and must be in quotes.\n"
" `msg` is the message DM'd to them when they join.\n"
"\n"
" `{key}` must be included in the message so a user knows what to type in the channel.\n"
" \n"
" Optional additions to the message include:\n"
" `{channel}` Mentions the channel where they must include the agreement message.\n"
" `{mention}` Mentions the user incase they have DM permissions turned off this should be used.\n"
" `{name}` Says the member name if you don't want to ping them.\n"
" `{guild}` Says the servers current name.\n"
" \n"
" Entering nothing will disable these.\n"
" "
msgstr ""
#: autorole.py:269
#, docstring
msgid ""
"\n"
" Set the agreement channel\n"
"\n"
" Entering nothing will clear this.\n"
" "
msgstr ""
#: autorole.py:276 autorole.py:299 autorole.py:328 autorole.py:367
msgid "No roles have been set for autorole."
msgstr ""
#: autorole.py:279 autorole.py:302 autorole.py:331 autorole.py:370
msgid "Autorole has been disabled, enable it first."
msgstr ""
#: autorole.py:283 autorole.py:376
msgid "Agreement channel cleared"
msgstr ""
#: autorole.py:286 autorole.py:381
msgid "Agreement channel set to "
msgstr ""
#: autorole.py:291
#, docstring
msgid ""
"\n"
" Set the agreement key\n"
"\n"
" Entering nothing will clear this.\n"
" "
msgstr ""
#: autorole.py:306
msgid "Agreement key cleared"
msgstr ""
#: autorole.py:309 autorole.py:338
msgid "Agreement key set to "
msgstr ""
#: autorole.py:314
#, docstring
msgid ""
"\n"
" Set the agreement message\n"
" `{key}` must be included in the message so a user knows what to type in the channel.\n"
"\n"
" Optional additions to the message include:\n"
" `{channel}` Mentions the channel where they must include the agreement message.\n"
" `{mention}` Mentions the user incase they have DM permissions turned off this should be used.\n"
" `{name}` Says the member name if you don't want to ping them.\n"
" `{guild}` Says the servers current name.\n"
"\n"
" Entering nothing will clear this.\n"
" "
msgstr ""
#: autorole.py:335
msgid "Agreement message cleared"
msgstr ""
#: autorole.py:348
#, docstring
msgid ""
"\n"
" Set the channel and message that will be used for accepting the rules.\n"
" \n"
" `channel` is the channel they must type the key in to get the role.\n"
" `key` is the message they must type to gain access and must be in quotes.\n"
" `msg` is the message DM'd to them when they join.\n"
"\n"
" `{key}` must be included in the message so a user knows what to type in the channel.\n"
" \n"
" Optional additions to the message include:\n"
" `{channel}` Mentions the channel where they must include the agreement message.\n"
" `{mention}` Mentions the user incase they have DM permissions turned off this should be used.\n"
" `{name}` Says the member name if you don't want to ping them.\n"
" `{guild}` Says the servers current name.\n"
" \n"
" Entering nothing will disable this.\n"
" "
msgstr ""

19
cherubim/LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2019-2023 Seraphim R. Pardee and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

26
cherubim/__init__.py Normal file
View File

@ -0,0 +1,26 @@
from .autoprayer import AutoPrayer
from .suggestionbox import SuggestionBox
from .custom_reactions import CustomReactions
from .entrycontrolresponder import EntryControlResponder
from .fun import Fun
from .standards import Standards
from ..reactrole.reactrole import ReactRole
from .quotes import Quotes
async def setup(bot):
await bot.add_cog(AutoPrayer(bot))
await bot.add_cog(SuggestionBox(bot))
await bot.add_cog(CustomReactions())
await bot.add_cog(Fun())
await bot.add_cog(Standards(bot))
await bot.add_cog(ReactRole(bot))
ecr = EntryControlResponder()
await bot.add_cog(ecr)
await bot.add_cog(Quotes(bot))

102
cherubim/autoprayer.py Normal file
View File

@ -0,0 +1,102 @@
import asyncio
import os
from datetime import datetime
import discord
from redbot.core import commands, checks, Config
class AutoPrayer(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=(3322665 + 2))
default_guild = {
"channels_enabled": [],
"duration": 300,
"threshold": 3,
"bot": False,
"pray": "🙏"
}
self.config.register_guild(**default_guild)
@commands.group(name="autoprayer", pass_context=True, no_pm=True)
@checks.admin_or_permissions(manage_guild=True)
async def autoprayer(self, ctx):
"""autoprayer cog settings"""
#if ctx.invoked_subcommand is None:
# await ctx.send_help()
pass
@autoprayer.command(name="on", pass_context=True, no_pm=True)
async def _autoprayer_on(self, ctx):
"""Turn on autoprayer mode in the current channel"""
guild_group = self.config.guild(ctx.guild)
async with guild_group.channels_enabled() as channels_enabled:
channel = ctx.message.channel
if channel.id in channels_enabled:
await ctx.send("AutoPrayer is already on in this channel.")
else:
channels_enabled.append(channel.id)
await ctx.send("AutoPrayer is now on in this channel.")
@autoprayer.command(name="off", pass_context=True, no_pm=True)
async def _autoprayer_off(self, ctx):
"""Turn off autoprayer mode in the current channel"""
guild_group = self.config.guild(ctx.guild)
async with guild_group.channels_enabled() as channels_enabled:
channel = ctx.message.channel
if channel.id not in channels_enabled:
await ctx.send("AutoPrayer is already off in this channel.")
else:
channels_enabled.remove(channel.id)
await ctx.send("AutoPrayer is now off in this channel.")
@autoprayer.command(name="bot", pass_context=True, no_pm=True)
async def _autoprayer_bot(self, ctx):
"""Turn on/off reactions to bot's own messages"""
await self.config.guild(ctx.guild).bot.set(not await self.config.guild(ctx.guild).bot())
if await self.config.guild(ctx.guild).bot():
await ctx.send("Reactions to bot messages turned on.")
else:
await ctx.send("Reactions to bot messages turned off.")
def is_command(self, msg):
return msg.content.startswith("--")
@commands.Cog.listener()
async def on_message(self, message):
try:
guild_group = self.config.guild(message.guild)
async with guild_group.channels_enabled() as channels_enabled:
if message.channel.id not in channels_enabled:
return
is_bot = await guild_group.bot()
if message.author == self.bot.user and not is_bot:
return
if self.is_command(message):
return
try:
if message.guild.id == 636984073226813449:
pray = [x for x in message.guild.emojis if x.name == "lightacandle"][0]
elif message.guild.name == "Orthodox Christian Women":
pray = [x for x in message.guild.emojis if x.name == "Candle"][0]
else:
pray = await guild_group.get_raw("pray")
await message.add_reaction(pray)
except discord.errors.HTTPException:
# Implement a non-spammy way to alert users in future
pass
except:
pass

View File

@ -0,0 +1,182 @@
from redbot.core import commands, checks, Config
import discord
import json
def json_to_embed(data):
embed = discord.Embed()
embed.type = "rich"
if "title" in data.keys():
embed.title = data["title"]
if "url" in data.keys():
embed.url = data["url"]
if "description" in data.keys():
embed.description = data["description"]
if "color" in data.keys():
embed.colour = data["color"]
if "author" in data.keys():
name = "None"
url = discord.Embed.Empty
icon_url = discord.Embed.Empty
if "name" in data["author"].keys():
name = data["author"]["name"]
if "url" in data["author"].keys():
url = data["author"]["url"]
if "icon_url" in data["author"].keys():
icon_url = data["author"]["icon_url"]
embed.set_author(name=name, url=url, icon_url=icon_url)
if "footer" in data.keys():
text = discord.Embed.Empty
icon_url = discord.Embed.Empty
if "text" in data["footer"].keys():
text = data["footer"]["text"]
if "icon_url" in data["footer"].keys():
icon_url = data["footer"]["icon_url"]
embed.set_footer(text=text, icon_url=icon_url)
if "image" in data.keys():
embed.set_image(url=data["image"])
if "thumbnail" in data.keys():
embed.set_thumbnail(url=data["thumbnail"])
if "fields" in data.keys():
for field in data["fields"]:
name = "None"
value = "None"
inline = True
if "name" in field:
name = field["name"]
if "value" in field:
value = field["value"]
if "inline" in field:
inline = field["inline"]
embed.add_field(name=name, value=value, inline=inline)
return embed
class CustomReactions(commands.Cog):
def __init__(self):
self.config = Config.get_conf(self, identifier=(3322665 + 3))
default_guild = {
"custom_reactions": []
}
self.config.register_guild(**default_guild)
@commands.command()
@checks.admin_or_permissions(manage_guild=True)
async def acr(self, ctx, cr_name: str, *, cr_value: str):
group = self.config.guild(ctx.guild)
async with group.custom_reactions() as custom_reactions:
sent = False
item = None
try:
json_obj = json.loads(cr_value)
name = cr_name
embed = json_to_embed(json_obj)
item = {
"name": name,
"value": cr_value
}
await ctx.send(f"Created reaction {name}, response:", embed=embed)
sent = True
except:
item = None
await ctx.send("Failed to create the embed, make sure your JSON is valid as well as any URLs.")
if sent:
custom_reactions.append(item)
@commands.command()
@checks.admin_or_permissions(manage_guild=True)
async def ecr(self, ctx, cr_name: str, *, cr_value: str):
group = self.config.guild(ctx.guild)
async with group.custom_reactions() as custom_reactions:
sent = False
item = None
existing_reaction = [x for x in custom_reactions if x["name"] == cr_name]
if existing_reaction:
custom_reactions.remove(existing_reaction[0])
try:
json_obj = json.loads(cr_value)
name = cr_name
embed = json_to_embed(json_obj)
item = {
"name": name,
"value": cr_value
}
await ctx.send(f"Edited reaction {name}, response:", embed=embed)
sent = True
except:
item = None
await ctx.send("Failed to create the embed, make sure your JSON is valid as well as any URLs.")
if sent:
custom_reactions.append(item)
@commands.command()
@checks.admin_or_permissions(manage_guild=True)
async def dcr(self, ctx, cr_name: str):
group = self.config.guild(ctx.guild)
async with group.custom_reactions() as custom_reactions:
sent = False
item = None
existing_reaction = [x for x in custom_reactions if x["name"] == cr_name]
if existing_reaction:
custom_reactions.remove(existing_reaction[0])
await ctx.send(f"Deleted `{cr_name}`.")
else:
await ctx.send(f"I don't have a reaction named `{cr_name}`. Are you sure it exists?")
@commands.Cog.listener()
async def on_message(self, message):
try:
group = self.config.guild(message.guild)
async with group.custom_reactions() as custom_reactions:
names = [x["name"] for x in custom_reactions]
if message.content in names:
index = names.index(message.content)
json_obj = json.loads(custom_reactions[index]["value"])
await message.channel.send(embed=json_to_embed(json_obj))
except Exception:
pass

View File

@ -0,0 +1,15 @@
from redbot.core import commands
import discord
import os
dir_path = os.path.dirname(__file__)
class EntryControlResponder(commands.Cog):
@commands.Cog.listener()
async def on_message(self, message):
if message.guild:
if message.guild.id == 858664948266958908 and ("entry-" in message.channel.name or "ticket-" in message.channel.name):
if message.author.id == 557628352828014614 and len(message.embeds) > 0:
if "welcome to our server!" in message.embeds[0].description:
embedToSend = discord.Embed(description="**1. Are you an Orthodox Christian? If yes, are you Eastern or Oriental Orthodox? Are you a catechumen or a baptised member? If no, are you another sort of Christian?**\n\n**2. What is your reason for joining the server?**\n\n**3. What is your biological gender?**\n\n**4. Which of these best describes where you live? \"UK and Ireland\", \"Europe\", \"Americas\", \"Asia\", \"Africa\", \"Australia and NZ\"**\n\n**5. Are you married, and/or do you have any children?**\n\n**6. On a scale of 0 to totally addicted, how do you feel about knitting?**")
await message.channel.send(embed=embedToSend)

32
cherubim/fun.py Normal file
View File

@ -0,0 +1,32 @@
from redbot.core import commands
import discord
import os
dir_path = os.path.dirname(__file__)
class Fun(commands.Cog):
@commands.command()
async def dab(self, ctx, item: str=None):
img = discord.File(f"{dir_path}/horsedabbing.jpg")
if item:
await ctx.send(f"{ctx.author.mention} dabs on {item}.", file=img)
else:
await ctx.send(f"{ctx.author.mention} dabs.", file=img)
@commands.command()
async def slap(self, ctx, item: str=None):
if item:
if item == "<@186046294286925824>":
item = "a random, poor, innocent angel of God"
await ctx.send(f"{ctx.author.mention} slaps {item} with a fish. :fish:")
else:
await ctx.send(f"{ctx.author.mention} didn't target anything and accidentally slapped themselves with a fish. :fish:")
@commands.command()
async def kill(self, ctx, item: str=None):
if item:
await ctx.send(f"{item} :gun:")
else:
await ctx.send("How am I supposed to kill nothing?!")

BIN
cherubim/horsedabbing.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

20
cherubim/imgperms.py Normal file
View File

@ -0,0 +1,20 @@
from redbot.core import commands
import discord
import os
dir_path = os.path.dirname(__file__)
class ImgPerms(commands.Cog):
@commands.command()
async def giveimg(self, ctx, user: discord.Member):
if ctx.guild.id == 362503610006765568:
if len([x for x in ctx.author.roles if x.id == 794373197713375302]) > 0:
await user.add_roles([x for x in ctx.guild.roles if x.id == 366885935289204736][0])
await ctx.send(f"Given image perms to {user.mention}.")
@commands.command()
async def takeimg(self, ctx, user: discord.Member):
if ctx.guild.id == 362503610006765568:
if len([x for x in ctx.author.roles if x.id == 794373197713375302]) > 0:
await user.remove_roles([x for x in ctx.guild.roles if x.id == 366885935289204736][0])
await ctx.send(f"Taken image perms to {user.mention}.")

9
cherubim/info.json Normal file
View File

@ -0,0 +1,9 @@
{
"AUTHOR" : "Elliott Pardee (vypr#0001)",
"NAME" : "cherubim",
"SHORT" : "A full-stack cog for Cherubim.",
"DESCRIPTION" : "A full-stack cog for Cherubim.",
"TAGS" : ["cherubim", "custom"],
"REQUIREMENTS" : ["tabulate", "requests"],
"HIDDEN" : false
}

79
cherubim/quotes.py Executable file
View File

@ -0,0 +1,79 @@
import asyncio
import os
import random
from datetime import datetime
from re import split
from typing import final
import discord
from redbot.core import commands, checks, Config
class Quotes(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=(3322665 + 55673))
default_guild = {
"quotes": {},
}
self.config.register_guild(**default_guild)
@commands.command(name="quote", pass_context=True, no_pm=True)
async def quote(self, ctx, user: discord.Member=None, value: int=None):
guild_group = self.config.guild(ctx.guild)
if user is None:
user = ctx.author
async with guild_group.quotes() as quotes:
if str(user.id) in quotes:
quote = None
if value is None:
quote = random.choice(quotes[str(user.id)])
else:
value = value - 1
if -1 < value < len(quotes[str(user.id)]):
quote = quotes[str(user.id)][value]
if quote is not None:
split_paragraphs = quote["text"].split("\n")
for idx in range(len(split_paragraphs)):
split_paragraphs[idx] = f"> {split_paragraphs[idx]}"
final_quote = "\n".join(split_paragraphs)
link = quote["link"]
await ctx.send(f"{user.display_name}:\n\n{final_quote}\n\nContext: <{link}>")
else:
await ctx.send("There are no quotes associated with this user.")
@commands.Cog.listener()
async def on_reaction_add(self, reaction, user):
guild_group = self.config.guild(reaction.message.guild)
reacts_needed = 4
async with guild_group.quotes() as quotes:
if reaction.emoji == "":
users_reacted_count = 0
users_reacted = await reaction.users().flatten()
for user in users_reacted:
if user.id != reaction.message.author.id:
users_reacted_count += 1
if users_reacted_count >= reacts_needed:
msg = reaction.message
final_obj = {
"text": msg.content,
"link": msg.jump_url
}
if str(msg.author.id) in quotes:
if final_obj not in quotes[str(msg.author.id)]:
quotes[str(msg.author.id)].append(final_obj)
else:
quotes[str(msg.author.id)] = [final_obj]

18
cherubim/standards.py Normal file
View File

@ -0,0 +1,18 @@
from redbot.core import commands
import discord
import asyncio
import os
dir_path = os.path.dirname(__file__)
class Standards(commands.Cog):
def __init__(self, bot):
self.bot = bot
# todo: update joining logic
async def on_member_update(self, member):
pass
# todo: update leaving logic
async def on_member_remove(self, member):
pass

174
cherubim/suggestionbox.py Normal file
View File

@ -0,0 +1,174 @@
import os
import asyncio # noqa: F401
import datetime
import discord
from redbot.core import commands, checks, Config
class SuggestionBox(commands.Cog):
"""custom cog for a configurable suggestion box"""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=(3322665 + 1))
self.usercache = []
default_guild = {
"inactive": True,
"channels_enabled": [],
"cleanup": False,
"anonymous": True,
"blocked_ids": []
}
self.config.register_guild(**default_guild)
@commands.group(name="setsuggest", pass_context=True, no_pm=True)
@checks.admin_or_permissions(manage_guild=True)
async def setsuggest(self, ctx):
"""configuration settings"""
pass
@setsuggest.command(name="on", pass_context=True, no_pm=True)
async def _setsuggest_on(self, ctx):
"""Turn on SuggestionBox in the current channel"""
guild_group = self.config.guild(ctx.guild)
async with guild_group.channels_enabled() as channels_enabled:
channel = ctx.message.channel
if channel.id in channels_enabled:
await ctx.send("SuggestionBox is already on in this channel.")
else:
channels_enabled.append(channel.id)
await ctx.send("SuggestionBox is now on in this channel.")
@setsuggest.command(name="off", pass_context=True, no_pm=True)
async def _setsuggest_off(self, ctx):
"""Turn off SuggestionBox in the current channel"""
guild_group = self.config.guild(ctx.guild)
async with guild_group.channels_enabled() as channels_enabled:
channel = ctx.message.channel
if channel.id not in channels_enabled:
await ctx.send("SuggestionBox is already off in this channel.")
else:
channels_enabled.remove(channel.id)
await ctx.send("SuggestionBox is now off in this channel.")
@setsuggest.command(name="block", pass_context=True, no_pm=True)
async def block(self, ctx, user: discord.Member):
"""Blocks a user from making suggestions."""
guild = ctx.guild
group = self.config.guild(guild)
async with group.blocked_ids() as blocked_ids:
if user.id in blocked_ids:
await ctx.send("This user is already in the block list, did you mean to `--setsuggest unblock`?")
else:
blocked_ids.append(user.id)