Skip to content

Commit

Permalink
Merge cogs from SauriCogs
Browse files Browse the repository at this point in the history
  • Loading branch information
Kreusada committed Dec 22, 2024
1 parent f8cf01a commit f2f1c0a
Show file tree
Hide file tree
Showing 32 changed files with 3,510 additions and 0 deletions.
5 changes: 5 additions & 0 deletions cogs.csv
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ Cocktail,Get information about different cocktails and their ingredients.,"Tools
CogPaths,Get various paths for a cog.,"Tools, Informative",Kreusada
Colour,View information about a colour.,"Tools, Informative",Kreusada
ConsoleClearer,Completely clear your Red console,Tools,Kreusada
Counting,Counting channel.,Tools,"saurichable, Kreusada"
EmbedCreator,"Create embeds using buttons, modals and dropdowns!",Tools,Kreusada
Flags,Get the flag for a country,Tools,Kreusada
Gallery,Image only channels.,Tools,"saurichable, Kreusada"
Lock,Lock `@everyone` from sending messages.,Moderation,"saurichable, Kreusada"
Mentionable,Makes unmentionable roles mentionable.,Tools,"saurichable, Kreusada"
MessageDeleter,"Delete messages from users and bots, inclusively or exclusively, in text channels.",Tools,Kreusada
Minifier,Minify your code with python minifier,Tools,Kreusada
MorseCode,Encode and decode morse code.,Tools,Kreusada
NameGenerator,Generate names.,Tools,Kreusada
OnThisDay,"Find out what happened today, in multiple different years in history.",Fun,Kreusada
Pick,Pick a random list,Tools,Kreusada
PyPi,Get information about a package available on PyPi.,Tools,"Kreusada, OofChair"
QR,Create QR codes.,Tools,Kreusada
Quotes,Get a random quote,Fun,Kreusada
Expand Down
373 changes: 373 additions & 0 deletions counting/LICENSE.md

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions counting/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
.. _counting:

========
Counting
========

This is the cog guide for the 'Counting' cog. This guide
contains the collection of commands which you can use in the cog.

Through this guide, ``[p]`` will always represent your prefix. Replace
``[p]`` with your own prefix when you use these commands in Discord.

.. note::

This guide was last updated for version 1.4.0. Ensure
that you are up to date by running ``[p]cog update counting``.

If there is something missing, or something that needs improving
in this documentation, feel free to create an issue `here <https://github.com/Kreusada/Kreusada-Cogs/issues>`_.

This documentation is auto-generated everytime this cog receives an update.

--------------
About this cog
--------------

Make a counting channel with goals.

--------
Commands
--------

Here are all the commands included in this cog (9):

+--------------------------+-------------------------------------------------------------------------------------------------------+
| Command | Help |
+==========================+=======================================================================================================+
| ``[p]countset`` | Various Counting settings. |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset channel`` | Set the counting channel. |
| | |
| | If channel isn't provided, it will delete the current channel. |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset goal`` | Set the counting goal. |
| | |
| | If goal isn't provided, it will be deleted. |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset reset`` | Reset the counter and start from 0 again! |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset role`` | Add a whitelisted role. |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset settings`` | See current settings. |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset start`` | Set the starting number. |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset topic`` | Toggle counting channel's topic changing. |
| | |
| | If `on_off` is not provided, the state will be flipped.= |
+--------------------------+-------------------------------------------------------------------------------------------------------+
| ``[p]countset warnmsg`` | Toggle a warning message. |
| | |
| | If `on_off` is not provided, the state will be flipped. |
| | Optionally add how many seconds the bot should wait before deleting the message (0 for not deleting). |
+--------------------------+-------------------------------------------------------------------------------------------------------+

------------
Installation
------------

If you haven't added my repo before, lets add it first. We'll call it
"kreusada-cogs" here.

.. code-block:: ini
[p]repo add kreusada-cogs https://github.com/Kreusada/Kreusada-Cogs
Now, we can install Counting.

.. code-block:: ini
[p]cog install kreusada-cogs counting
Once it's installed, it is not loaded by default. Load it by running the following
command:

.. code-block:: ini
[p]load counting
---------------
Further Support
---------------

For more support, head over to the `cog support server <https://discord.gg/GET4DVk>`_,
I have my own channel over there at #support_kreusada-cogs. Feel free to join my
`personal server <https://discord.gg/JmCFyq7>`_ whilst you're here.
10 changes: 10 additions & 0 deletions counting/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from redbot.core.bot import Red
from redbot.core.utils import get_end_user_data_statement

from .counting import Counting

__red_end_user_data_statement__ = get_end_user_data_statement(__file__)


async def setup(bot: Red):
await bot.add_cog(Counting(bot))
270 changes: 270 additions & 0 deletions counting/counting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
import asyncio
import datetime
import typing

import discord
from discord.utils import find, get
from redbot.core import Config, checks, commands
from redbot.core.bot import Red


class Counting(commands.Cog):
"""
Make a counting channel with goals.
"""

__version__ = "1.4.0"

def __init__(self, bot: Red):
self.bot = bot
self.config = Config.get_conf(self, identifier=1564646215646, force_registration=True)

self.config.register_guild(
channel=0,
previous=0,
goal=0,
last=0,
whitelist=None,
warning=False,
seconds=0,
topic=True,
)

async def red_delete_data_for_user(self, *, requester, user_id):
for guild in self.bot.guilds:
if user_id == await self.config.guild(guild).last():
await self.config.guild(guild).last.clear()

def format_help_for_context(self, ctx: commands.Context) -> str:
context = super().format_help_for_context(ctx)
return f"{context}\n\nVersion: {self.__version__}"

@checks.admin()
@checks.bot_has_permissions(manage_channels=True, manage_messages=True)
@commands.group(autohelp=True, aliases=["counting"])
@commands.guild_only()
async def countset(self, ctx: commands.Context):
"""Various Counting settings."""

@countset.command(name="channel")
async def countset_channel(
self, ctx: commands.Context, channel: typing.Optional[discord.TextChannel]
):
"""Set the counting channel.
If channel isn't provided, it will delete the current channel."""
if not channel:
await self.config.guild(ctx.guild).channel.set(0)
return await ctx.send("Channel removed.")
await self.config.guild(ctx.guild).channel.set(channel.id)
goal = await self.config.guild(ctx.guild).goal()
if await self.config.guild(ctx.guild).topic():
await self._set_topic(0, goal, 1, channel)
await ctx.send(f"{channel.name} has been set for counting.")

@countset.command(name="goal")
async def countset_goal(self, ctx: commands.Context, goal: int = 0):
"""Set the counting goal.
If goal isn't provided, it will be deleted."""
if not goal:
await self.config.guild(ctx.guild).goal.clear()
return await ctx.send("Goal removed.")
await self.config.guild(ctx.guild).goal.set(goal)
await ctx.send(f"Goal set to {goal}.")

@countset.command(name="start")
async def countset_start(self, ctx: commands.Context, number: int):
"""Set the starting number."""
channel = ctx.guild.get_channel(await self.config.guild(ctx.guild).channel())
if not channel:
return await ctx.send(
f"Set the channel with `{ctx.clean_prefix}countset channel <channel>`, please."
)
await self.config.guild(ctx.guild).previous.set(number)
await self.config.guild(ctx.guild).last.clear()
goal = await self.config.guild(ctx.guild).goal()
next_number = number + 1
if await self.config.guild(ctx.guild).topic():
await self._set_topic(number, goal, next_number, channel)
await channel.send(number)
if c_id != ctx.channel.id:
await ctx.send(f"Counting start set to {number}.")

@countset.command(name="reset")
async def countset_reset(self, ctx: commands.Context, confirmation: bool = False):
"""Reset the counter and start from 0 again!"""
if not confirmation:
return await ctx.send(
"This will reset the ongoing counting. This action **cannot** be undone.\n"
f"If you're sure, type `{ctx.clean_prefix}countset reset yes`."
)
p = await self.config.guild(ctx.guild).previous()
if p == 0:
return await ctx.send("The counting hasn't even started.")
c = ctx.guild.get_channel(await self.config.guild(ctx.guild).channel())
if not c:
return await ctx.send(
f"Set the channel with `{ctx.clean_prefix}countchannel <channel>`, please."
)
await self.config.guild(ctx.guild).previous.clear()
await self.config.guild(ctx.guild).last.clear()
await c.send("Counting has been reset.")
goal = await self.config.guild(ctx.guild).goal()
if await self.config.guild(ctx.guild).topic():
await self._set_topic(0, goal, 1, c)
if c_id != ctx.channel.id:
await ctx.send("Counting has been reset.")

@countset.command(name="role")
async def countset_role(self, ctx: commands.Context, role: typing.Optional[discord.Role]):
"""Add a whitelisted role."""
if not role:
await self.config.guild(ctx.guild).whitelist.clear()
await ctx.send(f"Whitelisted role has been deleted.")
else:
await self.config.guild(ctx.guild).whitelist.set(role.id)
await ctx.send(f"{role.name} has been whitelisted.")

@countset.command(name="warnmsg")
async def countset_warnmsg(
self,
ctx: commands.Context,
on_off: typing.Optional[bool],
seconds: typing.Optional[int],
):
"""Toggle a warning message.
If `on_off` is not provided, the state will be flipped.
Optionally add how many seconds the bot should wait before deleting the message (0 for not deleting).
"""
target_state = on_off or not (await self.config.guild(ctx.guild).warning())
await self.config.guild(ctx.guild).warning.set(target_state)
if target_state:
if not seconds or seconds < 0:
seconds = 0
await ctx.send("Warning messages are now enabled.")
else:
await ctx.send(
f"Warning messages are now enabled, will be deleted after {seconds} seconds."
)
await self.config.guild(ctx.guild).seconds.set(seconds)
else:
await ctx.send("Warning messages are now disabled.")

@countset.command(name="topic")
async def countset_topic(self, ctx: commands.Context, on_off: typing.Optional[bool]):
"""Toggle counting channel's topic changing.
If `on_off` is not provided, the state will be flipped.="""
target_state = on_off or not (await self.config.guild(ctx.guild).topic())
await self.config.guild(ctx.guild).topic.set(target_state)
if target_state:
await ctx.send("Updating the channel's topic is now enabled.")
else:
await ctx.send("Updating the channel's topic is now disabled.")

@countset.command(name="settings")
async def countset_settings(self, ctx: commands.Context):
"""See current settings."""
data = await self.config.guild(ctx.guild).all()
channel = ctx.guild.get_channel(data["channel"])
channel = channel.mention if channel else "None"

goal = "None" if data["goal"] == 0 else str(data["goal"])

role = ctx.guild.get_role(data["whitelist"])
role = role.name if role else "None"

warn = "Disabled" if data["warning"] else f"Enabled ({data['seconds']} s)"

embed = discord.Embed(colour=await ctx.embed_colour(), timestamp=datetime.datetime.now())
embed.set_author(name=ctx.guild.name, icon_url=ctx.guild.icon_url)
embed.title = "**__Counting settings:__**"
embed.set_footer(text="*required to function properly")

embed.add_field(name="Channel*:", value=channel)
embed.add_field(name="Whitelisted role:", value=role)
embed.add_field(name="Warning message:", value=warn)
embed.add_field(name="Next number:", value=str(data["previous"] + 1))
embed.add_field(name="Goal:", value=goal)
embed.add_field(name="Topic changing:", value=str(data["topic"]))

await ctx.send(embed=embed)

@commands.Cog.listener()
async def on_message(self, message):
if not message.guild or message.author.id == self.bot.user.id:
return
if message.channel.id != await self.config.guild(message.guild).channel():
return
last_id = await self.config.guild(message.guild).last()
previous = await self.config.guild(message.guild).previous()
seconds = await self.config.guild(message.guild).seconds()
if message.author.id != last_id:
try:
current = int(message.content)
if current - 1 == previous:
await self.config.guild(message.guild).previous.set(current)
await self.config.guild(message.guild).last.set(message.author.id)
if await self.config.guild(message.guild).topic():
return await self._update_topic(message.channel)
return
except (TypeError, ValueError):
pass
rid = await self.config.guild(message.guild).whitelist()
if rid:
role = message.guild.get_role(int(rid))
if role and role in message.author.roles:
return
if await self.config.guild(message.guild).warning():
if message.author.id != last_id:
warn_msg = await message.channel.send(
f"The next message in this channel must be {previous + 1}"
)
else:
warn_msg = await message.channel.send(f"You cannot count twice in a row.")
if seconds != 0:
await asyncio.sleep(seconds)
await warn_msg.delete()
try:
await message.delete()
except (discord.Forbidden, discord.NotFound):
pass

@commands.Cog.listener()
async def on_message_delete(self, message):
if not message.guild:
return
if message.channel.id != await self.config.guild(message.guild).channel():
return
try:
deleted = int(message.content)
previous = await self.config.guild(message.guild).previous()
goal = await self.config.guild(message.guild).goal()
if deleted == previous:
s = str(deleted)
if goal == 0:
msgs = await message.channel.history(limit=100).flatten()
else:
msgs = await message.channel.history(limit=goal).flatten()
msg = find(lambda m: m.content == s, msgs)
if not msg:
p = deleted - 1
await self.config.guild(message.guild).previous.set(p)
await message.channel.send(deleted)
except (TypeError, ValueError):
return

async def _update_topic(self, channel):
goal = await self.config.guild(channel.guild).goal()
prev = await self.config.guild(channel.guild).previous()
if goal != 0 and prev < goal:
await channel.edit(
topic=f"Let's count! | Next message must be {prev + 1}! | Goal is {goal}!"
)
elif goal != 0 and prev == goal:
await channel.send("We've reached the goal! :tada:")
await channel.edit(topic=f"Goal reached! :tada:")
else:
await channel.edit(topic=f"Let's count! | Next message must be {prev + 1}!")
Loading

0 comments on commit f2f1c0a

Please sign in to comment.