Bladeren bron

Add music playing capabilities

Frans Bergman 6 jaren geleden
bovenliggende
commit
951b834a03
2 gewijzigde bestanden met toevoegingen van 114 en 0 verwijderingen
  1. 1 0
      Gemfile
  2. 113 0
      main.rb

+ 1 - 0
Gemfile

@@ -4,3 +4,4 @@ ruby "2.5.3"
 
 gem "discordrb"
 gem "icunicode"
+gem "youtube-dl.rb"

+ 113 - 0
main.rb

@@ -6,6 +6,7 @@ require 'fileutils'
 require 'securerandom'
 require 'net/http'
 require 'json'
+require 'youtube-dl.rb'
 
 settings = YAML.load(File.read "config.yaml")['settings']
 bot = Discordrb::Commands::CommandBot.new token: settings['token'], prefix: settings['prefix']
@@ -95,4 +96,116 @@ bot.command(:copypasta, description: "Cites the holy texts.") do |_event, keywor
 end
 
 
+class UserQueue
+    def initialize(user)
+        @user = user
+        @songs = []
+    end
+
+    attr_accessor :user
+    attr_accessor :songs
+end
+
+class FairQueue
+    def initialize(voice_bot)
+        @voice_bot = voice_bot
+        @queues = []
+        @now_playing = nil
+    end
+
+    def append(user, video)
+        @queues.append UserQueue.new user unless @queues.any? { |queue| queue.user == user }
+        @queues.select{ |queue| queue.user == user }.first.songs.append(video)
+    end
+
+    def queue
+        queues = @queues.map{ |queue| queue.songs }
+        target_length = queues.map{ |queue| queue.length }.max
+        queues.map{ |queue| queue + (target_length - queue.length).times.collect{nil} }.transpose.flatten.compact
+    end
+
+    def play
+        until @queues.empty?
+            queue = @queues.shift
+            @now_playing = queue.songs.shift
+            # Rotate user to last place
+            @queues.append queue unless queue.songs.empty?
+            # Play song
+            # song_log("Playing *#{video.title}*...")
+            @voice_bot.play_file(@now_playing.filename)
+        end
+        @voice_bot.destroy
+    end
+
+    attr_accessor :now_playing
+end
+
+def format_title(video)
+    total_seconds = video.information[:duration]
+    seconds = total_seconds % 60
+    minutes = (total_seconds / 60) % 60
+    hours = total_seconds / (60 * 60)
+    timestamp = format("%02d:%02d", minutes, seconds)
+    timestamp = format("%02d:%s", hours, timestamp) if hours > 0
+    "**#{video.information[:fulltitle]}** `[#{timestamp}]`"
+end
+
+fairqueues = Hash.new
+
+youtube_dl_options = {
+    default_search: 'ytsearch',
+    format: 'bestaudio',
+    output: 'cache/%(title)s-%(id)s.%(ext)s'
+}
+
+bot.command(:play, description: "Plays 'music' of your choosing in your voice channel.") do |_event, *query|
+    voice_bot = _event.voice
+    unless voice_bot then
+        channel = _event.user.voice_channel
+        next "You're not in any voice channel!" unless channel
+        voice_bot = bot.voice_connect(channel)
+        fairqueues[_event.server] = FairQueue.new(voice_bot)
+    end
+
+    video = YoutubeDL.download query.join(' '), youtube_dl_options
+
+    fairqueue = fairqueues[_event.server]
+    fairqueue.append(_event.user, video)
+
+    if voice_bot.playing? then
+        "Added #{format_title(video)} to the queue."
+    else
+        Thread.new{fairqueue.play}
+        "Started playing #{format_title(video)}"
+    end
+end
+
+bot.command(:skip, description: "Expresses your dislike of the currently playing 'music'.") do |_event|
+    _event.voice.stop_playing
+end
+
+bot.command(:np, description: "Shows what 'music' is currently playing.") do |_event|
+    queue = fairqueues[_event.server]
+    next "Nothing is playing." unless _event.voice
+    format_title(queue.now_playing)
+end
+
+bot.command(:stop, description: "Puts an end to your misery.") do |_event|
+    if _event.voice
+        _event.voice.destroy
+        "Stopped playing."
+    else
+        "Nothing is playing."
+    end
+end
+
+bot.command(:queue, description: "Lists the impending torture.") do |_event|
+    queue = fairqueues[_event.server]
+    next "Nothing is playing." unless queue
+    next "The queue is empty." if queue.queue.empty?
+
+    queue.queue.each_with_index.map{|video, i| "#{i + 1}. #{format_title(video)}"}.join("\n")
+end
+
+
 bot.run