A Twitch Bot, in Ruby
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
5.8 KiB

  1. # Message formatting in console
  2. class String
  3. def red; "\e[31m#{self}\e[0m" end
  4. def yellow; "\e[33m#{self}\e[0m" end
  5. def green; "\e[32m#{self}\e[0m" end
  6. def cyan; "\e[36m#{self}\e[0m" end
  7. def bold; "\e[1m#{self}\e[22m" end
  8. end
  9. # Requied packages / modules
  10. require 'socket'
  11. require 'logger'
  12. require 'open-uri'
  13. # Create logger
  14. File.delete("log.txt") # Clear previous log
  15. log = Logger.new("log.txt", formatter: proc {|severity, datetime, progname, msg|
  16. "#{datetime}: #{msg}\n"})
  17. # Required Info
  18. load "credentials.txt"
  19. log.info("Loading \"credentials.txt\"")
  20. # -------- IGNORE -------- #
  21. OAUTH.downcase!
  22. BOTNAME.downcase!
  23. CHANNEL.downcase!.gsub!("#", "")
  24. # -------- IGNORE -------- #
  25. # Save "Preparing to connect" to "log.txt"
  26. log.info("Preparing to connect")
  27. # Variables
  28. socket = TCPSocket.new('irc.chat.twitch.tv', 6667)
  29. send = "PRIVMSG ##{CHANNEL} :" # shortcut for sending messages
  30. running = true
  31. content = nil
  32. message_count = 0
  33. message_limit = Time.now.to_i
  34. # Commands
  35. commands = ["!examplecommand","!ping"] # Add commands here
  36. api_commands = ["!followed","!uptime"] # API commands here
  37. admin_commands = ["!disconnect"] # Channel owner commands here
  38. # Authorization Login
  39. socket.puts("PASS #{OAUTH}") # Send the password(oauth) to Twitch
  40. socket.puts("NICK #{BOTNAME}") # Send the botname to Twitch
  41. socket.puts("JOIN ##{CHANNEL}") # Send the channel to Twitch
  42. # Save "Connected!" to "log.txt
  43. log.info("Joining #{CHANNEL.capitalize} as #{BOTNAME.capitalize} using OAUTH Token: #{OAUTH[6,OAUTH.length-12]}" + "*"*12)
  44. # This will add "Joining Somechannel as Bot using OAUTH Token: OAUTH:SomeTokenHereWithHid************" to log.txt
  45. Thread.abort_on_exception = true
  46. # Loop (Background Thread) for recieving Twitch chat data
  47. Thread.start do
  48. socket.puts(send + "Connected!") # Send "Connected!" to the Twitch channel
  49. puts "#{BOTNAME} Joined ##{CHANNEL}" # Connection Status
  50. puts "You should be fully connected now" # Connection Status
  51. puts ""
  52. puts "Type \"clear\" to clear terminal"
  53. puts ""
  54. while (running) do
  55. ready = IO.select([socket])
  56. ready[0].each do |s|
  57. line = s.gets
  58. # Respond to Twitch IRC "PING" Message
  59. if line.index("PING") == 0
  60. line.strip!
  61. socket.puts("PONG :tmi.twitch.tv\r\n")
  62. log.info("[IRC Message]: " + line)
  63. log.info("[IRC Response]: PONG :tmi.twitch.tv")
  64. puts("-".bold.red*line.length)
  65. puts "[Twitch] ".bold.cyan + "IRC: ".bold.yellow + line.bold.green
  66. puts("-".bold.red*line.length)
  67. end
  68. match = line.match(/^:(.+)!(.+)PRIVMSG ##{CHANNEL} :(.+)$/)
  69. message = match && match[3]
  70. if message =~ /^/
  71. message = message.strip
  72. user = match[1] # Get username
  73. # Twitch message limit - (Max 100 messages in 30 secs - Applies to mods and above)
  74. # Avoid global ban
  75. if Time.now.to_i - message_limit > 30 # If more than 30 seconds has passed
  76. message_count = 0 # Reset "message_count"
  77. end
  78. if message_count == 0 # If "message_count" is 0
  79. message_limit = Time.now.to_i # Start counting to 30 again
  80. end
  81. message_count = message_count + 1
  82. end
  83. # // COMMANDS // COMMANDS // COMMANDS
  84. if message != nil
  85. msg = message.downcase
  86. if admin_commands.include?(msg) and user == CHANNEL # ADMIN COMMANDS -> user == CHANNEL (OWNER)
  87. if msg.include?("!disconnect")
  88. socket.puts(send + "Disconnecting") # Disconnect from the channel
  89. socket.puts("PART ##{CHANNEL}") # Disconnect from the channel
  90. Disconnect()
  91. log.info("[Command] #{user}: #{message}")
  92. end
  93. user = user.capitalize # Capitalize first letter (Cuz I'm that kind of person)
  94. elsif commands.include?(msg) and message_count < 80
  95. puts "[Command] ".bold.cyan + "#{user}: ".bold + "#{message}".bold.cyan
  96. if api_commands.include?(msg) # API commands
  97. if msg.include?("uptime")
  98. file = open("https://decapi.me/twitch/uptime?channel=#{CHANNEL}") # API for uptime
  99. content = "#{CHANNEL} has been live for: " + file.read
  100. elsif msg.include?("followed")
  101. file = open("https://decapi.me/twitch/followage/#{CHANNEL}/#{user}") # API for followed
  102. content = file.read
  103. if content == "Follow not found"
  104. content = "#{user} is not following #{CHANNEL}"
  105. else
  106. content = "#{user} has been following #{CHANNEL} for " + content
  107. end
  108. end
  109. puts "[Response] ".bold.red + "Cortexio: ".bold + "API: ".bold.yellow + "\"#{content}\"".bold.red
  110. else
  111. file = open "Responses/" + msg.gsub!("!","") + ".txt" # open matching file
  112. content = file.read
  113. file.close
  114. puts "[Response] ".bold.red + "Cortexio: ".bold + "File: ".bold.yellow + "\"#{msg}.txt\"".bold.red
  115. end
  116. file.close
  117. log.info("[Command] #{user}: #{message}")
  118. else
  119. puts "[Message] ".bold.green + "#{user}: ".bold + "#{message}".bold.green
  120. log.info("[Message] #{user}: #{message}")
  121. if message[0] == "!" # Unrecognized command
  122. content = "Unrecognized command: \"#{message}\" - Type !commands to see a list of available commands."
  123. end
  124. end
  125. # Response handling
  126. if content != nil
  127. content.gsub!("USER", "@#{user}") # Take a look at "ping.txt" to see example usage
  128. content.gsub!("CHANNEL", "#{CHANNEL}")
  129. if content.include? "COMMANDS"
  130. content.gsub!("COMMANDS", "#{commands}")
  131. content.gsub!("\"", "")
  132. content.gsub!("[","")
  133. content.gsub!("]","")
  134. end
  135. socket.puts(send + content) # Send response if any
  136. content = nil # Too avoid multiple messages with the same response
  137. end
  138. end
  139. end
  140. end
  141. end
  142. def Disconnect() # End script
  143. running = false
  144. exit
  145. end
  146. # Loop to keep bot going
  147. while (running) do
  148. gets.chomp
  149. end