async def startMassSpeedsSession(self, ctx): """ Callable function to begin a mass speeds session. Initializes the participant list and creates a reactable message """ usersMessage = ctx.message await usersMessage.delete() fname = "guildsettings/" + ctx.guild.name.replace(" ", "") + ".json" settings = jsonHandling.loadJSON(fname) if "msActive" in settings.keys(): if settings["msActive"] == False: message = await ctx.send( "React to this message to join the mass speeds session.") self.messageID = message self.message = message await message.add_reaction("<a:EB:744967488751665303>") settings["msActive"] = True elif settings["msActive"] == True: await ctx.send("MS session already running!") else: settings["msActive"] = True MSfname = "massSpeeds/" + ctx.guild.name.replace(" ", "") + ".json" jsonHandling.dumpJSON(MSfname, {}) jsonHandling.dumpJSON(fname, settings)
async def renameVouchee(self, ctx, user: str, newName: str): """ Callable function for an admin to rename a vouchee in the system Parameters: user - String of the name of the vouchee/antivouchee in the system newName - String of the new name to use """ print( "------------------------------ beginning renameVouchee() ------------------------------" ) if self.whitelistCheck(ctx) == False: await ctx.send("This command is not allowed in this channel.") fname = "vouches/" + ctx.guild.name.replace(" ", "") + ".json" vouches = jsonHandling.loadJSON(fname) data = vouches.pop(user.lower()) vouches[newName.lower()] = data jsonHandling.dumpJSON(fname, vouches) await ctx.send("Rename complete.") print( "------------------------------ ending renameVouchee() ------------------------------" )
async def updatingmessage(self, ctx): """ Callable function to create a table that can be filled with vouches """ print( "------------------------------ beginning updatingmessage() ------------------------------" ) # delete the senders message usersMessage = ctx.message await usersMessage.delete() # create a new message and send it message = await ctx.send(embed=discord.Embed( title="Type update message to initalise me.")) # store the details of the sent message updatingVouchMessage = { "messageID": message.id, "channelID": message.channel.id } # load server settings fname = "guildsettings/" + ctx.guild.name.replace(" ", "") + ".json" settings = jsonHandling.loadJSON(fname) # update details of updating vouch message settings["updatingVouchMessage"] = updatingVouchMessage # save details jsonHandling.dumpJSON(fname, settings) print( "------------------------------ ending updatingmessage() ------------------------------" )
def joinMassSpeeds(self, guild, member): """ Adds member to the list of active participants. Triggered by reacting to the emote in the bot message Parameters: Member - Discord ID for the user who reacted """ MSfname = "massSpeeds/" + guild.name.replace(" ", "") + ".json" players = jsonHandling.loadJSON(MSfname) players[str(member.id)] = 0 jsonHandling.dumpJSON(MSfname, players)
async def resetMassSpeeds(self, ctx): """ Callable function to reset the Mass Speeds Session """ fname = "guildsettings/" + ctx.guild.name.replace(" ", "") + ".json" settings = jsonHandling.loadJSON(fname) settings["msActive"] = False jsonHandling.dumpJSON(fname, settings) MSfname = "massSpeeds/" + ctx.guild.name.replace(" ", "") + ".json" jsonHandling.dumpJSON(MSfname, {})
def leaveMassSpeeds(self, guild, member): """ Remove member from the list of active participants. Triggered by removing reaction to the emote in the bot message Parameters: Member - Discord ID for the user who reacted """ # remove participant from the JSON file MSfname = "massSpeeds/" + guild.name.replace(" ", "") + ".json" players = jsonHandling.loadJSON(MSfname) players.pop(str(member.id)) jsonHandling.dumpJSON(MSfname, players)
async def unvouch(self, ctx, user: str): """ Callable function for a DGS rank to unvouch someone they previously unvouched Parameters: user - string of the name of the vouchee *argv - additional arguments. Intended as a description of the reasoning for a antivouch """ print( "------------------------------ beginning unvouch() ------------------------------" ) if self.whitelistCheck(ctx) == False: await ctx.send("Cannot do that in this channel") return try: user = user.lower() fname = "vouches/" + ctx.guild.name.replace(" ", "") + ".json" vouches = jsonHandling.loadJSON(fname) print(vouches) authorName = str(ctx.author.id) if user not in vouches.keys() or ( user in vouches.keys() and authorName not in vouches[user]["vouchers"]): await ctx.send("You haven't vouched them.") if user in vouches.keys( ) and authorName in vouches[user]["vouchers"]: vouches[user]['vouches'] = vouches[user]['vouches'] - vouches[ user]['vouchers'][authorName]['value'] if vouches[user]['vouches'] <= 0: ctx.send( "Vouchee is at 0 or below - removing from vouch list") await self.removeUser(ctx, user) else: del vouches[user]['vouchers'][authorName] jsonHandling.dumpJSON(fname, vouches) await ctx.send("Vouch successfully removed.") except Exception as e: print(e) traceback.print_exc(file=sys.stdout) print( "------------------------------ ending unvouch() ------------------------------" )
def addBuffer(serverName, bufferType, data): """ Helper function to add arbitrary data to the buffer you specify. Assigns a unique ID for the data within that buffer Parameters: bufferType - string name of the buffer to add to: for example, "vouches" data - data to add to the buffer """ # generate filename of settings file settingsFileName = "guildsettings/" + serverName + ".json" # load settings info if os.path.exists(settingsFileName): settings = jsonHandling.loadJSON(settingsFileName) else: settings = {} # determine which ID to grab IDType = bufferType + "IDcounter" # get unique ID of new buffer item try: ID = settings[IDType] settings[IDType] = settings[IDType] + 1 except Exception as e: print(e) ID = 1 settings[IDType] = ID + 1 # update settings file jsonHandling.dumpJSON(settingsFileName, settings) # generate filename of buffer file for this server + buffer type buffername = "buffers/" + serverName + bufferType + ".json" print("buffername", buffername) # load buffer if os.path.exists(buffername): testBuffer = jsonHandling.loadJSON(buffername) else: testBuffer = {} # add data to the buffer at correct ID testBuffer[ID] = data # save the buffer data jsonHandling.dumpJSON(buffername, testBuffer) return
def removeBuffer(serverName, bufferType, bufferNo: int): """ Helper function to remove an entry from a buffer Parameters: bufferType - string name of the buffer to view: for example, "vouches" bufferNo - integer ID of the buffer entry to delete """ buffername = "buffers/" + serverName + bufferType + ".json" testBuffer = jsonHandling.loadJSON(buffername) if bufferNo == 0: for x in list(testBuffer): del testBuffer[x] else: del testBuffer[bufferNo] jsonHandling.dumpJSON(buffername, testBuffer) return
async def removeUser(self, ctx, user: str): """ Callable function for an admin to remove a vouchee from the system Parameters: user - String of the name of the vouchee/antivouchee """ print( "------------------------------ beginning viewVouchBuffer() ------------------------------" ) if self.whitelistCheck(ctx) == False: await ctx.send("This command is not allowed in this channel.") else: fname = "vouches/" + ctx.guild.name.replace(" ", "") + ".json" vouches = jsonHandling.loadJSON(fname) del vouches[user.lower()] jsonHandling.dumpJSON(fname, vouches) await ctx.send(user + " was completely removed from the vouch list.") print( "------------------------------ ending viewVouchBuffer() ------------------------------" )
def findNames(self, ctx): def equal(im1, im2): return ImageChops.difference(im1, im2).getbbox() is None def fuzzyEqual(im1, im2): im1 = np.array(im1) im2 = np.array(im2) err = np.sum((im1.astype("float") - im2.astype("float"))**2) err /= float(im1.shape[0] * im1.shape[1]) return err def findRow(zero, time, charName): (glwidth, glheight) = zero.width, zero.height (twidth, theight) = time.width, time.height for x in range(twidth - glwidth): for y in range(theight - glheight): im = time.crop((x, y, x + glwidth, y + glheight)) if fuzzyEqual(im, zero) < 0.05: charDict = { "character": charName, "charLength": glwidth } fullTime[x] = charDict mainX = x mainY = y im.save("test/" + str(x) + " " + str(y) + ".png") return True, mainX, mainY mainX = 0 mainY = 0 return False, mainX, mainY def decoder(fullTime): timeDictList = (sorted(fullTime)) timeStr = "" prevX = 0 for x in timeDictList: if (x - prevX > 3 and prevX > 0): timeStr = timeStr + " " + str(fullTime[x]["character"]) elif x - prevX < 0: continue else: timeStr = timeStr + str(fullTime[x]["character"]) prevX = int(x) + int(fullTime[x]["charLength"]) return timeStr def findNonZeros(filepath, fullTime, glwidth, glheight, k): zero = Image.open(filepath) zero = zero.convert('1') (glwidth, glheight) = zero.width, zero.height for x in range(0, twidth - glwidth + 1): im = time.crop((x, rowY, x + glwidth, rowY + glheight)) if fuzzyEqual(im, zero) < 0.05: charDict = {"character": k, "charLength": glwidth} fullTime[x] = charDict return fullTime chars = { "u": "charGlyph/glyphLowerU.png", "n": "charGlyph/glyphLowerN.png", "t": "charGlyph/glyphLowerT.png", "e": "charGlyph/glyphLowerE.png", "r": "charGlyph/glyphLowerR.png", "d": "charGlyph/glyphLowerD.png", "x": "charGlyph/glyphLowerX.png", "p": "charGlyph/glyphLowerP.png", "a": "charGlyph/glyphLowerA.png", "l": "charGlyph/glyphLowerL.png", "i": "charGlyph/glyphLowerI.png", "o": "charGlyph/glyphLowerO.png", "s": "charGlyph/glyphLowerS.png", "f": "charGlyph/glyphLowerF.png", "m": "charGlyph/glyphLowerM.png", "k": "charGlyph/glyphLowerK.png", "g": "charGlyph/glyphLowerG.png", "y": "charGlyph/glyphLowerY.png", "w": "charGlyph/glyphLowerW.png", "h": "charGlyph/glyphLowerH.png", "b": "charGlyph/glyphLowerB.png", "c": "charGlyph/glyphLowerC.png", "q": "charGlyph/glyphLowerQ.png", "z": "charGlyph/glyphLowerZ.png", "v": "charGlyph/glyphLowerV.png", "j": "charGlyph/glyphLowerJ.png", "H": "charGlyph/glyphCapH.png", "Q": "charGlyph/glyphCapQ.png", "C": "charGlyph/glyphCapC.png", "D": "charGlyph/glyphCapD.png", "S": "charGlyph/glyphCapS.png", "G": "charGlyph/glyphCapG.png", "O": "charGlyph/glyphCapO.png", "E": "charGlyph/glyphCapE.png", "T": "charGlyph/glyphCapT.png", "Y": "charGlyph/glyphCapY.png", "K": "charGlyph/glyphCapK.png", "B": "charGlyph/glyphCapB.png", "F": "charGlyph/glyphCapF.png", "M": "charGlyph/glyphCapM.png", "I": "charGlyph/glyphCapI.png", "U": "charGlyph/glyphCapU.png", "R": "charGlyph/glyphCapR.png", "P": "charGlyph/glyphCapP.png", "X": "charGlyph/glyphCapX.png", "W": "charGlyph/glyphCapW.png", "V": "charGlyph/glyphCapV.png", "Z": "charGlyph/glyphCapZ.png", "A": "charGlyph/glyphCapA.png", "L": "charGlyph/glyphCapL.png", "M": "charGlyph/glyphCapM.png", "N": "charGlyph/glyphCapN.png", "P": "charGlyph/glyphCapP.png", "J": "charGlyph/glyphCapJ.png", "1": "charGlyph/glyphName1.png", "2": "charGlyph/glyphName2.png", "3": "charGlyph/glyphName3.png", "4": "charGlyph/glyphName4.png", "5": "charGlyph/glyphName5.png", "6": "charGlyph/glyphName6.png", "7": "charGlyph/glyphName7.png", "8": "charGlyph/glyphName8.png", "9": "charGlyph/glyphName9.png", "0": "charGlyph/glyphName0.png" } namesFound = [] times = [] for file in os.listdir("./character"): times.append(file) for t in times: name = "Couldn't find name" fullTime = {} fname = "character/" + t time = Image.open(fname) enhancer = ImageEnhance.Contrast(time) time = enhancer.enhance(2) (twidth, theight) = time.width, time.height time = time.convert('1') rows, cols = time.size for i in range(1, rows - 1): for j in range(1, cols - 1): amt = (time.getpixel((i - 1, j)) + time.getpixel( (i + 1, j)) + time.getpixel( (i, j - 1)) + time.getpixel( (i, j + 1)) + time.getpixel( (i + 1, j - 1)) + time.getpixel( (i + 1, j + 1)) + time.getpixel( (i - 1, j - 1)) + time.getpixel( (i, j + 1))) if amt == 0: time.putpixel((i, j), 0) time.save("ahh/" + t + "test.png") matchFound = False for k, v in chars.items(): zero = Image.open(v) zero = zero.convert('1') matchFound, rowX, rowY = (findRow(zero, time, k)) if matchFound == True: break (glwidth, glheight) = zero.width, zero.height if rowX == 0: print("Couldn't find name") for x in range(rowX + 1, twidth - glwidth + 1): im = time.crop((x, rowY, x + glwidth, rowY + glheight)) if equal(im, zero): fullTime[x] = 0 for k, v in chars.items(): fullTime = findNonZeros(v, fullTime, glwidth, glheight, k) name = decoder(fullTime) fname = "names/names.json" namesDict = jsonHandling.loadJSON(fname) # print(self.getNames()) # possibleDgers = list(namesDict) possibleDgers = [] for x in self.getNames(): possibleDgers.append(x[0]) if name in possibleDgers: print(fname[:-4], name) elif name is None: print(fname[:-4], "NA") continue else: closestMatch = difflib.get_close_matches(name, possibleDgers) if len(closestMatch) > 0: print(fname[:-4], closestMatch[0]) name = closestMatch[0] else: print(fname[:-4], "NA") if name == None: name = "None found" elif len(name) > 0: jsonHandling.dumpJSON(fname, namesDict) print("name=====", name) namesFound.append(name) else: namesFound.append("None") return namesFound
async def formTeams(self, ctx): """ Callable function to creates teams based on active participants, rank values and then outputs those teams into the server """ usersMessage = ctx.message await usersMessage.delete() MSfname = "massSpeeds/" + ctx.guild.name.replace(" ", "") + ".json" fname = "guildsettings/" + ctx.guild.name.replace(" ", "") + ".json" settings = jsonHandling.loadJSON(fname) if "msActive" not in settings.keys(): await ctx.send( "No mass speeds session in progress. <a:EB:744967488751665303> (Not in settings)" ) return if settings["msActive"] == False: await ctx.send( "No mass speeds session in progress. <a:EB:744967488751665303> (MS Session = False)" ) return if len(self.teamMessages) > 0: for x in range(len(self.teamMessages)): msg = self.teamMessages.pop() await msg.delete() players = jsonHandling.loadJSON(MSfname) MSrole = get(ctx.guild.roles, name="Mass Speeds") playersValue = {} toBeRemoved = [] for x in players.keys(): member = ctx.guild.get_member(int(x)) if MSrole in member.roles: value = self.rankValue(getRoles(member.roles)) if member.nick == None: playersValue[member.name] = value else: playersValue[member.nick] = value else: toBeRemoved.append(x) for x in toBeRemoved: players.pop(str(x)) jsonHandling.dumpJSON(MSfname, players) teams, leftovers = self.runRandomMassSpeeds(playersValue) for k, v in teams.items(): team = discord.Embed() message = "" for x in v: message = message + x + "\n" team.add_field(name=k, value=message, inline=False) messageSent = await ctx.send(embed=team) self.teamMessages.append(messageSent) message = "" if len(leftovers) > 0: for x in leftovers: message = message + x + "\n" else: message = "None" leftovers = discord.Embed() leftovers.add_field(name="Leftovers", value=message) messageSent = await ctx.send(embed=leftovers) self.teamMessages.append(messageSent)
async def acceptVouch(self, ctx, vouchID: str, silent=False): """ Callable function for admin's to accept a vouch from the buffer based on ID Parameters: vouchID - String representing the vouch to accept silent - Boolean indicating whether or not to get verbose information """ try: print( "------------------------------ beginning acceptVouch() ------------------------------" ) # Message to be printed out at the end. message = "Vouch complete!" # get data for this vouchID vouchData = bufferHandling.getBufferData( ctx.guild.name.replace(" ", ""), "vouches", vouchID) # get vouches data fname = "vouches/" + ctx.guild.name.replace(" ", "") + ".json" vouches = jsonHandling.loadJSON(fname) # add the vouch to the vouch datastore vouches = self.addVouchee(vouchData["vouchInfo"]["user"], vouches) # Remove any instances of this person already vouching/anti'ing the vouchee # We will update with their new information (new vouch/anti and rank value) try: del vouches[vouchData["vouchInfo"]["user"]]["antivouchers"][ vouchData["voucherInfo"]["voucher"]] print("removing exisiting antivouch entry") except: pass try: del vouches[vouchData["vouchInfo"]["user"]]["vouchers"][ vouchData["voucherInfo"]["voucher"]] print("removing exisiting vouch entry") except: pass # add the voucher info to the vouch datastore # if it's a vouch if vouchData["vouchInfo"]["vouchType"] == "vouch": vouches[vouchData["vouchInfo"]["user"]]["vouchers"][vouchData[ "voucherInfo"]["voucher"]] = vouchData["voucherInfo"] # if it's an antivouch elif vouchData["vouchInfo"]["vouchType"] == "antivouch": vouches[vouchData["vouchInfo"]["user"]]["antivouchers"][ vouchData["voucherInfo"] ["voucher"]] = vouchData["voucherInfo"] # Update the number of vouches numVouches = 0 for voucher in vouches[vouchData["vouchInfo"]["user"]]['vouchers']: numVouches += vouches[vouchData["vouchInfo"] ["user"]]['vouchers'][voucher]['value'] for antivoucher in vouches[vouchData["vouchInfo"] ["user"]]['antivouchers']: numVouches -= vouches[vouchData["vouchInfo"]["user"]][ 'antivouchers'][antivoucher]['value'] # Add to dict vouches[vouchData["vouchInfo"]["user"]]["vouches"] = max( numVouches, 0) #c heck if user has been vouched to 0 and remove if so if vouches[vouchData["vouchInfo"]["user"]]["vouches"] == 0: del vouches[vouchData["vouchInfo"]["user"]] message = ("Reached 0 vouches. Removed " + vouchData["vouchInfo"]["user"]) silent = False # save vouch data jsonHandling.dumpJSON(fname, vouches) # remove vouch from buffer bufferHandling.removeBuffer(ctx.guild.name.replace(" ", ""), "vouches", vouchID) # await self.updateMessage(ctx) if silent == False: await ctx.send(message) else: return print( "------------------------------ ending acceptVouch() ------------------------------" ) except KeyError: await ctx.send("No vouch with ID:" + vouchID + " exists in the buffer.") except Exception as e: print(e) traceback.print_exc(file=sys.stdout)