async def changestatus(self, ctx, statType, *, status): #creates the action that the bot is doing based on input if statType.lower() == 'watching': customAct = discord.Activity(type=discord.ActivityType.watching, name=status) elif statType.lower() == 'listening': customAct = discord.Activity(type=discord.ActivityType.listening, name=status) elif statType.lower() == 'playing': customAct = discord.Game(status) #if the inputted action is not on the valid list, inform user and give valid examples else: await ctx.send( f'Sorry {ctx.author.mention}, but I need to be playing, watching or listening to something\nE.g: `.changestatus playing Mario` means that I can play Mario! :smile:' ) return #changes the status of the bot await self.client.change_presence(status=discord.Status.idle, activity=customAct) #informs the console of the change and adds data to "usage.json" ConsoleMessage( f'{ctx.author} changed the status to {statType} {status}') add_usage("status changes")
async def _8ball(self, ctx, *, question): #all possible responses for the 8ball responses = [ 'It is certain.', 'It is decidedly so.', 'Without a doubt.', 'Yes - definitely.', 'You may rely on it.', 'As I see it, yes.', 'Most likely.', 'Outlook good.', 'Yes.', 'Signs point to yes.', 'Reply hazy, try again.', 'Ask again later.', 'Better not tell you now.', 'Cannot predict now.', 'Concentrate and ask again.', 'Don\'t count on it.', 'My reply is no.', 'My sources say no.', 'Outlook not so good.', 'Very doubtful.'] #will send a message to the server with the asked question and a random response from the above list await ctx.send(f'{ctx.author.mention}\nQuestion: {question}\nAnswer: {random.choice(responses)}') #will add number of uses to "usage.json" add_usage("fortunes told")
async def endpoll(self,ctx): voted = False try: with open(f'{PATH}\\data\\polls\\poll{ctx.channel.id}.json','r') as f: stats = json.load(f) except: await ctx.send(f'There doesn\'t seem to be any active polls in this channel {ctx.author.mention}.') return stats["finished"] = str(datetime.now().strftime("%d-%m-%Y %H;%M;%S")) stats["Ending Author"] = str(ctx.author) stats["Ending AuthorID"] = ctx.author.id with open(f'{PATH}\\data\\polls\\archived polls\\poll {stats["started"]} #{ctx.channel}.json','w') as f: json.dump(stats,f,indent=4) os.remove(f'{PATH}\\data\\polls\\poll{ctx.channel.id}.json') ConsoleMessage(f'{ctx.author} has ended the poll for {stats["question"]} in #{ctx.channel}') out = f'Hey @everyone!\nThe poll `{stats["question"]}` has ended!\nThe results are:' for item in stats["options"]: if item["votes"] != 0: voted = True out += f'\n\t\t`{item["name"]}` with {item["votes"]} ' if item["votes"] == 1: out += 'vote!' else: out += 'votes!' if voted: add_usage("polls ended with votes") out += '\n\nThank you everyone for voting! :smile:' else: add_usage("polls ended without votes") out += '\n\nLooks like nobody wanted to vote today... :cry:' await ctx.send(out)
async def vote(self, ctx, *,value): if value.lower() == 'a real number' or value.lower() == 'real number': await ctx.send(f'Sorry {ctx.author.mention}, but you need to put...ha.ha.ha.') return try: with open(f'{PATH}\\data\\polls\\poll{ctx.channel.id}.json','r') as f: stats = json.load(f) except: await ctx.send(f'There doesn\'t seem to be any active polls in this channel {ctx.author.mention}. If you have any suggestions then feel free to put them in #suggestions') return try: val = int(value) if val < 1: await ctx.send(f'Sorry {ctx.author.mention}, but I don\'t think {val} is an actual option') return except: await ctx.send(f'Sorry {ctx.author.mention}, but you need to put a real number after the `.vote `') return userVoted = False for user in stats["voters"]: if user["id"] == ctx.author.id: userVoted = True for item in user["choices"]: if item == val: await ctx.send(f'Sorry {ctx.author.mention}, but you have already voted for this!') return if len(user["choices"]) >= stats["limit"]: await ctx.send(f'Sorry {ctx.author.mention}, but it looks like you have used the maximum number of votes for this poll!') return else: try: stats["options"][val-1]["votes"] += 1 user["choices"].append(val) break except: await ctx.send(f'Sorry {ctx.author.mention}, but there isn\'t really a number {val} option.\nHere, have a look at what\'s avaliable with `.pollstats`') return if userVoted == False: try: stats["options"][val-1]["votes"] += 1 voter = {} voter["name"] = str(ctx.author) voter["id"] = ctx.author.id voter["choices"] = [val] stats["voters"].append(voter) except: await ctx.send(f'Sorry {ctx.author.mention}, but there isn\'t really a number {val} option.\nHere, have a look at what\'s avaliable with `.pollstats`') return stats["total votes"] += 1 with open(f'{PATH}\\data\\polls\\poll{ctx.channel.id}.json','w') as f: json.dump(stats,f,indent=4) add_usage("total votes") await ctx.message.delete() ConsoleMessage(f'{ctx.author} voted for "{stats["options"][val-1]["name"]}" in poll for "{stats["question"]}" on channel #{ctx.channel.name}') await ctx.send(f'Thank you for voting {ctx.author.mention}! :smile:')
async def startpoll(self, ctx, question, limit, *, options): #This chunk of code is entirelly for common typos and users trying to mess with formatting question.replace('`','') question.replace('\n',' ') question.replace('\t',' ') #question = ' '.join(question) options.replace('`','') options.replace('\t',' ') options.replace('\n',' ') #options = ' '.join(options) if options.endswith('.+'): options = options[:-2] if options.endswith(' .+'): options = options[:-3] if options.startswith('.+'): options = options[2:] if options.startswith(' .+'): options = options[3:] #if the maxumum vote limit is set to 0 or below, a message is sent and the function ends if int(limit) < 1: await ctx.send(f'Hmmm...I think that people might want more than {limit} votes :sweat_smile:') return #opts = [] out = f'@everyone\nPoll started by {ctx.author.mention}:\n\n{question}' #tmp = options.split('.+') i = 1 opts = options.split('.+') for item in opts:#tmp:: if item.isspace(): del item pass out += f'\n\t`.vote {i}` for `{item}`' # opts.append(item) i += 1 if len(opts) <= 1:#tmp) <= 1: await ctx.send(f'Hmmm...I think people like more options than that') return if int(limit) > len(opts): limit = str(len(opts)) out += f'\n\n(Note: you are only allowed {limit} ' if int(limit) == 1: out += 'vote)' else: out += 'votes)' out += '\nTo see percentages for votes, type `.pollstats`\nTo see your previous votes in this poll, type `.myvotes`' if self.createpolljson(ctx, question, limit, opts): ConsoleMessage(f'{ctx.author} has created a new poll: "{question}" in #{ctx.channel.name} with options: {opts}') await ctx.message.delete() await ctx.send(out) add_usage("polls started") else: await ctx.message.delete() await ctx.send(f'Sorry {ctx.author.mention}, but there is still an ongoing poll in this channel. You can cancel it with .pollend')
async def clear(self, ctx, amount=1): await ctx.channel.purge(limit=amount + 1) #informs the console of the changes and adds to clear counter in "usage.json" if amount > 1: ConsoleMessage( f'{ctx.author} cleared {amount} messages from channel #{ctx.channel.name}' ) add_usage("messages cleared", amount) elif amount == 1: ConsoleMessage( f'{ctx.author} cleared 1 message from channel #{ctx.channel.name}' ) add_usage("messages cleared")
def rollSingleDice(self,ctx,dice_val): #checks that a valid option (2,4,8,10,12,20,100) has been entered if (dice_val == 2) or (dice_val == 4) or (dice_val == 6) or (dice_val == 8) or (dice_val == 10) or (dice_val == 12) or (dice_val == 20) or (dice_val == 100): #if dice is two sided, it is a coin if dice_val == 2: #adds to coin stats in "usage.json" add_usage("times coins used") add_usage("total coins used") #will randomise outcome and produce either heads or tails if (random.randint(0,1) == 0): out = 'heads' else: out = 'tails' #message that will be sent to the server out = f'{ctx.author.mention} flipped a coin and got `{out}`' #if it is not 2 sided else: #will add to dice stats in "usage.json" add_usage("times dice used") add_usage("total dice used") #will produce a random number between 1 to the maximum value on the dice randval = random.randint(1,dice_val) #custom message for rolling a 1 on a 20 sided dice if randval == 1 and dice_val == 20: out = f'{ctx.author.mention} rolled a `natural 1` on a `d20`...' #custom message for rolling a 20 on a 20 sided dice elif randval == 20 and dice_val == 20: out = f'{ctx.author.mention} rolled a `natural 20` on a `d20`!' #if not 1 or 20 on a 20 sided dice, will produce the default message else: out = f'{ctx.author.mention} rolled `{randval}` on a `d{dice_val}`' #if it is not a 2,4,6,8,10,12,20 or 100 sided dice; will inform user of invalid input else: out = f'Hmmm...I don\'t think that\'s a real dice {ctx.author.mention}.\nTry one of these dice: `.d2, .d4, .d6, .d8, .d10, .d12, .d20, .d100`' return out
async def roll(self, ctx, dice): #if the user does not specify the number of dice to use, will only use one if dice.startswith('d'): out = self.rollSingleDice(ctx,int(dice[1:])) #otherwise will split the input into a list based on 'd', so 2d6 will become [2,6] else: vals = dice.split('d') out = '' #if there are only 2 items in the list (prevents bad input) if len(vals) == 2: #the first value is taken as the number of dice to roll number = int(vals[0]) #the second value is taken as the number of sides to the dice dice_val = int(vals[1]) #if the number of dice is one, roll one dice if number == 1: out = self.rollSingleDice(ctx,int(vals[1])) #if the user would like to roll multiple dice (max 30) elif number > 1 and number < 31: #checks that a valid option (2,4,8,10,12,20,100) has been entered for the sides of the dice if (dice_val == 2) or (dice_val == 4) or (dice_val == 6) or (dice_val == 8) or (dice_val == 10) or (dice_val == 12) or (dice_val == 20) or (dice_val == 100): #if it is 2 sided, it is considered as a coin if (dice_val == 2): #adds to coin stats in "usage.json" add_usage("times coins used") add_usage("total coins used",number) #counter for number of each output heads = 0 tails = 0 #output message initialised out = f'{ctx.author.mention} flipped {number} coins and got:\n' #will randomise the output of either "heads" or "tails" and add to the counters for number of times specified for i in range(number): if random.randint(0,1) == 0: out += '`heads`' heads += 1 else: out += '`tails`' tails += 1 if i != number-1: out += ', ' #has a final counter for the total of each output out += f'\n{heads} heads and {tails} tails' #if it is not a coin else: #adds to the dice stats in "usage.json" add_usage("times dice used") add_usage("total dice used",number) #initialises the total values rolled counter total = 0 #initialises the output message out = f'{ctx.author.mention} rolled {number}d{dice_val}\'s and got:\n' #generated a random dice roll, adds the roll to the output and to the total for i in range(number): add = random.randint(1,dice_val) #if the randomly rolled value is either a 20 or 1 on a d20, add data to "usage.json" if add == 20 and dice_val == 20: add_usage("natural 20's") elif add == 1 and dice_val == 20: add_usage("natural 1's") total += add out += f'`{add}`' if i != number - 1: out += ', ' #displays the combined total of all of the rolls out += f'\ntotal `{total}`' #if an invalid dice value is entered, will inform the user else: out = f'Sorry {ctx.author.mention}, I don\'t think that\'s a real dice...' #if the user attempts to roll less than 1 dice or more than 30, will inform the user that it is an invalid input else: out = f'Hmmm...I don\'t think I can possibly roll {number} dice. Sorry about that :sweat_smile:' #sends output message to server await ctx.send(out) ###SPECIAL CASES### #if the user rolls a 1 on a d20 or a 20 on a d20 for the single rolls, send additional message delayed by 1 second if out.endswith('`d20`...'): add_usage("natural 1's") sleep(1) await ctx.send('*...ouch*') elif out.endswith('`d20`!'): add_usage("natural 20's") sleep(1) await ctx.send(':partying_face:')
async def ping(self, ctx): await ctx.send(f'pong! {round(self.client.latency * 1000)}ms') add_usage("pings")