A Twitter bot that tweets random frames from the Computer Chronicles TV show https://twitter.com/chronicles_bot
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.

cc.rb 2.4KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. require 'dotenv/load'
  2. require 'json'
  3. require 'open-uri'
  4. require 'twitter'
  5. Dotenv.load
  6. TWITTER_CONSUMER_KEY = ENV["TWITTER_CONSUMER_KEY"]
  7. TWITTER_CONSUMER_SECRET = ENV["TWITTER_CONSUMER_SECRET"]
  8. TWITTER_ACCESS_TOKEN = ENV["TWITTER_ACCESS_TOKEN"]
  9. TWITTER_ACCESS_TOKEN_SECRET = ENV["TWITTER_ACCESS_TOKEN_SECRET"]
  10. YOUTUBE_DL_PATH = `which youtube-dl`.chomp
  11. FFMPEG_PATH = `which ffmpeg`.chomp
  12. FFPROBE_PATH = `which ffprobe`.chomp
  13. VIDEO_PATH = "/tmp/video.mp4"
  14. FRAME_PATH = "/tmp/frame.png"
  15. PLAYLIST_ID = ENV["PLAYLIST_ID"]
  16. throw "TWITTER_CONSUMER_KEY is required" unless TWITTER_CONSUMER_KEY
  17. throw "TWITTER_CONSUMER_SECRET is required" unless TWITTER_CONSUMER_SECRET
  18. throw "TWITTER_ACCESS_TOKEN is required" unless TWITTER_ACCESS_TOKEN
  19. throw "TWITTER_ACCESS_TOKEN_SECRET is required" unless TWITTER_ACCESS_TOKEN_SECRET
  20. throw "PLAYLIST_ID is required" unless PLAYLIST_ID
  21. throw "Can't find youtube-dl" if YOUTUBE_DL_PATH.empty?
  22. throw "Can't find ffprobe" if FFPROBE_PATH.empty?
  23. throw "Can't find ffmpeg" if FFMPEG_PATH.empty?
  24. class YouTubeService
  25. def initialize(playlist_id)
  26. @playlist_id = playlist_id
  27. end
  28. def fetch_random_frame_of_random_video
  29. download_random_video
  30. extract_frame
  31. delete_video
  32. end
  33. def download_random_video
  34. `#{YOUTUBE_DL_PATH} --playlist-random --max-downloads 1 -o #{VIDEO_PATH} -f mp4 #{@playlist_id}`
  35. end
  36. def extract_frame
  37. length = get_video_length
  38. random_second = rand(0..length)
  39. `#{FFMPEG_PATH} -v error -ss #{random_second} -i #{VIDEO_PATH} -frames 1 -y #{FRAME_PATH}`
  40. end
  41. def get_video_length
  42. `#{FFPROBE_PATH} -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 #{VIDEO_PATH}`.chomp.to_i
  43. end
  44. def delete_video
  45. `rm #{VIDEO_PATH}`
  46. end
  47. def delete_frame
  48. `rm #{FRAME_PATH}`
  49. end
  50. end
  51. class TwitterService
  52. def initialize(key, secret, token, token_secret)
  53. @twitter = Twitter::REST::Client.new do |config|
  54. config.consumer_key = key
  55. config.consumer_secret = secret
  56. config.access_token = token
  57. config.access_token_secret = token_secret
  58. end
  59. end
  60. def tweet_image(filepath)
  61. @twitter.update_with_media(String.new, File.new(filepath))
  62. end
  63. end
  64. youtube = YouTubeService.new(PLAYLIST_ID)
  65. youtube.fetch_random_frame_of_random_video
  66. twitter = TwitterService.new(
  67. TWITTER_CONSUMER_KEY,
  68. TWITTER_CONSUMER_SECRET,
  69. TWITTER_ACCESS_TOKEN,
  70. TWITTER_ACCESS_TOKEN_SECRET,
  71. )
  72. twitter.tweet_image(FRAME_PATH)
  73. youtube.delete_frame