PageRenderTime 24ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/functions.py

https://bitbucket.org/alexanderpaul/marinas-utility-music
Python | 222 lines | 152 code | 32 blank | 38 comment | 57 complexity | 669272978869cc461f5cc07c608132cd MD5 | raw file
  1. import os
  2. import sys
  3. import asyncio
  4. # my modules
  5. import config
  6. import helpers
  7. import embeds
  8. async def Reboot(Bot, Player, Message):
  9. # checks if the one executing the command is the owner of the bot
  10. # which can be set on the config.py module
  11. if Message.author.id == config.OwnerID:
  12. # if the bot is currently connected to a voice channel, disconnect it first
  13. if Player.voice != None:
  14. await Player.DisconnectVoiceChannel()
  15. await Message.channel.send('Rebooting...')
  16. await Bot.logout()
  17. # reruns the python script
  18. python = sys.executable
  19. os.execl(python, python, 'main.py')
  20. else:
  21. await Message.channel.send('{}, you do not have the will to reboot me.'.format(Message.author.mention))
  22. async def JoinVoiceChannel(Bot, Player, Message):
  23. # if the bot is not connected to any voice channel
  24. if Player.voice == None:
  25. Player.SetVoice(await Bot.get_channel(config.MusicVoiceChannelID).connect())
  26. await Message.channel.send('Joined into the music voice channel by {}.'.format(Message.author.display_name))
  27. else:
  28. await Message.channel.send('{}, I am already connected to a voice channel.'.format(Message.author.mention))
  29. async def DisconnectVoiceChannel(Player, Message):
  30. # if the bot is connected to any voice channel
  31. if Player.voice != None:
  32. await Player.DisconnectVoiceChannel()
  33. await Message.channel.send('{} disconnected me from the music voice channel.'.format(Message.author.display_name))
  34. else:
  35. await Message.channel.send('{}, I am not connected to the music voice channel.'.format(Message.author.mention))
  36. async def PlayMusic(Bot, Player, Message):
  37. # if the bot isn't joined to a voice channel yet, join it first
  38. if len(Bot.voice_clients) == 0:
  39. await JoinVoiceChannel(Bot, Player, Message)
  40. # gets the search query or the song title from the command
  41. query = Message.content[Message.content.find(' ')+1:]
  42. print('Search Query: {}'.format(query))
  43. # if the query is a youtube playlist
  44. if 'youtube.com/playlist?list=' in query:
  45. return
  46. # get song by title or video url
  47. else:
  48. # a helper function from another module (helpers.py)
  49. # which uses the Youtube Data API to search for Youtube videos and gather content details
  50. Song = helpers.GetSongs(Message, 1)
  51. # if a song was found, add the song to the queue
  52. if Song:
  53. Player.Queue.AddSong(Song)
  54. else:
  55. await Message.channel.send('Search failed.')
  56. return
  57. # sends an embedded message (for aesthetics) of the details of the song that's added to the queue
  58. await embeds.SendAddedToQueue(Bot, Player.Queue)
  59. # if the queue size is equal to one after adding a song, play it immediately
  60. if Player.Queue.size() == 1:
  61. await Player.PlaySong(Song, Bot)
  62. async def SearchMusic(Bot, Player, Message):
  63. searcher = Message.author
  64. # if the bot isn't joined to a voice channel yet
  65. if len(Bot.voice_clients) == 0:
  66. await JoinVoiceChannel(Bot, Player, Message)
  67. # a helper function from another module (helpers.py)
  68. # which uses the Youtube Data API to search for Youtube videos and gather content details
  69. searchSongs = helpers.GetSongs(Message, 2)
  70. if searchSongs == None:
  71. await Message.channel.send('{}, search failed.'.format(Message.author.mention))
  72. return
  73. # sends an embedded message containing the songs that matched the search
  74. await embeds.SendSearchResults(Bot, Message, Player, searchSongs)
  75. # a custom checker to check the response of the searcher or if the responder is the searcher
  76. # this returns true if a valid response is receive which is either a cancel or a search number
  77. # returns
  78. def CheckResponse(Message):
  79. if Message.author == searcher:
  80. # cancels the search
  81. if Message.content.lower() == 'cancel' or Message.content.lower() == 'exit':
  82. return True
  83. try:
  84. number = int(Message.content)
  85. if number >= 1 and number <= config.MaxSearchResults:
  86. print('Valid number caught!')
  87. return True
  88. else:
  89. print('Invalid number caught!')
  90. asyncio.run_coroutine_threadsafe(Message.channel.send('Number {} is not in search results.'.format(number)), Bot.loop)
  91. return False
  92. except ValueError:
  93. print('Value Error Exception!')
  94. asyncio.run_coroutine_threadsafe(Message.channel.send('Invalid input. Make sure to enter a number.'), Bot.loop)
  95. return False
  96. # executes the checker function above to filter the responses
  97. # will keep checking until a True is received or it times out which returns a None
  98. response = await Bot.wait_for('message', check=CheckResponse, timeout=config.SearchTimeOut)
  99. # if a valid (True) response is received and did not timeout
  100. if response != None:
  101. # if the response is a cancel
  102. if (response.content.lower() == 'cancel' or response.content.lower() == 'exit'):
  103. await Message.channel.send('Search cancelled.')
  104. else:
  105. # gets the position number from the response
  106. position = int(response.content)
  107. Song = searchSongs[position-1]
  108. Player.Queue.AddSong(Song)
  109. await embeds.SendAddedToQueue(Bot, Player.Queue)
  110. print('Queue Size: {}'.format(Player.Queue.size()))
  111. if Player.Queue.size() == 1:
  112. await Player.PlaySong(Song, Bot)
  113. else:
  114. await Message.channel.send('Search timed out.')
  115. async def SkipSong(Player, Message):
  116. # if the queue is not empty
  117. if (Player.Queue.size() > 0):
  118. await Message.channel.send('{} skipped {}.'.format(Message.author.display_name, Player.Queue.songs[0].title))
  119. Player.SkipSong()
  120. else:
  121. await Message.channel.send('{}, there is no song playing.'.format(Message.author.mention))
  122. async def RemoveSong(Player, Message):
  123. # only executes if the queue size is greater than 1
  124. # to prevent removal of the first song
  125. if (Player.Queue.size() > 1):
  126. try:
  127. pos = int(Message.content[Message.content.find(' '):])
  128. await Message.channel.send('{} removed {}'.format(Message.author.display_name, Player.Queue.songs[pos-1].title))
  129. # a position is valid if it's greater than one and is within the queue size
  130. if pos > 1 or pos < Player.Queue.size():
  131. Player.Queue.RemoveSong(pos)
  132. # if no number is parsed from the command
  133. except ValueError:
  134. await Message.channel.send('{}, invalid input. Please enter a number.'.format(Message.author.mention))
  135. else:
  136. await Message.channel.send('{}, no song available to be removed.'.format(Message.author.mention))
  137. async def PauseSong(Player, Message):
  138. # checks if the queue size is not empty
  139. if (Player.Queue.size() > 0):
  140. # only executes if the player is playing a song
  141. if (Player.voice.is_playing):
  142. await Message.channel.send('{} paused {}.'.format(Message.author.display_name, Player.Queue.songs[0].title))
  143. Player.PauseSong()
  144. else:
  145. await Message.channel.send('{}, I am already paused.'.format(Message.author.mention))
  146. else:
  147. await Message.channel.send('{}, there is no song in the queue.'.format(Message.author.mention))
  148. async def ResumeSong(Player, Message):
  149. # checks if the queue is not empty
  150. if (Player.Queue.size() > 0):
  151. # only executes if the player is paused
  152. if (Player.voice.is_paused):
  153. await Message.channel.send('{} resumed {}.'.format(Message.author.display_name, Player.Queue.songs[0].title))
  154. Player.PauseSong()
  155. else:
  156. await Message.channel.send('{}, I am already playing.'.format(Message.author.mention))
  157. else:
  158. await Message.channel.send('{}, there is no song in the queue.'.format(Message.author.mention))
  159. async def SetLoopSong(Player, Message):
  160. Player.Queue.SetLoopSong()
  161. if Player.Queue.isLoopingSong: loopsong = 'enabled'
  162. else: loopsong = 'disabled'
  163. await Message.channel.send('{} {} song loop.'.format(Message.author.display_name, loopsong))
  164. async def SetLoopQueue(Player, Message):
  165. Player.Queue.SetLoopQueue()
  166. if Player.Queue.isLoopingQueue: loopqueue = 'enabled'
  167. else: loopqueue = 'disabled'
  168. await Message.channel.send('{} {} queue loop.'.format(Message.author.display_name, loopqueue))
  169. async def SetVolume(Player, Message):
  170. if Player.source != None:
  171. try:
  172. volume = float(Message.content[Message.content.find(' ')+1:])
  173. Player.SetVolume(volume)
  174. await Message.channel.send('{} set my volume to {}.'.format(Message.author.mention, Player.source.volume))
  175. except ValueError:
  176. await Message.channel.send('{}, invalid volume. Number must be between 0 to 2.0.'.format(Message.author.mention))
  177. else:
  178. await Message.channel.send('{}, no song is playing.'.format(Message.author.mention))
  179. async def Mute(Player, Message):
  180. if Player.source.volume > 0:
  181. Player.SetVolume(0)
  182. await Message.channel.send('{} muted me.'.format(Message.author.display_name))
  183. else:
  184. await Message.channel.send('{}, I am already muted.'.format(Message.author.mention))
  185. async def Unmute(Player, Message):
  186. if Player.source.volume <= 0:
  187. Player.SetVolume(.5)
  188. await Message.channel.send('{} unmuted me. Thank you! :heartpulse:'.format(Message.author.display_name))
  189. else:
  190. await Message.channel.send('{}, I\'m not muted.'.format(Message.author.mention))