You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
8.8 KiB
265 lines
8.8 KiB
import asyncio
|
|
import random
|
|
from datetime import datetime, timedelta
|
|
from typing import Any
|
|
|
|
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 2. Each message is in quotes and separated by a comma"
|
|
]
|
|
|
|
Cog: Any = getattr(commands, "Cog", object)
|
|
|
|
|
|
class AnnounceDaily(Cog):
|
|
"""
|
|
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 <subcommand>` for more details
|
|
"""
|
|
if ctx.invoked_subcommand is None:
|
|
pass
|
|
|
|
@commands.command()
|
|
@checks.guildowner()
|
|
@commands.guild_only()
|
|
async def runannounce(self, ctx: commands.Context):
|
|
"""Manually run 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:
|
|
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 images
|
|
"""
|
|
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_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_from_now)
|
|
|
|
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(
|
|
"Announcement time has been set to {}::{}::{} every day\n"
|
|
"**Changes will apply after next scheduled announcement or reload**".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 True:
|
|
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("AnnounceDaily"):
|
|
print("Announce canceled, cog has been lost")
|
|
return
|
|
|
|
await self.send_announcements()
|
|
|
|
await asyncio.sleep(3)
|
|
|
|
|
|
# [p]setchannel #channelname - Set the announcement channel per server
|
|
# [p]addmsg <message goes here> - 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 <x> - S
|