-
Notifications
You must be signed in to change notification settings - Fork 8
Feature/embeds #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
veeru153
wants to merge
4
commits into
rewrite
Choose a base branch
from
feature/embeds
base: rewrite
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,233 @@ | ||
import asyncio | ||
import logging | ||
import discord | ||
from discord.ext import commands | ||
|
||
import json | ||
import re | ||
|
||
class Embeds(commands.Cog): | ||
|
||
def __init__(self, bot: commands.Bot) -> None: | ||
self.bot = bot | ||
|
||
self.DESC_MAX_LEN = 4096 | ||
self.FIELD_TITLE_MAX_LEN = 256 | ||
self.FIELD_VALUE_MAX_LEN = 1024 | ||
|
||
@commands.hybrid_command() | ||
async def embed(self, ctx: commands.Context): | ||
""" | ||
Interactively construct a Discord embed. | ||
""" | ||
raise NotImplementedError('Command requires implementation and permission set-up.') | ||
|
||
|
||
log = logging.getLogger() | ||
INPUT_TIMED_OUT = "Input timed out." | ||
|
||
def check(m: discord.Message): | ||
return m.channel == ctx.channel and m.author == ctx.author | ||
|
||
def is_skip(msg: discord.Message): | ||
return msg.content.strip().lower() == "skip" | ||
|
||
def is_done(msg: discord.Message): | ||
return msg.content.strip().lower() == "done" | ||
|
||
async def handle_desc(embed: discord.Embed): | ||
try: | ||
desc: discord.Message = await self.bot.wait_for("message", check=check, timeout=timeout) | ||
if not is_skip(desc): | ||
embed.description = desc.content.strip()[:self.DESC_MAX_LEN] | ||
except asyncio.TimeoutError: | ||
await ctx.send(INPUT_TIMED_OUT) | ||
|
||
async def handle_color(embed: discord.Embed): | ||
while True: | ||
try: | ||
color_msg: discord.Message = await self.bot.wait_for("message", check=check, timeout=timeout) | ||
if is_skip(color_msg): | ||
break | ||
color_str = color_msg.content | ||
embed.color = discord.Color.from_str(color_str) | ||
break | ||
except ValueError: | ||
await ctx.send("Invalid Color. Please provide the color in hex format (e.g. `#123456`). Use `skip` to skip this.") | ||
except asyncio.TimeoutError: | ||
await ctx.send(INPUT_TIMED_OUT) | ||
|
||
async def handle_img(embed: discord.Embed): | ||
try: | ||
img_url_msg: discord.Message = await self.bot.wait_for("message", check=check, timeout=timeout) | ||
if is_skip(img_url_msg): | ||
return | ||
img_url = img_url_msg.content.strip() | ||
if img_url.startswith("<"): | ||
img_url = img_url[1:] | ||
if img_url.endswith(">"): | ||
img_url = img_url[:-1] | ||
embed.set_image(url=img_url) | ||
except asyncio.TimeoutError: | ||
await ctx.send(INPUT_TIMED_OUT) | ||
except Exception as ex: | ||
log.error("[Embeds.handle_img] Error setting image", ex, exc_info=1) | ||
|
||
async def handle_fields(embed: discord.Embed): | ||
while True: | ||
try: | ||
await ctx.send("You are now adding another field. Please use the following format: `\"Title\" \"Value\"`. You can type `done` to complete the embed.") | ||
field_msg = await self.bot.wait_for("message", check=check, timeout=timeout) | ||
if is_done(field_msg): | ||
break | ||
match = re.search('\"(.+?)\" +\"(.+?)\"', field_msg.content.strip()) | ||
if match == None: | ||
await ctx.send("Invalid Format") | ||
else: | ||
title = match.group(1)[:self.FIELD_TITLE_MAX_LEN] | ||
value = match.group(2)[:self.FIELD_VALUE_MAX_LEN] | ||
embed.add_field(name=title, value=value) | ||
except asyncio.TimeoutError: | ||
await ctx.send(INPUT_TIMED_OUT) | ||
|
||
async def get_channel(): | ||
while True: | ||
try: | ||
channel_msg: discord.Message = await self.bot.wait_for("message", check=check, timeout=timeout) | ||
if len(channel_msg.channel_mentions) == 0: | ||
await ctx.send("Could not find that channel") | ||
else: | ||
channel = channel_msg.channel_mentions[0] | ||
return channel | ||
except asyncio.TimeoutError: | ||
await ctx.send(INPUT_TIMED_OUT) | ||
break | ||
|
||
async def send_or_update_embed(embed: discord.Embed, channel: discord.TextChannel): | ||
try: | ||
msg_id_msg: discord.Message = await self.bot.wait_for("message", check=check, timeout=timeout) | ||
msg_id = msg_id_msg.content.strip() | ||
matches = re.match('[0-9]+', msg_id) | ||
if matches: | ||
msg = await channel.fetch_message(msg_id) | ||
await msg.edit(embed=embed) | ||
return | ||
await channel.send(embed=embed) | ||
except discord.NotFound as ex: | ||
await ctx.send("No message with this ID was found.") | ||
except discord.HTTPException as ex: | ||
# TODO: temp. Need to confirm how to handle this correctly. | ||
await ctx.send("An error occurred while updating/sending the embed.") | ||
log.error("Error updating/sending embed: %s", ex, exc_info=1) | ||
except Exception as ex: | ||
await ctx.send("An error occurred.") | ||
log.error(ex) | ||
|
||
timeout = 60 | ||
embed = discord.Embed() | ||
|
||
await ctx.send("Please type the description of the embed. Use `skip` to skip this.") | ||
await handle_desc(embed) | ||
await ctx.send("Please provide the colour in hex format (e.g. `#123456`). Use `skip` to skip this.") | ||
await handle_color(embed) | ||
await ctx.send("Please provide the URL for the image you would like to display. Use `skip` to skip this.") | ||
await handle_img(embed) | ||
await handle_fields(embed) | ||
await ctx.send("Which channel should the embed be sent in?") | ||
channel = await get_channel() | ||
member_perms = channel.permissions_for(ctx.author) | ||
if not (member_perms.send_messages and member_perms.embed_links): | ||
await ctx.send("Missing channel permissions.") | ||
return | ||
await ctx.send("Should this embed replace any existing message in that channel? If yes, type the message ID, otherwise type anything else.") | ||
await send_or_update_embed(embed, channel) | ||
|
||
|
||
@commands.command() | ||
async def embedraw(self, ctx: commands.Context): | ||
async def embedraw(self, ctx: commands.Context, type, channel, *argv): | ||
""" | ||
Create a Discord embed via raw JSON input. | ||
""" | ||
raise NotImplementedError('Command requires implementation and permission set-up.') | ||
|
||
# NOTE: This breaks if we miss type or channel as it tries to parse the JSON body in those and breaks. IDK how to fix. | ||
|
||
log = logging.getLogger() | ||
embed_data = None | ||
msg_id = None | ||
print(type, channel, argv) | ||
|
||
# try: | ||
|
||
# if type == "create": | ||
# if len(argv) != 1: | ||
# await ctx.send('Invalid arguments. Please use the following format: `create <#channel> <embed_data>`.') | ||
# return | ||
# embed_data = argv[0] | ||
# elif type == "update": | ||
# if len(argv) != 2: | ||
# await ctx.send('Invalid arguments. Please use the following format: `update <#channel> <message_id> <embed_data>`.') | ||
# return | ||
# msg_id = argv[0].strip() | ||
# embed_data = argv[1] | ||
# else: | ||
# await ctx.send('Unidentified type. Please use either `create` or `update` as the type.') | ||
# return | ||
|
||
# member_perms = channel.permissions_for(ctx.author) | ||
# if not (member_perms.send_messages and member_perms.embed_links): | ||
# await ctx.send("Missing channel permissions.") | ||
# return | ||
|
||
# raw = json.loads(embed_data) | ||
# embed = discord.Embed() | ||
|
||
# if 'description' in raw: | ||
# embed.description = raw['description'].strip()[:self.DESC_MAX_LEN] | ||
|
||
# if 'colour' in raw: | ||
# try: | ||
# embed.color = embed.color = discord.Color.from_str(raw['colour']) | ||
# except ValueError as ex: | ||
# await ctx.send('Invalid Color. Please provide the color in hex format (e.g. `#123456`).') | ||
# return | ||
|
||
# if 'image_url' in raw: | ||
# img_url = raw['image_url'].content.strip() | ||
# if img_url.startswith("<"): | ||
# img_url = img_url[1:] | ||
# if img_url.endswith(">"): | ||
# img_url = img_url[:-1] | ||
# embed.set_image(url=img_url) | ||
|
||
# if 'fields' in raw: | ||
# fields = raw['fields'] | ||
# if len(fields) > 20: | ||
# await ctx.send("") | ||
# return | ||
|
||
# for tuple in fields: | ||
# if len(tuple) > 2: | ||
# continue | ||
# title, value = tuple | ||
# title = title[:self.FIELD_TITLE_MAX_LEN] | ||
# value = value[:self.FIELD_VALUE_MAX_LEN] | ||
# embed.add_field(name=title, value=value) | ||
|
||
# if type == "update": | ||
# msg = await channel.fetch_message(msg_id) | ||
# await msg.edit(embed=embed) | ||
# return | ||
|
||
# await channel.send(embed=embed) | ||
|
||
# except commands.errors.MissingRequiredArgument as ex: | ||
# await ctx.send('Invalid arguments.') | ||
# except commands.errors.ChannelNotFound as ex: | ||
# await ctx.send('Channel not found.') | ||
# except discord.NotFound as ex: | ||
# await ctx.send('Message with that ID was not found in the target channel.') | ||
# except discord.HTTPException as ex: | ||
# await ctx.send("An error occurred while updating/sending the embed.") | ||
# log.error("Error updating/sending embed: %s", ex, exc_info=1) | ||
# except ex: | ||
# await ctx.send('An error occurred.') | ||
# log.error(ex) | ||
|
||
async def setup(bot: commands.Bot): | ||
await bot.add_cog(Embeds(bot)) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.