require 'yaml' require 'discordrb' require 'icunicode' require 'open-uri' 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'] def save_settings File.open("config.yaml", 'w') do |file| file.write(YAML.dump({'settings' => $settings})) end end bot.command(:translit) do |_event, script, *text| _event.message.mentions.each do |user| member = user.on(_event.channel.server) original_name = member.nick original_name ||= member.username transliterated = original_name.transliterate(script).force_encoding("UTF-8") member.nick = transliterated _event.send_message("Congratulations on your new nickname, #{member.mention}") end _event.send_message("Translitterated: #{text.join(' ').transliterate(script).force_encoding("UTF-8")}") "Finished translitting" end bot.command(:reset) do |_event| _event.message.mentions.each do |user| user.on(_event.channel.server).nickname = nil end "Finished resetting" end bot.command(:loli, description: "Calls for the lolice.") do |_event| "https://tankernn.eu/~frans/files/loli_police_#{rand(1..3)}.png" end bot.command(:reap, description: "Reaps images posted by the caller in the current channel.") do |_event, stop_id| next "No stop_id supplied" if stop_id == nil FileUtils::mkdir_p("/tmp/tankbot_images/") stop = false earliest_message_id = nil control_message = _event.send_message("Reaping images sent by #{_event.author.mention}. React to this message to stop.") until stop messages = _event.channel.history(100, earliest_message_id) messages.select{ |message| message.author === _event.author }.each do |message| puts "#{message.id}, #{stop_id}" if control_message.reactions? or message.id == stop_id stop = true break end message.attachments.select{ |attachment| attachment.image? }.each do |attachment| control_message.edit(control_message.content + "\nDownloading **#{attachment.filename}**... (#{message.timestamp.strftime("%F")})") open("/tmp/tankbot_images/#{attachment.id}-#{attachment.filename}", 'wb') do |file| file << open(attachment.url).read end end end stop = messages.length < 100 earliest_message_id = messages.last.id end filename = "#{SecureRandom.uuid}.tar.gz" `tar -czf /var/www/scr/#{filename} /tmp/tankbot_images` FileUtils::rm_rf("/tmp/tankbot_images") control_message.edit("https://scr.tankernn.eu/#{filename}") end bot.command(:neko, description: "Requests (sometimes lewd) nekos.") do |_event, keyword| url = "https://nekos.life/api/v2/img/" options = ["cum", "les", "meow", "tickle", "lewd", "feed", "bj", "nsfw_neko_gif", "poke", "anal", "slap", "avatar", "pussy", "lizard", "classic", "kuni", "pat", "kiss", "neko", "cuddle", "fox_girl", "boobs", "random_hentai_gif", "hug"] if options.include? keyword then response = JSON.parse(Net::HTTP.get(URI("#{url}#{keyword}"))) "Here's your lewds! °˖✧◝(⁰▿⁰)◜✧˖°\n#{response['url']}" else "No such tag. Please specify one of `#{options.join(", ")}`" end end bot.command(:lmgtfy, description: "Helps tech-illiterate people to enlightenment.") do |_event, *args| "http://lmgtfy.com/?s=d&q=#{args.join('+')}" end bot.command(:copypasta, description: "Cites the holy texts.") do |_event, keyword| pastafile = "copypastas.json" file = File.read pastafile pastas = JSON.parse file if pastas.include? keyword then pastas[keyword] else "No such pasta. Available pastas include `#{pastas.keys.join(", ")}`" end 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) voice_bot.volume = $settings['volume'] 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.command(:volume, description: "Sets the severity of currently playing 'music'.") do |_event, volume| next "Nothing is playing." unless _event.voice $settings['volume'] = _event.voice.volume = [volume.to_f, 1.5].min save_settings "" end bot.run