require 'discordrb' require 'video_info' require 'uri' require 'optparse' require 'shellwords' def sanity_check_video(url) if !url.include?("youtube") return false end video = VideoInfo.new(url) title = video.title title.slice! " - YouTube Music" if video.duration > 1200 puts "skipping #{url} since it's over 20 minutes" return false elsif File.exists?("tracks/#{title}.mp3") || File.exists?("spool/#{title}.mp3") puts "#{url} already downloaded, not downloading again" return false end return true end def parse_songs_from_string(message) urls = URI.extract(message) if urls.length != 0 puts "Found #{urls}; downloading" urls.each do |url| if sanity_check_video(url) res = `youtube-dl --ignore-errors --output \"spool/%(title)s.%(ext)s\" --extract-audio --audio-format mp3 #{url}` if res puts "Downloaded #{url}" else puts "error downloading #{url}" end end end end nil end def update_mpd() new_songs = Dir["spool/*.mp3"] if new_songs.length <= 0 return true end puts "telling mpd to refresh" `mv spool/*.mp3 tracks/` `mpc update` new_songs.each do |song| s = song.split("/")[1] res = system("mpc add #{Shellwords.shellescape(s)}") if res puts "added #{s} to mpd" else puts "error adding #{s} to mpd" end end end options = {} OptionParser.new do |opt| opt.on("-t", "--token DISCORD_BOT_TOKEN") {|o| options[:bot_token] = o} opt.on("-c", "--channel CHANNEL_ID") {|o| options[:channel_id] = Integer(o)} end.parse! if options.length == 0 puts "Need to specifiy token and channel" exit end puts "creating spool and tracks directories" `mkdir -p spool` `"mkdir -p tracks` if File.exists?("/usr/bin/mpd") if !File.exists?("/usr/bin/mpc") puts "Bailing since mpd exists but not mpc (which is needed to control mpd)" exit end puts "starting mpd if not already running" `systemctl start mpd` unless `ps aux | grep mpd` != "" `mpc clear` `mpc add /` `mpc shuffle` `mpc repeat` end bot = Discordrb::Commands::CommandBot.new token: options[:bot_token], prefix: '!radio ' bot.command :start do |event| `mpc play` event.respond("starting radio") end bot.command :stop do |event| `mpc stop` event.respond("stoping radio") end bot.command :reload do |event| event.respond("reloading queue") `mpc stop` `mpc clear` `mpc update` `mpc add /` event.respond("queue reloaded") nil end bot.command :pause do |event| event.respond("pausing playback") `mpc toggle` nil end bot.command :skip do |event| event.respond("skipping") `mpc next` nil end bot.command :shuffle do |event| `mpc shuffle` event.respond("shuffled queue") nil end bot.command :initialize do |event| event.respond("loading last 50 messages from channel") channel = bot.channel(options[:channel_id]) messages = channel.history(50) messages.each do |msg| parse_songs_from_string(msg.content) end update_mpd() event.respond("done loading") end bot.message(in: options[:channel_id],contains: "youtube.com") do |event| parse_songs_from_string(event.content) update_mpd() end bot.run