From 46707e63f2728ba55c8136999575d138ae923b35 Mon Sep 17 00:00:00 2001 From: Bobloy Date: Wed, 16 May 2018 11:33:57 -0400 Subject: [PATCH 1/7] AnnounceDaily initial commit --- announcedaily/__init__.py | 5 + announcedaily/announcedaily.py | 249 +++++++++++++++++++++++++++++++++ announcedaily/info..json | 18 +++ 3 files changed, 272 insertions(+) create mode 100644 announcedaily/__init__.py create mode 100644 announcedaily/announcedaily.py create mode 100644 announcedaily/info..json diff --git a/announcedaily/__init__.py b/announcedaily/__init__.py new file mode 100644 index 0000000..2ac3ea5 --- /dev/null +++ b/announcedaily/__init__.py @@ -0,0 +1,5 @@ +from .announcedaily import AnnounceDaily + + +def setup(bot): + bot.add_cog(AnnounceDaily(bot)) diff --git a/announcedaily/announcedaily.py b/announcedaily/announcedaily.py new file mode 100644 index 0000000..83b7d1d --- /dev/null +++ b/announcedaily/announcedaily.py @@ -0,0 +1,249 @@ +import asyncio +import random +from datetime import datetime, timedelta + +import discord + +from redbot.core import Config, checks, commands + +from redbot.core.bot import Red +from redbot.core.data_manager import cog_data_path +from redbot.core.utils.chat_formatting import pagify, box + +DEFAULT_MESSAGES = [ + # "Example message. Uncomment and overwrite to use" +] + + +class AnnounceDaily: + """ + Send daily announcements + """ + + def __init__(self, bot: Red): + self.bot = bot + self.path = str(cog_data_path(self)).replace('\\', '/') + + self.image_path = self.path + "/" + + self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True) + default_global = { + 'messages': [], + 'images': [], + 'time': {'hour': 0, 'minute': 0, 'second': 0} + } + default_guild = { + "channelid": None + } + + self.config.register_global(**default_global) + self.config.register_guild(**default_guild) + + async def _get_msgs(self): + return DEFAULT_MESSAGES + await self.config.messages() + + @commands.group(name="announcedaily", aliases=['annd']) + @checks.mod_or_permissions(administrator=True) + @commands.guild_only() + async def _ad(self, ctx: commands.Context): + """ + Base command for managing AnnounceDaily settings + + Do `[p]help annd ` for more details + """ + if ctx.invoked_subcommand is None: + await ctx.send_help() + + @commands.command() + @checks.guildowner() + @commands.guild_only() + async def runannounce(self, ctx: commands.Context): + """Trigger the daily announcement""" + + await self.send_announcements() + await ctx.send("Success") + + @_ad.command() + async def setchannel(self, ctx: commands.Context, channel: discord.TextChannel = None): + """ + Set the announcement channel for this server + + Don't pass a channel to clear this server of receiving announcements + """ + if channel is not None: + await self.config.guild(ctx.guild).channelid.set(channel.id) + await ctx.send("Announcement channel has been set to {}".format(channel.mention)) + else: + await self.config.guild(ctx.guild).channelid.set(None) + await ctx.send("Announcement channel has been cleared") + + @_ad.command() + async def addmsg(self, ctx: commands.Context, *, msg): + """ + Add a message to the pool of announcement messages + """ + async with self.config.messages() as msgs: + msgs.append(msg) + + await ctx.send("Message successfully added!") + + @_ad.command() + async def addimg(self, ctx: commands.Context, filename=None): + """ + Add an image to the pool of announcement images + + You must attach an image while executing this command + """ + if ctx.message.attachments: + att_ = ctx.message.attachments[0] + try: + h = att_.height + except AttributeError: + await ctx.send("You must attach an image, no other file will be accepted") + return + + if filename is None: + filename = att_.filename + + try: + # with open(self.image_path + filename, 'w') as f: + # await att_.save(f) + await att_.save(self.image_path + filename) + except discord.NotFound: + await ctx.send("Did you delete the message? Cause I couldn't download the attachment") + except discord.HTTPException: + await ctx.send("Failed to download the attachment, please try again") + else: + async with self.config.images() as images: + if filename in images: + await ctx.send("Image {} has been overwritten!".format(filename)) + else: + images.append(filename) + await ctx.send("Image {} has been added!".format(filename)) + else: + await ctx.send("You must attach an image when sending this command") + + @_ad.command() + async def listmsg(self, ctx: commands.Context): + """ + List all registered announcement messages + """ + messages = await self.config.messages() + for page in pagify("\n".join("{} - {}".format(key, image) for key, image in enumerate(messages))): + await ctx.send(box(page)) + await ctx.send("Done!") + + @_ad.command() + async def listimg(self, ctx: commands.Context): + """ + List all registered announcement immages + """ + images = await self.config.images() + for page in pagify("\n".join(images)): + await ctx.send(box(page)) + await ctx.send("Done!") + + @_ad.command() + async def delmsg(self, ctx: commands.Context, index: int): + """ + Remove a message from the announcement pool + + Must provide the index of the message, which can be found by using `[p]annd listmsg` + """ + async with self.config.messages() as messages: + try: + out = messages.pop(index) + except IndexError: + await ctx.send("Invalid index, check valid indexes with `listmsg` command") + return + + await ctx.send("The following message was removed:\n```{}```".format(out)) + + @_ad.command() + async def delimg(self, ctx: commands.Context, filename: str): + """ + Remove an image from the announcement pool + + Does not delete the file from the disk, so you may have to clean it up occasionally + """ + async with self.config.images() as images: + if filename not in images: + await ctx.send("This file doesn't exist") + else: + images.remove(filename) + await ctx.send("Successfully removed {}".format(filename)) + + @_ad.command() + async def settime(self, ctx: commands.Context, minutes: int): + """ + Set the daily announcement time + + It will first announce at the time you provided, then it will repeat every 24 hours + """ + ann_time = datetime.now() + timedelta(minutes=minutes) + + h = ann_time.hour + m = ann_time.minute + s = ann_time.second + await self.config.time.set({'hour': h, 'minute': m, 'second': s}) + + await ctx.send("Announcements time has been set to {}::{}::{} every day\n" + "Changes will apply after next announcement".format(h, m, s)) + + async def send_announcements(self): + messages = await self._get_msgs() + images = await self.config.images() + + total = len(messages) + len(images) + if total < 1: + return + + x = random.randint(0, total - 1) + + if x >= len(messages): + x -= len(messages) + choice = images[x] + choice = open(self.image_path + choice, 'rb') + is_image = True + else: + choice = messages[x] + is_image = False + + for guild in self.bot.guilds: + channel = await self.config.guild(guild).channelid() + if channel is None: + continue + channel = guild.get_channel(channel) + if channel is None: + continue + + if is_image: + await channel.send(file=discord.File(choice)) + else: + await channel.send(choice) + + async def check_day(self): + while self is self.bot.get_cog("Timerole"): + tomorrow = datetime.now() + timedelta(days=1) + time = await self.config.time() + h, m, s = time['hour'], time['minute'], time['second'] + midnight = datetime(year=tomorrow.year, month=tomorrow.month, + day=tomorrow.day, hour=h, minute=m, second=s) + + await asyncio.sleep((midnight - datetime.now()).seconds) + + if self is not self.bot.get_cog("Timerole"): + return + + await self.send_announcements() + + await asyncio.sleep(3) + +# [p]setchannel #channelname - Set the announcement channel per server +# [p]addmsg - Adds a msg to the pool +# [p]addimg http://imgurl.com/image.jpg - Adds an image to the pool +# [p]listmsg - Lists all messages in the pool +# [p]listimg - Unsure about this one, but would probably just post all the images +# [p]delmsg - Remove msg from pool +# [p]delimg - Remove image from pool +# [p]settime - S diff --git a/announcedaily/info..json b/announcedaily/info..json new file mode 100644 index 0000000..c762df6 --- /dev/null +++ b/announcedaily/info..json @@ -0,0 +1,18 @@ +{ + "author": [ + "Bobloy" + ], + "bot_version": [ + 3, + 0, + 0 + ], + "description": "Cog Template", + "hidden": true, + "install_msg": "Thank you for installing MyCog", + "requirements": [], + "short": "Cog Template", + "tags": [ + "bobloy" + ] +} \ No newline at end of file From 954361635ecf5664fdb8680eff1bcf17d94f39dd Mon Sep 17 00:00:00 2001 From: Bobloy Date: Wed, 16 May 2018 11:36:36 -0400 Subject: [PATCH 2/7] Description update --- README.md | 3 ++- announcedaily/info..json | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2f53825..8f61811 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ Cog Function | Name | Status | Description (Click to see full status) -| --- | --- | --- | +| --- | --- | --- | +| announcedaily | **Alpha** |
Send daily announcements to all servers at a specified timesCommissioned release, so suggestions will not be accepted
| | ccrole | **Beta** |
Create custom commands that also assign rolesMay have some bugs, please create an issue if you find any
| | chatter | **Alpha** |
Chat-bot trained to talk like your guildMissing some key features, but currently functional
| | coglint | **Alpha** |
Error check code in python syntax posted to discordWorks, but probably needs more turning to work for cogs
| diff --git a/announcedaily/info..json b/announcedaily/info..json index c762df6..c2e9ce6 100644 --- a/announcedaily/info..json +++ b/announcedaily/info..json @@ -7,11 +7,11 @@ 0, 0 ], - "description": "Cog Template", + "description": "Send daily announcements to all servers at a specified times", "hidden": true, - "install_msg": "Thank you for installing MyCog", + "install_msg": "Thank you for installing AnnounceDaily! Get started with `[p]help AnnounceDaily`", "requirements": [], - "short": "Cog Template", + "short": "Send daily announcements", "tags": [ "bobloy" ] From d585e89fcd5002dbe79d2154e00633fdf18138d5 Mon Sep 17 00:00:00 2001 From: Bobloy Date: Thu, 17 May 2018 10:12:32 -0400 Subject: [PATCH 3/7] Actually do the announcement --- announcedaily/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/announcedaily/__init__.py b/announcedaily/__init__.py index 2ac3ea5..07e6740 100644 --- a/announcedaily/__init__.py +++ b/announcedaily/__init__.py @@ -1,5 +1,9 @@ +from redbot.core.bot import Red + from .announcedaily import AnnounceDaily -def setup(bot): - bot.add_cog(AnnounceDaily(bot)) +def setup(bot: Red): + daily = AnnounceDaily(bot) + bot.loop.create_task(daily.check_day()) + bot.add_cog(daily) From e09d43d1af8a1ef3c41d73851aa389e68f499bfa Mon Sep 17 00:00:00 2001 From: Bobloy Date: Thu, 17 May 2018 10:31:59 -0400 Subject: [PATCH 4/7] Not timerole you fool --- announcedaily/__init__.py | 2 +- announcedaily/announcedaily.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/announcedaily/__init__.py b/announcedaily/__init__.py index 07e6740..8cc69d5 100644 --- a/announcedaily/__init__.py +++ b/announcedaily/__init__.py @@ -5,5 +5,5 @@ from .announcedaily import AnnounceDaily def setup(bot: Red): daily = AnnounceDaily(bot) - bot.loop.create_task(daily.check_day()) bot.add_cog(daily) + bot.loop.create_task(daily.check_day()) diff --git a/announcedaily/announcedaily.py b/announcedaily/announcedaily.py index 83b7d1d..67a0cf0 100644 --- a/announcedaily/announcedaily.py +++ b/announcedaily/announcedaily.py @@ -223,18 +223,21 @@ class AnnounceDaily: await channel.send(choice) async def check_day(self): - while self is self.bot.get_cog("Timerole"): + print("Out of start") + while self is self.bot.get_cog("AnnounceDaily"): + print("Start") tomorrow = datetime.now() + timedelta(days=1) time = await self.config.time() h, m, s = time['hour'], time['minute'], time['second'] midnight = datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=h, minute=m, second=s) + print("Sleeping for {} seconds".format((midnight - datetime.now()).seconds)) await asyncio.sleep((midnight - datetime.now()).seconds) if self is not self.bot.get_cog("Timerole"): return - + print("Pre-announce") await self.send_announcements() await asyncio.sleep(3) From f5e88f061387c615f22d055be4e049e9cbcbf2c1 Mon Sep 17 00:00:00 2001 From: Bobloy Date: Thu, 17 May 2018 10:34:25 -0400 Subject: [PATCH 5/7] Still not timerole --- announcedaily/announcedaily.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/announcedaily/announcedaily.py b/announcedaily/announcedaily.py index 67a0cf0..a9b3b54 100644 --- a/announcedaily/announcedaily.py +++ b/announcedaily/announcedaily.py @@ -188,7 +188,7 @@ class AnnounceDaily: await self.config.time.set({'hour': h, 'minute': m, 'second': s}) await ctx.send("Announcements time has been set to {}::{}::{} every day\n" - "Changes will apply after next announcement".format(h, m, s)) + "Changes will apply after next announcement or reload".format(h, m, s)) async def send_announcements(self): messages = await self._get_msgs() @@ -235,7 +235,7 @@ class AnnounceDaily: print("Sleeping for {} seconds".format((midnight - datetime.now()).seconds)) await asyncio.sleep((midnight - datetime.now()).seconds) - if self is not self.bot.get_cog("Timerole"): + if self is not self.bot.get_cog("AnnounceDaily"): return print("Pre-announce") await self.send_announcements() From a845977cc4779585f549711562d62507b42b5ab2 Mon Sep 17 00:00:00 2001 From: Bobloy Date: Thu, 17 May 2018 10:42:35 -0400 Subject: [PATCH 6/7] Working, prints are weird though --- announcedaily/announcedaily.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/announcedaily/announcedaily.py b/announcedaily/announcedaily.py index a9b3b54..8f19dab 100644 --- a/announcedaily/announcedaily.py +++ b/announcedaily/announcedaily.py @@ -223,9 +223,7 @@ class AnnounceDaily: await channel.send(choice) async def check_day(self): - print("Out of start") while self is self.bot.get_cog("AnnounceDaily"): - print("Start") tomorrow = datetime.now() + timedelta(days=1) time = await self.config.time() h, m, s = time['hour'], time['minute'], time['second'] @@ -236,8 +234,9 @@ class AnnounceDaily: await asyncio.sleep((midnight - datetime.now()).seconds) if self is not self.bot.get_cog("AnnounceDaily"): + print("Announce canceled, cog has been lost") return - print("Pre-announce") + await self.send_announcements() await asyncio.sleep(3) From bfc65e262edd118438ea8fda196a9d5d1651518d Mon Sep 17 00:00:00 2001 From: bobloy Date: Fri, 7 Sep 2018 09:24:30 -0400 Subject: [PATCH 7/7] auto_help update and clearer messages --- announcedaily/announcedaily.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/announcedaily/announcedaily.py b/announcedaily/announcedaily.py index 8f19dab..17a1bd7 100644 --- a/announcedaily/announcedaily.py +++ b/announcedaily/announcedaily.py @@ -3,15 +3,14 @@ import random from datetime import datetime, timedelta import discord - from redbot.core import Config, checks, commands - from redbot.core.bot import Red from redbot.core.data_manager import cog_data_path from redbot.core.utils.chat_formatting import pagify, box DEFAULT_MESSAGES = [ - # "Example message. Uncomment and overwrite to use" + # "Example message. Uncomment and overwrite to use", + # "Example message 2. Each message is in quotes and separated by a comma" ] @@ -52,13 +51,13 @@ class AnnounceDaily: Do `[p]help annd ` for more details """ if ctx.invoked_subcommand is None: - await ctx.send_help() + pass @commands.command() @checks.guildowner() @commands.guild_only() async def runannounce(self, ctx: commands.Context): - """Trigger the daily announcement""" + """Manually run the daily announcement""" await self.send_announcements() await ctx.send("Success") @@ -174,13 +173,13 @@ class AnnounceDaily: await ctx.send("Successfully removed {}".format(filename)) @_ad.command() - async def settime(self, ctx: commands.Context, minutes: int): + async def settime(self, ctx: commands.Context, minutes_from_now: int): """ Set the daily announcement time It will first announce at the time you provided, then it will repeat every 24 hours """ - ann_time = datetime.now() + timedelta(minutes=minutes) + ann_time = datetime.now() + timedelta(minutes=minutes_from_now) h = ann_time.hour m = ann_time.minute @@ -188,7 +187,7 @@ class AnnounceDaily: await self.config.time.set({'hour': h, 'minute': m, 'second': s}) await ctx.send("Announcements time has been set to {}::{}::{} every day\n" - "Changes will apply after next announcement or reload".format(h, m, s)) + "**Changes will apply after next scheduled announcement or reload**".format(h, m, s)) async def send_announcements(self): messages = await self._get_msgs()