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.

260 lines
8.7KB

  1. import random
  2. import re
  3. import discord
  4. import requests
  5. from discord.ext.commands import bot
  6. from Roxbot import checks
  7. from Roxbot.settings import guild_settings
  8. from Roxbot.logging import log
  9. class Fun:
  10. def __init__(self, bot_client):
  11. self.bot = bot_client
  12. @bot.command()
  13. async def roll(self, ctx, expression = ""):
  14. """
  15. Rolls a die using dice expression format.
  16. Usage:
  17. {command_prefix}roll expression
  18. spaces in expression are ignored
  19. Example:
  20. .roll 2d20h1 + 7 # Rolls two D20s takes the highest 1, then adds 7
  21. .roll #will give brief overview of dice expression format
  22. Dice expression format:
  23. An expression can consist of many sub expressions added together and then a multiplier at the end to indicate how many times the expression should be rolled.
  24. Sub expressions can be of many types:
  25. <number> #add this number to the total
  26. d<sides> #roll a dice with that many sides and add it to the total
  27. <n>d<sides> #roll n dice. each of those dice have <sides> number of sides, sum all the dice and add to the total
  28. add r<number> #reroll any rolls below <number>
  29. add h<number> #only sum the <number> highest rolls rather than all of them
  30. add l<number> #only sum the <number> lowest rolls rather than all of them
  31. +<number> # Add this number to the sum.
  32. x<number> #only use at the end. roll the rest of the expression <number> times(max 10)")
  33. Credit: TBTerra#5677
  34. """
  35. response = ''
  36. rollVerbose = True
  37. # sanitise input by removing all spaces, converting to lower case
  38. expression = expression.lower().replace(' ','')
  39. # check end of expression for a 'x<number>'
  40. parts = expression.split('x',1)
  41. times = 1
  42. if len(parts) == 2:
  43. try:
  44. times = int(parts[1])
  45. if times < 1:
  46. times = 1
  47. if times > 10:
  48. response += "*Warning:* cannot roll an expression more than 10 times. will roll 10 times rather than {}.\n".format(times)
  49. times = 10
  50. except ValueError:
  51. times = 1
  52. response += "*Warning:* was unable to resolve how many times this command was meant to run. defaulted to once.\n"
  53. m=re.findall('(-?)((?:(\d*)d(\d*))|\d+)(r\d*)?([h,l]{1}\d*)?',parts[0])
  54. if m == []:
  55. return await ctx.send("Expression missing. If you are unsure of what the format should be, please use `{}help roll`".format(ctx.prefix))
  56. dice = []
  57. for item in m:
  58. temp = [0]*5
  59. temp[0] = 1 if item[0] == '' else -1#if theres a - at the beginning of the sub expression there needs to be a -1 multiplier applied to the sub expression total
  60. if 'd' in item[1]:#if its a dice/set of dice rather than a number
  61. if item[2] == '':#if its just a dY rather than an XdY
  62. temp[1] = 1
  63. temp[2] = int(item[3])
  64. else:
  65. temp[1] = int(item[2])
  66. if temp[1] > 10 and rollVerbose == True:#if there is a sub expression that involves lots of rolls then turn off verbose mode
  67. rollVerbose = False
  68. response += '*Warning:* large number of rolls detected, will not use verbose rolling.\n'
  69. temp[2] = int(item[3])
  70. else:
  71. temp[1] = int(item[1])
  72. temp[2] = 1
  73. temp[3] = 0 if item[4] == '' else int(item[4][1:])
  74. if item[5] == '':
  75. temp[4] = 0
  76. else:
  77. if item[5][0] == 'h':
  78. temp[4] = int(item[5][1:])
  79. else:
  80. temp[4] = -int(item[5][1:])
  81. dice.append(temp)
  82. for i in range(times):
  83. total = 0
  84. if times > 1:
  85. response += 'Roll {}: '.format(i+1)
  86. else:
  87. response += 'Rolled: '
  88. for j in range(len(dice)):
  89. if j != 0 and rollVerbose:
  90. response += ' + '
  91. if dice[j][0] == -1 and rollVerbose:
  92. response += '-'
  93. if dice[j][2] == 1:
  94. if rollVerbose:
  95. response += '{}'.format(dice[j][1])
  96. total += dice[j][0] * dice[j][1]
  97. else:
  98. if rollVerbose:
  99. response += '('
  100. temp = []
  101. for k in range(dice[j][1]):
  102. t = [0,'']
  103. t[0] = random.randint(1,dice[j][2])
  104. t[1] = '{}'.format(t[0])
  105. if t[0] <= dice[j][3]:
  106. t[0] = random.randint(1,dice[j][2])
  107. t[1] += '__{}__'.format(t[0])
  108. temp.append(t)
  109. def takeFirst(ele):
  110. return ele[0]
  111. if dice[j][4] > 0:
  112. temp.sort(key=takeFirst, reverse=True)
  113. for k in range(len(temp)):
  114. if k >= dice[j][4]:
  115. temp[k][1] = '~~' + temp[k][1] + '~~'
  116. temp[k][0] = 0
  117. if dice[j][4] < 0:
  118. temp.sort(key=takeFirst)
  119. for k in range(len(temp)):
  120. if k >= -dice[j][4]:
  121. temp[k][1] = '~~' + temp[k][1] + '~~'
  122. temp[k][0] = 0
  123. for k in range(len(temp)):
  124. if rollVerbose:
  125. response += '{},'.format(temp[k][1])
  126. total+= dice[j][0] * temp[k][0]
  127. if rollVerbose:
  128. response = response[:-1] + ')'
  129. if rollVerbose:
  130. response += ' Totaling: {}'.format(total)
  131. else:
  132. response += ' Total: {}'.format(total)
  133. if i < (times-1): response += '\n'
  134. return await ctx.send(response)
  135. @checks.isnt_anal()
  136. @bot.command()
  137. async def spank(self, ctx, *, user: discord.User = None):
  138. """
  139. Spanks the mentioned user ;)
  140. Usage:
  141. {command_prefix}spank @Roxbot#4170
  142. {command_prefix}spank Roxbot
  143. """
  144. if not user:
  145. return await ctx.send("You didn't mention someone for me to spank")
  146. return await ctx.send(":peach: :wave: *{} spanks {}*".format(self.bot.user.name, user.name))
  147. @checks.isnt_anal()
  148. @bot.command(aliases=["succ"])
  149. async def suck(self, ctx, *, user: discord.User = None):
  150. """
  151. Sucks the mentioned user ;)
  152. Usage:
  153. {command_prefix}suck @Roxbot#4170
  154. {command_prefix}suck Roxbot
  155. """
  156. if not user:
  157. return await ctx.send("You didn't mention someone for me to suck")
  158. return await ctx.send(":eggplant: :sweat_drops: :tongue: *{} sucks {}*".format(self.bot.user.name, user.name))
  159. @bot.command()
  160. async def hug(self, ctx, *, user: discord.User = None):
  161. """
  162. Hugs the mentioned user :3
  163. Usage:
  164. {command_prefix}hug @Roxbot#4170
  165. {command_prefix}hug Roxbott
  166. """
  167. if not user:
  168. return await ctx.send("You didn't mention someone for me to hug")
  169. return await ctx.send(":blush: *{} hugs {}*".format(self.bot.user.name, user.name))
  170. @bot.command(aliases=["headpat"])
  171. async def pet(self, ctx, *, user: discord.User = None):
  172. """
  173. Gives headpats to the mentioned user :3
  174. Usage:
  175. {command_prefix}pet @Roxbot#4170
  176. {command_prefix}pet Roxbot
  177. """
  178. if not user:
  179. return await ctx.send("You didn't mention someone for me to headpat")
  180. return await ctx.send("Nyaa! :3 *{} gives headpats to {}*".format(self.bot.user.name, user.name))
  181. @bot.command(aliases=["wf", "wr", "husbandorate", "hr", "spousurate", "sr"])
  182. async def waifurate(self, ctx):
  183. """
  184. Rates the mentioned waifu(s). husbando/spousurate also work.
  185. Usage:
  186. {command_prefix}waifurate @user#9999
  187. This command is in dedicated to Hannah, who suggested this command to me. I hope she's out there, somewhere, getting her waifus rated in peace.
  188. """
  189. mentions = ctx.message.mentions
  190. if ctx.invoked_with in ["hr", "husbandorate"]:
  191. waifu = "husbando"
  192. elif ctx.invoked_with in ["sr", "spousurate"]:
  193. waifu = "spousu"
  194. else:
  195. waifu = "waifu"
  196. if not mentions:
  197. return await ctx.send("You didn't mention anyone for me to rate.", delete_after=10)
  198. rating = random.randrange(1, 11)
  199. if rating <= 2:
  200. emoji = ":sob:"
  201. elif rating <= 4:
  202. emoji = ":disappointed:"
  203. elif rating <= 6:
  204. emoji = ":thinking:"
  205. elif rating <= 8:
  206. emoji = ":blush:"
  207. elif rating == 9:
  208. emoji = ":kissing_heart:"
  209. else:
  210. emoji = ":heart_eyes:"
  211. if len(mentions) > 1:
  212. return await ctx.send("Oh poly {} rating? :smirk: Your combined waifu rating is {}/10. {}".format(waifu, rating, emoji))
  213. else:
  214. return await ctx.send("Oh that's your {}? I rate them a {}/10. {}".format(waifu, rating, emoji))
  215. @bot.command(aliases=["cf"])
  216. async def coinflip(self, ctx):
  217. """Flip a coin"""
  218. return await ctx.send("The coin landed on {}!".format(random.choice(["heads", "tails"])))
  219. @bot.command()
  220. async def aesthetics(self, ctx, *, convert):
  221. """Converts text to be more a e s t h e t i c s"""
  222. WIDE_MAP = dict((i, i + 0xFEE0) for i in range(0x21, 0x7F))
  223. WIDE_MAP[0x20] = 0x3000
  224. converted = str(convert).translate(WIDE_MAP)
  225. await ctx.send(converted)
  226. logging = guild_settings.get(ctx.guild).logging
  227. log_channel = self.bot.get_channel(logging["channel"])
  228. await log(ctx.guild, log_channel, "aesthetics", User=ctx.author, Argument_Given=convert, Channel=ctx.channel, Channel_Mention=ctx.channel.mention)
  229. @bot.command(aliases=["ft", "frog"])
  230. async def frogtips(self, ctx):
  231. """RETURNS FROG TIPS FOR HOW TO OPERATE YOUR FROG"""
  232. endpoint = "https://frog.tips/api/1/tips/"
  233. croak = requests.get(endpoint)
  234. tip = random.choice(croak.json()["tips"])
  235. embed = discord.Embed(title="Frog Tip #{}".format(tip["number"]), description=tip["tip"], colour=discord.Colour(0x4C943D))
  236. embed.set_author(name="HOW TO OPERATE YOUR FROG")
  237. embed.set_footer(text="https://frog.tips")
  238. return await ctx.send(embed=embed)
  239. def setup(bot_client):
  240. bot_client.add_cog(Fun(bot_client))