Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.89 KB | None | 0 0
  1. """ Bot to coordinate a TorD game
  2. written by Kitty for Ratz
  3. because apparently I have nothing better to do with my life than write
  4. code for free lmao <3
  5. """
  6. # importing other libraries is just this easy
  7. # random module is part of python, no need to worry about this
  8. from random import shuffle
  9. # discord.py: get it with > pip install --user discord
  10. import discord
  11.  
  12. # STICK YOUR FUCKING BOT TOKEN HERE AND YOU'LL CUM, I PROMISE
  13. TOKEN = 'MjQyNDc2MjE1NTQwMTIxNjAw.XQf6jA.adpX0Rw_UoMPfcy1X_ZWFkaZGmo'
  14.  
  15.  
  16. # the first few functions are at the top because python style spec says that
  17. # functions that don't use 'self' shouldn't be in a class
  18.  
  19.  
  20. def newqueue(players):
  21. """grab the players in a queue and shuffle them"""
  22. # setting one variable to another in python *usually* creates a
  23. # reference, so we use the list's copy() function
  24. this = players.copy()
  25. # shuffle the list to randomize the player order
  26. shuffle(this)
  27. # and feed it back to whatever called this function
  28. return this
  29. # sidenote, you can use 'return' to end a function as well
  30.  
  31.  
  32. def runqueue(gamestate):
  33. """start the game or move the queue"""
  34.  
  35. # check to see if we're starting a new game
  36. if not gamestate['lastplayer']:
  37. # there's no last player, so we need to start with a new queue,
  38. # then kick the first person into the last player slot
  39. gamestate['queue'] = newqueue(gamestate['players'])
  40. gamestate['lastplayer'] = gamestate['queue'].pop(0)
  41. # game should be ready to play at this point, so kick back
  42. return
  43.  
  44. # pop out the first player in the queue to the lastplayer var
  45. gamestate['lastplayer'] = gamestate['queue'].pop(0)
  46. print(str(gamestate['lastplayer']).ljust(50, '_'))
  47.  
  48. # check to see if there is anybody left in the queue
  49. # this should effectively never leave the queue empty
  50. # but stupidly might leave the person after the end of the queue unknown
  51. # until it is actually their turn
  52. if not gamestate['queue']:
  53. # if not, grab a new randomized queue
  54. gamestate['queue'] = newqueue(gamestate['players'])
  55. print(gamestate['queue'])
  56.  
  57.  
  58. class TordBot(discord.Client):
  59. """uhhhhhh hi guys im gay
  60. uh jk this is actually the class that wraps the discord.Client thing
  61. and makes the bot actually run lmao
  62. """
  63.  
  64. def __init__(self, *args, **kwargs):
  65. """class initialization
  66. defines some variables that we're going to be using while the bot
  67. is running, and then kicks off discord.py's normal startup
  68. """
  69. # btw, class variables should ONLY be defined in __init__
  70. # they can be redefined elsewhere afterwards
  71.  
  72. # gamestate: a dictionary of servers containing dictionaries of
  73. # channels containing game state information
  74. # when compared to your code, this piece right here makes it so that
  75. # the bot can be used on multiple servers and channels simultaneously
  76. self.gamestate = {}
  77.  
  78. # prefix: well FUCK, I have no idea what this does, do you?
  79. self.prefix = '!'
  80.  
  81. # kick off the initialization of the parent class
  82. super().__init__(*args, **kwargs)
  83.  
  84. async def on_ready(self):
  85. """just a little thing to let us know the bot is ready"""
  86. # btw, print() just writes shit to the console, use it
  87. # like console.log() in js
  88. # ALSO SPEAKING OF JS, WE DON'T USE FUCKING SEMICOLONS
  89. # i mean you can but p much only if you're trying to put two commands
  90. # on the same line and that's against python style spec so fuck that
  91. print('Logged in as')
  92. print(self.user.name)
  93. print(self.user.id)
  94. print('------')
  95.  
  96. def get_gamestate(self, channel):
  97. """grab the gamestate for the specific channel in question"""
  98. if channel.guild.id not in self.gamestate:
  99. self.gamestate[channel.guild.id] = {}
  100. if channel.id not in self.gamestate[channel.guild.id]:
  101. # at this point, we don't have a gamestate for the channel in
  102. # question, so we define its skeleton here
  103. self.gamestate[channel.guild.id][channel.id] = {
  104. 'players': [],
  105. 'queue': [],
  106. 'lastplayer': None,
  107. 'inprogress': False
  108. }
  109. return self.gamestate[channel.guild.id][channel.id]
  110.  
  111. def endgame(self, channel):
  112. """end the game
  113. this is it's own function because there's more than one way the game
  114. could be ended
  115. """
  116. gamestate = self.get_gamestate(channel)
  117. gamestate['players'].clear()
  118. gamestate['queue'].clear()
  119. gamestate['lastplayer'] = None
  120. gamestate['inprogress'] = False
  121.  
  122. async def on_message(self, msg):
  123. """handler for incoming messages"""
  124. # so it turns out python style also says things shouldn't get too big
  125. # fuck python style as far as that goes, turn off the linter warnings
  126. # pylint: disable=too-many-return-statements
  127. # pylint: disable=too-many-branches
  128. # pylint: disable=too-many-statements
  129.  
  130. # split() will split a string by spaces by default, which we use here
  131. # to see if we've got the command we're looking for or not
  132. msgsplit = msg.content.split()
  133.  
  134. # so a big concept of Python is that almost everything can be
  135. # interpreted as a boolean, and checking things this way is what
  136. # a lot of people would consider "pythonic"
  137. # `False` things would be things like an empty array or dict,
  138. # '', 0, and False, of course
  139. # We do this here to see if the msgsplit list is empty
  140. if not msgsplit:
  141. # no message, it's probably not for us
  142. return
  143.  
  144. # so in the way that discord.py handles things, it gives us a
  145. # 'message' argument to the on_message() function. This is a class
  146. # object that contains all of the pertinent information associated
  147. # with the message.
  148. # Notable attributes include:
  149. # - message.author: a class object for the person that wrote it
  150. # - author.id: the id of the person
  151. # - author.name: the discord username of the person
  152. # - author.nick: the nickname of the user in the current server
  153. # - author.mention: a preformatted string to highlight the user
  154. # effectively translates to <@{author.id}>
  155. # - message.guild: the "server" where the message was posted
  156. # - guild.id: fuck why am i still awake, it's 8:34am
  157. # - message.channel: the channel the message was posted in
  158. # - channel.id: the snowflake of the channel
  159. # also, your code didn't have any references to it in your original so
  160. # I didn't put any in this script, but...
  161. # - message.mentions: an array of people who were highlighted in the
  162. # message received, you could use this for taking actions towards
  163. # a specified person
  164.  
  165. if msgsplit[0] == self.prefix + 'j':
  166. gamestate = self.get_gamestate(msg.channel)
  167. # if gamestate['inprogress']:
  168. # await msg.channel.send(
  169. # 'Sorry, the game is already in progress!')
  170. # return
  171. if msg.author in gamestate['players']:
  172. # ok so this is the first message send in here
  173. # 'await' is a thing that has to do with asynchronous operation
  174. # don't worry about it too much, just know that it has to be
  175. # used pretty much before anything that is sent or received
  176. # from the server. more demanding and heavy bots would need it
  177. # a lot more but this bot is no big deal. also shit will break
  178. # if you don't use it where you need to. it'll probably just
  179. # not do whatever the command was supposed to do and complain
  180. # on the console but not actually completely stop or anything
  181. await msg.channel.send('You are already in queue, dafaq?')
  182. else:
  183. # holy FUCK is this easy or what? we literally fucking add
  184. # the person themself to the list. fucking miracles, man.
  185. # even better, this is a class object of the person, so we
  186. # get all of the goodies that go along with that
  187. gamestate['players'].append(msg.author)
  188. await msg.channel.send('You have been added to the queue.')
  189.  
  190. elif msgsplit[0] == self.prefix + 'r':
  191. gamestate = self.get_gamestate(msg.channel)
  192. if msg.author in gamestate['players']:
  193. gamestate['players'].remove(msg.author)
  194. if msg.author in gamestate['queue']:
  195. gamestate['queue'].remove(msg.author)
  196. if len(gamestate['players']) < 2:
  197. final = gamestate['players'][0]
  198. nick = final.nick if final.nick else final.name
  199. await msg.channel.send(
  200. 'WOW ARE YOU SERIOUSLY GONNA LEAVE ' + nick.upper()
  201. + ' ALL BY THEMSELVES? YOU\'RE SUCH AN ASSHOLE.\n'
  202. 'Also, games over.')
  203. self.endgame(msg.channel)
  204. else:
  205. await msg.channel.send(
  206. 'You have been removed from the queue.')
  207. else:
  208. await msg.channel.send(
  209. 'How can I remove you from a queue you '
  210. 'were never a part of..?')
  211.  
  212. elif msgsplit[0] == self.prefix + 'skip':
  213. gamestate = self.get_gamestate(msg.channel)
  214. if not gamestate['inprogress']:
  215. await msg.channel.send(
  216. 'Uh.. Who you trying to fuck over without a game starting?')
  217. return
  218. if not gamestate['queue']:
  219. await msg.channel.send(
  220. 'There should be people in queue before you try that.. \n'
  221. f'Should probly try `{self.prefix}n` first.')
  222. return
  223. #Figure out how the fuck to remove people... Fml
  224. #Tried These Two Options:
  225. #del gamestate['players'][0]
  226. #del gamestate['queue'][0]
  227. #gamestate['players'].remove(0)
  228. #gamestate['queue'].remove(0)
  229. gamestate['players'].pop(0)
  230. gamestate['queue'].pop(0)
  231. if len(gamestate['players']) < 2:
  232. final = gamestate['players'][0]
  233. nick = final.nick if final.nick else final.name
  234. await msg.channel.send(
  235. 'WOW YOU REMOVE THE LAST PERSON PLAYING WITH YOU, ' + nick.upper()
  236. + '? YOU\'RE SUCH AN ASSHOLE.\n'
  237. + 'Also, games over.')
  238. self.endgame(msg.channel)
  239. else:
  240. runqueue(gamestate)
  241. await msg.channel.send(
  242. 'The player has been removed from queue \n' +
  243. gamestate['lastplayer'].mention +
  244. 'is asking ' +
  245. gamestate['queue'][0].mention +
  246. ' Truth or Dare!?')
  247.  
  248. elif msgsplit[0] == self.prefix + 'q':
  249. gamestate = self.get_gamestate(msg.channel)
  250. if not gamestate['inprogress']:
  251. await msg.channel.send(
  252. 'There isn\'t a game being played, you dumb dumb.')
  253. return
  254. if not gamestate['queue']:
  255. # "f-strings" allow you to use vars inside of strings
  256. await msg.channel.send(
  257. 'There is nobody in the queue, you dumb dumb. '
  258. f'Should probly try `{self.prefix}n`')
  259. return
  260. buffer = '**The currrent Queue Is:**\n'
  261. buffer += ''.ljust(53, '-') + '\n' # easy divider bars
  262. buffer += gamestate['lastplayer'].nick \
  263. if gamestate['lastplayer'].nick \
  264. else gamestate['lastplayer'].name
  265. buffer += '\n'
  266. for player in gamestate['queue']:
  267. # now this is a tricky little thing here that uses the person's
  268. # nickname in the server if they have one, otherwise just uses
  269. # their regular username
  270. buffer += player.nick if player.nick else player.name
  271. buffer += '\n'
  272. buffer += ''.ljust(53, '-') + '\n'
  273. buffer += '**Players Joined: **\n'
  274. buffer += ''.ljust(53, '-') + '\n'
  275. for player in gamestate['players']:
  276. buffer += player.nick if player.nick else player.name
  277. buffer += '\n'
  278. await msg.channel.send(buffer)
  279.  
  280. elif msgsplit[0] == self.prefix + 'n':
  281. gamestate = self.get_gamestate(msg.channel)
  282. if not gamestate['inprogress']:
  283. await msg.channel.send(
  284. 'Please start the game by typing `' +
  285. self.prefix + 'start`')
  286. return
  287. # lmao get shit done hahahaha kill me
  288. runqueue(gamestate)
  289. # and the moment we've all been waiting for
  290. await msg.channel.send(
  291. gamestate['lastplayer'].mention +
  292. ' is asking ' +
  293. gamestate['queue'][0].mention +
  294. ' Truth or Dare!?')
  295.  
  296. elif msgsplit[0] == self.prefix + 'start':
  297. gamestate = self.get_gamestate(msg.channel)
  298. if gamestate['inprogress']:
  299. await msg.channel.send(
  300. 'Are u fookin stoopid? ther\'s alredy a gayme her')
  301. return
  302. # you can't start with less than 2 players.
  303. # midgets count as a half a player, so you need at least 4 midgets.
  304. # 3 midgets would only be 1.5 players, and that's less than 2.
  305. if len(gamestate['players']) < 2:
  306. await msg.channel.send(
  307. 'You need at least 2 players to start a game\n'
  308. f'Please join with, `{self.prefix}j`')
  309. return
  310. gamestate['inprogress'] = True
  311. await msg.channel.send(
  312. '***WELCOME TO THE THUNDERDOME***\n'
  313. 'In this arena, literally every one of you are gas as fuck.\n'
  314. 'You must submit to whatever the other n-word tells you to do.'
  315. '\nMay Allah have mercy on your soul.'
  316. f'\nThe Game Has Now Started - `{self.prefix}n` to show who\'s asking who.')
  317.  
  318. elif msgsplit[0] == self.prefix + 'end':
  319. gamestate = self.get_gamestate(msg.channel)
  320. if not gamestate['inprogress']:
  321. await msg.channel.send(
  322. 'There\'s no game being played here so maybe you should'
  323. 'end your life instead')
  324. return
  325. # clear out all of the crap and reinit gamestate
  326. self.endgame(msg.channel)
  327. await msg.channel.send(
  328. 'The game is over.')
  329.  
  330.  
  331. # more PROPER python shit, technically everything is a module
  332. # and no runtime code should be run outside of a function, so that
  333. # you can reuse the code elsewhere without it running by itself
  334. # "main" doesn't actually mean anything here, it could be named
  335. # anything else that you'd like
  336. def main():
  337. """RUN THE FOOKIN BOT ALREADY GODDAM"""
  338. bot = TordBot()
  339. bot.run(TOKEN)
  340.  
  341.  
  342. # on the other hand, __name__ here is a way of checking what module
  343. # we currently identify as, this would normally be the filename
  344. # (but without .py on the end of it) if being used as a module,
  345. # but if it is being run directly, then __name__ will be __main__
  346. # that said, if you're running this directly, actually run the bot here?
  347. if __name__ == '__main__':
  348. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement