From e896d47a65ce7c2f1c0e4d606dbea21d5f33804e Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 19 Oct 2019 00:22:15 -0700 Subject: [PATCH 1/8] I didn't break it moving stuff to a method --- Cogs/Hw.py | 107 ++++++++++++++++++----------------------------------- 1 file changed, 36 insertions(+), 71 deletions(-) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index 8f3cdd08..263adedc 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -321,62 +321,15 @@ async def edithw(self, ctx, *, build = None): await ctx.message.add_reaction("📬") await hwChannel.send(bparts) - msg = 'Alright, *{}*, what parts does "{}" have now? (Please include *all* parts for this build - you can add new lines with *shift + enter*)\n'.format(DisplayName.name(ctx.author), bname) - msg += 'You can also pass pcpartpicker links to have them formatted automagically - I can also format them using different styles.\n' - msg += 'For example: ' - msg += '```https://pcpartpicker.com/list/123456 mdblock``` would format with the markdown block style.\n' - msg += 'Markdown styles available are *normal, md, mdblock, bold, bolditalic*' - while True: - parts = await self.prompt(hw_id, ctx, msg, hwChannel, DisplayName.name(ctx.author)) - if not parts: - self._stop_hw(ctx.author) - return - if 'pcpartpicker.com' in parts.content.lower(): - # Possibly a pc partpicker link? - msg = 'It looks like you sent a pc part picker link - did you want me to try and format that? (y/n/stop)' - test = await self.confirm(hw_id, ctx, parts, hwChannel, msg) - if test == None: - self._stop_hw(ctx.author) - return - elif test == True: - partList = parts.content.split() - if len(partList) == 1: - partList.append(None) - output = None - try: - output = await PCPP.getMarkdown(partList[0], partList[1], False) - except: - pass - if not output: - msg = 'Something went wrong! Make sure you use a valid pcpartpicker link.' - await hwChannel.send(msg) - self._stop_hw(ctx.author) - return - if len(output) > 2000: - msg = "That's an *impressive* list of parts - but the max length allowed for messages in Discord is 2000 characters, and you're at *{}*.".format(len(output)) - msg += '\nMaybe see if you can prune up that list a bit and try again?' - await hwChannel.send(msg) - self._stop_hw(ctx.author) - return - # Make sure - conf = await self.confirm(hw_id, ctx, output, hwChannel, None, ctx.author) - if conf == None: - # Timed out - self._stop_hw(ctx.author) - return - elif conf == False: - # Didn't get our answer - msg = 'Alright, *{}*, what parts does "{}" have now? (Please include *all* parts for this build - you can add new lines with *shift + enter*)'.format(DisplayName.name(ctx.author), bname) - continue + # Prompt if user wants to use embeds + msg = '*{}*, would you like to make this build an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) + embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) + + mainBuild = await self.getHardware(hw_id, ctx, hwChannel, mainBuild, bname) + + if not mainBuild: + return - m = '{} set to:\n{}'.format(bname, output) - await hwChannel.send(m) - mainBuild['Hardware'] = output - self.settings.setGlobalUserStat(ctx.author, "Hardware", buildList) - break - mainBuild['Hardware'] = parts.content - self.settings.setGlobalUserStat(ctx.author, "Hardware", buildList) - break msg = '*{}*, {} was edited successfully!'.format(DisplayName.name(ctx.author), bname) self._stop_hw(ctx.author) await hwChannel.send(msg) @@ -915,7 +868,7 @@ async def newhw(self, ctx): msg = 'Alright, *{}*, let\'s add a new build.\n\n'.format(DisplayName.name(ctx.author)) if len(buildList) == 1: - msg += 'You currently have *1 build* on file.\n\n' + msg += 'You currently have *1 build* on file.\n\nLet\'s get started!' else: msg += 'You currently have *{} builds* on file.\n\nLet\'s get started!'.format(len(buildList)) @@ -953,6 +906,29 @@ async def newhw(self, ctx): bname = buildName.content if self.checkSuppress(ctx): bname = Nullify.clean(bname) + + # Prompt if user wants to use embeds + msg = '*{}*, would you like to make this build an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) + embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) + + newBuild = await self.getHardware(hw_id, ctx, hwChannel, newBuild, bname) + + if not newBuild: + return + + # Check if we already have a main build and clear it + for build in buildList: + if build['Main']: + build['Main'] = False + + buildList.append(newBuild) + self.settings.setGlobalUserStat(ctx.author, "Hardware", buildList) + msg = '*{}*, {} was created successfully! It has been set as your main build. To select a different main, you can use `{}mainhw`'.format(DisplayName.name(ctx.author), bname, ctx.prefix) + self._stop_hw(ctx.author) + await hwChannel.send(msg) + + # Get Parts from User + async def getHardware(self, hw_id, ctx, hwChannel, build, bname): msg = 'Alright, *{}*, what parts does "{}" have? (Please include *all* parts for this build - you can add new lines with *shift + enter*)\n'.format(DisplayName.name(ctx.author), bname) msg += 'You can also pass pcpartpicker links to have them formatted automagically - I can also format them using different styles.\n' msg += 'For example: ' @@ -1003,21 +979,10 @@ async def newhw(self, ctx): continue m = '{} set to:\n{}'.format(bname, output) await hwChannel.send(m) - newBuild['Hardware'] = output - break - newBuild['Hardware'] = parts.content - break - - # Check if we already have a main build and clear it - for build in buildList: - if build['Main']: - build['Main'] = False - - buildList.append(newBuild) - self.settings.setGlobalUserStat(ctx.author, "Hardware", buildList) - msg = '*{}*, {} was created successfully! It has been set as your main build. To select a different main, you can use `{}mainhw`'.format(DisplayName.name(ctx.author), bname, ctx.prefix) - self._stop_hw(ctx.author) - await hwChannel.send(msg) + build['Hardware'] = output + return build + build['Hardware'] = parts.content + return build # New HW helper methods def channelCheck(self, msg, dest = None): From a058b3a2f061bbfd08d5dbd8ef1bf966a4455b5f Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 19 Oct 2019 14:48:59 -0700 Subject: [PATCH 2/8] It works but no PCPP stuff --- Cogs/Hw.py | 277 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 261 insertions(+), 16 deletions(-) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index 263adedc..316d6e6b 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -2,6 +2,7 @@ import discord import time import argparse +import json from operator import itemgetter from discord.ext import commands from Cogs import ReadableTime @@ -25,6 +26,9 @@ def __init__(self, bot, settings): self.settings = settings self.hwactive = {} self.charset = "0123456789" + + # Something stupid that no one would ever actually use... + self.embedPrefix = "^^&&^^&&" def gen_id(self): # Just use the current time as that shouldn't ever be the same (unless a user @@ -306,8 +310,28 @@ async def edithw(self, ctx, *, build = None): if self.checkSuppress(ctx): bname = Nullify.clean(bname) bparts = Nullify.clean(bparts) + + isEmbed = False + + # Prompt if user wants to continue using embeds + if mainBuild["Hardware"].startswith(self.embedPrefix): + # Prompt if user wants to use embeds + msg = '*{}*, we\'ve detected that this is an embed. Would you like to keep this as an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) + embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) + + if not embedConf: + self._stop_hw(ctx.author) + return + isEmbed = embedConf + + msg = "" + + # Embed already contains title, just say we're retrieving parts + if isEmbed: + msg = "Retrieving parts..." + else: + msg = '"{}"\'s current parts:'.format(bname) - msg = '"{}"\'s current parts:'.format(bname) try: await hwChannel.send(msg) except: @@ -319,17 +343,18 @@ async def edithw(self, ctx, *, build = None): return if hwChannel == ctx.author and ctx.channel != ctx.author.dm_channel: await ctx.message.add_reaction("📬") - await hwChannel.send(bparts) - - # Prompt if user wants to use embeds - msg = '*{}*, would you like to make this build an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) - embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) - mainBuild = await self.getHardware(hw_id, ctx, hwChannel, mainBuild, bname) + if isEmbed: + mainBuild = await self.getEmbeddedHardware(hw_id, ctx, hwChannel, mainBuild, bname) + else: + await hwChannel.send(bparts) + mainBuild = await self.getHardware(hw_id, ctx, hwChannel, mainBuild, bname) if not mainBuild: return + self.settings.setGlobalUserStat(ctx.author, "Hardware", buildList) + msg = '*{}*, {} was edited successfully!'.format(DisplayName.name(ctx.author), bname) self._stop_hw(ctx.author) await hwChannel.send(msg) @@ -662,13 +687,31 @@ async def hw(self, ctx, *, user : str = None, build = None): return # At this point - we *should* have a user and a build - msg_head = "__**{}'s {}:**__\n\n".format(DisplayName.name(memFromName), buildParts['Name']) - msg = msg_head + buildParts['Hardware'] - if len(msg) > 2000: # is there somwhere the discord char count is defined, to avoid hardcoding? - msg = buildParts['Hardware'] # if the header pushes us over the limit, omit it and send just the string - if self.checkSuppress(ctx): - msg = Nullify.clean(msg) - await ctx.channel.send(msg) + if buildParts['Hardware'].startswith(self.embedPrefix): + hardware = EmbeddedHardware.parse(buildParts['Hardware'].replace(self.embedPrefix, "")) + + embed = discord.Embed() + embed.title = "{}'s {}".format(DisplayName.name(memFromName), buildParts['Name']) + + embed.description = hardware.description + embed.clear_fields() + + if not hardware.thumbnail == None: + embed.set_thumbnail(url=hardware.thumbnail) + + for x in hardware.fields: + embed.add_field(name=x.title, value=x.body) + + await ctx.channel.send(embed=embed) + + else: + msg_head = "__**{}'s {}:**__\n\n".format(DisplayName.name(memFromName), buildParts['Name']) + msg = msg_head + buildParts['Hardware'] + if len(msg) > 2000: # is there somwhere the discord char count is defined, to avoid hardcoding? + msg = buildParts['Hardware'] # if the header pushes us over the limit, omit it and send just the string + if self.checkSuppress(ctx): + msg = Nullify.clean(msg) + await ctx.channel.send(msg) @commands.command(pass_context=True) @@ -911,7 +954,13 @@ async def newhw(self, ctx): msg = '*{}*, would you like to make this build an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) - newBuild = await self.getHardware(hw_id, ctx, hwChannel, newBuild, bname) + if not embedConf: + self._stop_hw(ctx.author) + return + elif embedConf: + newBuild = await self.getEmbeddedHardware(hw_id, ctx, hwChannel, newBuild, bname) + else: + newBuild = await self.getHardware(hw_id, ctx, hwChannel, newBuild, bname) if not newBuild: return @@ -984,6 +1033,156 @@ async def getHardware(self, hw_id, ctx, hwChannel, build, bname): build['Hardware'] = parts.content return build + async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): + # Example embed + if "Hardware" not in build: + build['Hardware'] = "{ \"desc\":\"Description\", \"fields\": [{\"title\":\"Field\", \"body\":\"Field Body\"}] }" + + hardware = EmbeddedHardware.parse(build['Hardware'].replace(self.embedPrefix, "")) + displayName = DisplayName.name(ctx.author) + + msg = "Your embed currently looks like this:" + msg2 = "To save this build, use `Finalize`. You may use a listed command from below or paste a PCPartPicker link.\n" + msg2 += "(Add Field/Edit Field/Remove Field/Edit Description/Remove Description/Edit Thumbnail/Remove Thumbnail/Finalize/Stop)" + + newTitleMsg = "What would you like the title of this field to be?" + newBodyMsg = "What would you like the body of this field to be?" + newDescMsg = "What would you like the new description to be?" + newThumbnailMsg = "Provide a link to an image you'd like to use" + + embed = discord.Embed() + embed.title = "{}'s {}".format(displayName, bname) + + while True: + embed.description = hardware.description + embed.clear_fields() + + if not hardware.thumbnail == None: + embed.set_thumbnail(url=hardware.thumbnail) + + for x in hardware.fields: + embed.add_field(name=x.title, value=x.body) + + await hwChannel.send(msg) + await hwChannel.send(embed=embed) + parts = await self.prompt(hw_id, ctx, msg2, hwChannel, DisplayName.name(ctx.author), False) + + if not parts: + self._stop_hw(ctx.author) + return + if "finalize" in parts.content.lower(): + build["Hardware"] = self.embedPrefix + hardware.serialize() + return build + elif "add field" in parts.content.lower(): + newTitle = await self.prompt(hw_id, ctx, newTitleMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newTitle: + continue + newBody = await self.prompt(hw_id, ctx, newBodyMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newTitle: + continue + hardware.fields.append(EmbeddedHardwareField(newTitle.content, newBody.content)) + elif "edit field" in parts.content.lower(): + # Get all the titles and append a number in front + fieldList = "Fields:\n" + index = 1 + + for x in hardware.fields: + fieldList += "{}: {}\n".format(index, x.title) + index += 1 + + fieldList += "Which field would you like to edit? Enter in the number of the field" + fieldToEdit = None + + # Loop until we get a valid number + while True: + fieldToEdit = await self.prompt(hw_id, ctx, fieldList, hwChannel, DisplayName.name(ctx.author), False) + + if not fieldToEdit: + break + + # Try to get a number out of the message + try: + index = int(fieldToEdit.content) + except ValueError: + await hwChannel.send("Invalid number. Make sure it is an actual field between 1 and {}".format(len(hardware.fields))) + continue + + # Check field actually exists + if index < 1 or index > len(hardware.fields): + await hwChannel.send("Invalid number. Make sure it is an actual field between 1 and {}".format(len(hardware.fields))) + continue + + # Woah, We actually got a number? + fieldToEdit = hardware.fields[index - 1] + break + + if not fieldToEdit: + continue + + newTitle = await self.prompt(hw_id, ctx, newTitleMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newTitle: + continue + newBody = await self.prompt(hw_id, ctx, newBodyMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newTitle: + continue + + fieldToEdit.title = newTitle.content + fieldToEdit.body = newBody.content + + elif "remove field" in parts.content.lower(): + # Get all the titles and append a number in front + fieldList = "Fields:\n" + index = 1 + + for x in hardware.fields: + fieldList += "{}: {}\n".format(index, x.title) + index += 1 + + fieldList += "Which field would you like to edit? Enter in the number of the field" + fieldToEdit = None + + # Loop until we get a valid number + while True: + fieldToEdit = await self.prompt(hw_id, ctx, fieldList, hwChannel, DisplayName.name(ctx.author), False) + + if not fieldToEdit: + break + + # Try to get a number out of the message + try: + index = int(fieldToEdit.content) - 1 + except ValueError: + await hwChannel.send("Invalid number. Make sure it is an actual field between 1 and {}".format(len(hardware.fields))) + continue + + # Check field actually exists + if index < 1 or index > len(hardware.fields): + await hwChannel.send("Invalid number. Make sure it is an actual field between 1 and {}".format(len(hardware.fields))) + continue + + # Woah, We actually got a number? + del hardware.fields[index] + break + + elif "edit description" in parts.content.lower(): + newDescription = await self.prompt(hw_id, ctx, newDescMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newDescription: + continue + hardware.description = newDescription.content + elif "remove description" in parts.content.lower(): + hardware.description = None + elif "edit thumbnail" in parts.content.lower(): + newThumbnail = await self.prompt(hw_id, ctx, newThumbnailMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newThumbnail: + continue + hardware.thumbnail = newThumbnail.content + elif "remove thumbnail" in parts.content.lower(): + hardware.thumbnail = None + else: + hwChannel.send("Invalid command") + + return None + # New HW helper methods def channelCheck(self, msg, dest = None): if self.stillHardwaring(msg.author) == False: @@ -1115,7 +1314,7 @@ def littleCheck(m): else: return False - async def prompt(self, hw_id, ctx, message, dest = None, author = None): + async def prompt(self, hw_id, ctx, message, dest = None, author = None, confirm = True): # Get author name authorName = None if author: @@ -1168,6 +1367,10 @@ def littleCheck(m): msg = "No problem, *{}!* See you later!".format(authorName, ctx.prefix) await dest.send(msg) return None + + if not confirm: + return talk + # Make sure conf = await self.confirm(hw_id, ctx, talk, dest, "", author) if conf == True: @@ -1179,3 +1382,45 @@ def littleCheck(m): else: # Timed out return None + +class EmbeddedHardware: + + def __init__(self, description, thumbnail, fields): + self.description = description + self.thumbnail = thumbnail + self.fields = fields + + def serialize(self): + serializedFields = [] + for x in self.fields: + serializedFields.append(x.serialize()) + + string = json.dumps({ + "desc": self.description, + "thumbnail": self.thumbnail, + "fields": serializedFields + }, indent=4) + print(string) + return string + + @staticmethod + def parse(hardware): + obj = json.loads(hardware) + + fields = [] + if "fields" in obj: + for field in obj.get("fields"): + fields.append(EmbeddedHardwareField(field.get("title"), field.get("body"))) + + return EmbeddedHardware(obj.get("desc"), obj.get("thumbnail"), fields) + +class EmbeddedHardwareField: + def __init__(self, title, body): + self.title = title + self.body = body + + def serialize(self): + return { + "title": self.title, + "body": self.body, + } \ No newline at end of file From e20101cee9d31ef5647355a26e067b0a50186248 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Tue, 22 Oct 2019 19:15:31 -0700 Subject: [PATCH 3/8] Added some error checking, limiting of number of fields and characters --- Cogs/Hw.py | 128 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 31 deletions(-) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index 316d6e6b..0eae39cb 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -313,16 +313,9 @@ async def edithw(self, ctx, *, build = None): isEmbed = False - # Prompt if user wants to continue using embeds + # Check if it's an embed to change inital msg and launch embed editer if mainBuild["Hardware"].startswith(self.embedPrefix): - # Prompt if user wants to use embeds - msg = '*{}*, we\'ve detected that this is an embed. Would you like to keep this as an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) - embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) - - if not embedConf: - self._stop_hw(ctx.author) - return - isEmbed = embedConf + isEmbed = True msg = "" @@ -691,7 +684,8 @@ async def hw(self, ctx, *, user : str = None, build = None): hardware = EmbeddedHardware.parse(buildParts['Hardware'].replace(self.embedPrefix, "")) embed = discord.Embed() - embed.title = "{}'s {}".format(DisplayName.name(memFromName), buildParts['Name']) + embed.title = "{}'s {}".format(DisplayName.name(memFromName), buildParts['Name']) + embed.color = ctx.author.color embed.description = hardware.description embed.clear_fields() @@ -1045,13 +1039,12 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): msg2 = "To save this build, use `Finalize`. You may use a listed command from below or paste a PCPartPicker link.\n" msg2 += "(Add Field/Edit Field/Remove Field/Edit Description/Remove Description/Edit Thumbnail/Remove Thumbnail/Finalize/Stop)" - newTitleMsg = "What would you like the title of this field to be?" - newBodyMsg = "What would you like the body of this field to be?" newDescMsg = "What would you like the new description to be?" newThumbnailMsg = "Provide a link to an image you'd like to use" embed = discord.Embed() - embed.title = "{}'s {}".format(displayName, bname) + embed.title = "{}'s {}".format(displayName, bname) + embed.color = ctx.author.color while True: embed.description = hardware.description @@ -1066,21 +1059,64 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): await hwChannel.send(msg) await hwChannel.send(embed=embed) parts = await self.prompt(hw_id, ctx, msg2, hwChannel, DisplayName.name(ctx.author), False) - + if not parts: self._stop_hw(ctx.author) return - if "finalize" in parts.content.lower(): + + if "pcpartpicker.com" in parts.content.lower(): + useLinkMsg = "Do you want to use this pcpartpicker link? This will overwrite all of your current hardware fields (y/n/stop)" + useLink = await self.confirm(hw_id, ctx, None, hwChannel, useLinkMsg) + + if not useLink: + continue + + try: + # No formatting please + output = await PCPP.getMarkdown(parts.content) + except: + pass + + if not output: + msg = 'Something went wrong! Make sure you use a valid pcpartpicker link.' + await hwChannel.send(msg) + continue + + newFields = [] + + # Time to parse the already parsed response + for line in output.splitlines(): + if "```" in line or not line: + continue + + parts = line.split(":") + if len(parts) != 2: + continue + + newFields.append(EmbeddedHardwareField(parts[0].strip(), parts[1].strip())) + + # I really doubt this would ever happen, but just in case + if len(newFields) == 0: + await hwChannel.send("There is no information in this link! Ignoring link") + continue + + if len(newFields) > 25: + await hwChannel.send("I appreciate your enthusiasm, but this has too many pieces of hardware. The max I can handle in an embed is *25*, and you are at {}".format(len(newFields))) + + hardware.fields = newFields + + elif "finalize" in parts.content.lower(): build["Hardware"] = self.embedPrefix + hardware.serialize() return build + elif "add field" in parts.content.lower(): - newTitle = await self.prompt(hw_id, ctx, newTitleMsg, hwChannel, DisplayName.name(ctx.author), False) - if not newTitle: - continue - newBody = await self.prompt(hw_id, ctx, newBodyMsg, hwChannel, DisplayName.name(ctx.author), False) - if not newTitle: + if len(hardware.fields) == 25: + await hwChannel.send("There is a max of 25 Fields, you may think of combining some of your fields") continue + + newTitle, newBody = getField(hw_id, ctx, hwChannel) hardware.fields.append(EmbeddedHardwareField(newTitle.content, newBody.content)) + elif "edit field" in parts.content.lower(): # Get all the titles and append a number in front fieldList = "Fields:\n" @@ -1119,12 +1155,8 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): if not fieldToEdit: continue - newTitle = await self.prompt(hw_id, ctx, newTitleMsg, hwChannel, DisplayName.name(ctx.author), False) - if not newTitle: - continue - newBody = await self.prompt(hw_id, ctx, newBodyMsg, hwChannel, DisplayName.name(ctx.author), False) - if not newTitle: - continue + # We have the build now + newTitle, newBody = getField(hw_id, ctx, hwChannel) fieldToEdit.title = newTitle.content fieldToEdit.body = newBody.content @@ -1165,10 +1197,16 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): break elif "edit description" in parts.content.lower(): - newDescription = await self.prompt(hw_id, ctx, newDescMsg, hwChannel, DisplayName.name(ctx.author), False) - if not newDescription: - continue - hardware.description = newDescription.content + newDescription = None + while True: + newDescription = await self.prompt(hw_id, ctx, newDescMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newDescription: + continue + + if len(newDescription.content) > 2048: + await hwChannel.send("Please limit the description to be 2048 characters or less") + hardware.description = newDescription.content + break elif "remove description" in parts.content.lower(): hardware.description = None elif "edit thumbnail" in parts.content.lower(): @@ -1179,10 +1217,38 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): elif "remove thumbnail" in parts.content.lower(): hardware.thumbnail = None else: - hwChannel.send("Invalid command") + await hwChannel.send("Invalid command") return None + async def getField(self, hw_id, ctx, hwChannel): + newTitleMsg = "What would you like the title of this field to be?" + newBodyMsg = "What would you like the body of this field to be?" + + newTitle, newBody = None + + while True: + newTitle = await self.prompt(hw_id, ctx, newTitleMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newTitle: + return + + if len(newTitle.content) > 256: + await hwChannel.send("Can you shorten that a little? The max length for the title is 256 characters, and you are at {}".format(len(newTitle.content))) + continue + break + + while True: + newBody = await self.prompt(hw_id, ctx, newBodyMsg, hwChannel, DisplayName.name(ctx.author), False) + if not newTitle: + return + + if len(newBody.content) > 1024: + await hwChannel.send("Woah that's *impressive*. However, the body of a field must stay below 1024 characters, and you are at {}".format(len(newBody.content))) + continue + break + + return newTitle, newBody + # New HW helper methods def channelCheck(self, msg, dest = None): if self.stillHardwaring(msg.author) == False: From 5118d927a61fde9abc06e1afdf4e40ac069ec3b8 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Tue, 22 Oct 2019 19:35:39 -0700 Subject: [PATCH 4/8] Unbroke the old way of setting hw --- Cogs/Hw.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index 0eae39cb..e7733ace 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -323,7 +323,7 @@ async def edithw(self, ctx, *, build = None): if isEmbed: msg = "Retrieving parts..." else: - msg = '"{}"\'s current parts:'.format(bname) + msg = '__**{}\'s current parts:**__'.format(bname) try: await hwChannel.send(msg) @@ -948,7 +948,7 @@ async def newhw(self, ctx): msg = '*{}*, would you like to make this build an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) - if not embedConf: + if embedConf == None: self._stop_hw(ctx.author) return elif embedConf: From dbac2d836bfb5674d822db9140bd778e1af6cf7e Mon Sep 17 00:00:00 2001 From: Avery Black Date: Tue, 22 Oct 2019 19:43:05 -0700 Subject: [PATCH 5/8] Somehow embeds still send even if they are overfilled...wack. Shouldn't happen anymore though --- Cogs/Hw.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index e7733ace..d9f9a884 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -1101,7 +1101,8 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): continue if len(newFields) > 25: - await hwChannel.send("I appreciate your enthusiasm, but this has too many pieces of hardware. The max I can handle in an embed is *25*, and you are at {}".format(len(newFields))) + await hwChannel.send("I appreciate your enthusiasm, but this has too many pieces of hardware. The max I can handle in an embed is *25*, and you are at {}".format(len(newFields))) + continue hardware.fields = newFields From fff309d396268b979e0f7b40a889348877d2ffee Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 25 Oct 2019 09:15:57 -0700 Subject: [PATCH 6/8] Fixed wording on too many fields --- Cogs/Hw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index d9f9a884..de249b54 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -1101,7 +1101,7 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): continue if len(newFields) > 25: - await hwChannel.send("I appreciate your enthusiasm, but this has too many pieces of hardware. The max I can handle in an embed is *25*, and you are at {}".format(len(newFields))) + await hwChannel.send("I appreciate your enthusiasm, but this has too many pieces of hardware. The max I can handle in an embed is *25*, and there are {}".format(len(newFields))) continue hardware.fields = newFields From dfaaa3c98cc25c42245d1cfb2097d143160274ce Mon Sep 17 00:00:00 2001 From: Avery Black Date: Thu, 31 Oct 2019 20:18:33 -0700 Subject: [PATCH 7/8] Error checking is good --- Cogs/Hw.py | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index 23f0dbbf..68aa2335 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -832,12 +832,25 @@ async def newhw(self, ctx): if hwChannel == ctx.author and ctx.channel != ctx.author.dm_channel: await ctx.message.add_reaction("📬") - msg = '*{}*, tell me what you\'d like to call this build (type stop to cancel):'.format(DisplayName.name(ctx.author)) + # Prompt if user wants to use embeds + msg = '*{}*, would you like to make this build an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) + embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) + + if embedConf == None: + self._stop_hw(ctx.author) + return + + msg = '*{}*, tell me what you\'d like to call this build (type stop to cancel):'.format(DisplayName.name(ctx.author)) + # Get the build name newBuild = { 'Main': True } while True: buildName = await self.prompt(hw_id, ctx, msg, hwChannel, DisplayName.name(ctx.author)) + if embedConf and len(buildName.content) > 230: + await hwChannel.send("This title is too long. It needs to be under 230 characters, and you are at {} characters.".format(len(buildName.content))) + continue + if not buildName: self._stop_hw(ctx.author) return @@ -853,15 +866,7 @@ async def newhw(self, ctx): break bname = Utils.suppressed(ctx,buildName.content) - - # Prompt if user wants to use embeds - msg = '*{}*, would you like to make this build an embed? (y/n/stop)'.format(DisplayName.name(ctx.author)) - embedConf = await self.confirm(hw_id, ctx, None, hwChannel, msg) - - if embedConf == None: - self._stop_hw(ctx.author) - return - elif embedConf: + if embedConf: newBuild = await self.getEmbeddedHardware(hw_id, ctx, hwChannel, newBuild, bname) else: newBuild = await self.getHardware(hw_id, ctx, hwChannel, newBuild, bname) @@ -949,13 +954,16 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): msg2 = "To save this build, use `Finalize`. You may use a listed command from below or paste a PCPartPicker link.\n" msg2 += "(Add Field/Edit Field/Remove Field/Edit Description/Remove Description/Edit Thumbnail/Remove Thumbnail/Finalize/Stop)" - errMsg = "The embed cannot be displayed! Make sure your thumbnail total is under 6000 characters (you may need to remove fields or edit them) and that your thumbnail URL is valid.\n" + errMsg = "The embed cannot be displayed! Make sure your thumbnail total is under 6000 characters (you may need to remove fields or edit them).\n" errMsg += "__This build *cannot* be finalized with the `Finalize` command until this is fixed.__" newDescMsg = "What would you like the new description to be?" newThumbnailMsg = "Provide a link to an image you'd like to use. It must start with `http` or `https`" while True: + # Reset Failure + failure = False + embed = discord.Embed() embed.title = "{}'s {}".format(displayName, bname) embed.color = ctx.author.color @@ -973,11 +981,20 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): try: await hwChannel.send(msg, embed=embed) except HTTPException as exception: + # Thumbnail is invalid - remove it and print it out if "Not a well formed URL." in exception.args[0]: - await hwChannel.send("__Thumbnail has an invalid link.__ Please set a new thumbnail link or remove it") + await hwChannel.send("__Thumbnail link removed.__ Thumbnail link was invalid and prevented the embed from forming correctly") + + # Bad + embed._thumbnail = None + + hardware.thumbnail = None + await hwChannel.send(embed=embed) else: await hwChannel.send(errMsg) - failure = True + # Prevent finalization since it's likely longer than 6000 characters + failure = True + parts = await self.prompt(hw_id, ctx, msg2, hwChannel, DisplayName.name(ctx.author), False) @@ -1128,10 +1145,11 @@ async def getEmbeddedHardware(self, hw_id, ctx, hwChannel, build, bname): while True: newDescription = await self.prompt(hw_id, ctx, newDescMsg, hwChannel, DisplayName.name(ctx.author), False) if not newDescription: - continue + break if len(newDescription.content) > 2048: await hwChannel.send("Please limit the description to be 2048 characters or less") + continue hardware.description = newDescription.content break elif "remove description" in parts.content.lower(): @@ -1164,7 +1182,7 @@ async def getField(self, hw_id, ctx, hwChannel): return if len(newTitle.content) > 256: - await hwChannel.send("Can you shorten that a little? The max length for the title is 256 characters, and you are at {}".format(len(newTitle.content))) + await hwChannel.send("The max length for the title is 256 characters, and you are at {}".format(len(newTitle.content))) continue break @@ -1174,7 +1192,7 @@ async def getField(self, hw_id, ctx, hwChannel): return if len(newBody.content) > 1024: - await hwChannel.send("Woah that's *impressive*. However, the body of a field must stay below 1024 characters, and you are at {}".format(len(newBody.content))) + await hwChannel.send("The body of a field must stay below 1024 characters, and you are at {}".format(len(newBody.content))) continue break @@ -1388,7 +1406,7 @@ def serialize(self): "thumbnail": self.thumbnail, "fields": serializedFields }, indent=4) - + return string @staticmethod From 615f5ec6f9c21440446c122804a86758fde39081 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 21 Mar 2020 21:02:16 -0700 Subject: [PATCH 8/8] Fixed w/ Master This will probably still conflict, unfortunately - but it should work. --- Cogs/Hw.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cogs/Hw.py b/Cogs/Hw.py index 68aa2335..9f409890 100644 --- a/Cogs/Hw.py +++ b/Cogs/Hw.py @@ -7,6 +7,7 @@ def setup(bot): # Add the bot and deps settings = bot.get_cog("Settings") bot.add_cog(Hw(bot, settings)) + # This is the Uptime module. It keeps track of how long the bot's been up @@ -21,6 +22,9 @@ def __init__(self, bot, settings): # Something stupid that no one would ever actually use... self.embedPrefix = "^^&&^^&&" + global Utils, DisplayName + Utils = self.bot.get_cog("Utils") + DisplayName = self.bot.get_cog("DisplayName") def gen_id(self):