Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require 'google/apis/youtube_v3'
- require 'googleauth'
- require 'googleauth/stores/file_token_store'
- require 'fileutils'
- require 'json'
- require 'redd'
- require 'dotenv'
- Dotenv.load
- SUBREDDIT = ARGV[0] || 'hiphopheads'
- PLAYLIST_ID = ARGV[1] || 'PLGt3gNR-AoFkJR021gXUKlmqZWFosjXFm'
- INTERVAL = ARGV[2] || 'day'
- DONE_IDS = begin
- File.readlines('/tmp/youtube-' + SUBREDDIT + '.txt').map(&:strip)
- rescue
- []
- end
- SERVICE = Google::Apis::YoutubeV3::YouTubeService.new
- def authorize
- credentials_path = File.join(Dir.home, '.credentials','youtube-api.yaml')
- FileUtils.mkdir_p(File.dirname(credentials_path))
- client_id = Google::Auth::ClientId.from_file(__dir__ + "/client_secret.json")
- token_store = Google::Auth::Stores::FileTokenStore.new(file: credentials_path)
- authorizer = Google::Auth::UserAuthorizer.new(client_id, Google::Apis::YoutubeV3::AUTH_YOUTUBE, token_store)
- user_id = 'default'
- credentials = authorizer.get_credentials(user_id)
- if credentials.nil?
- url = authorizer.get_authorization_url(base_url: 'urn:ietf:wg:oauth:2.0:oob')
- puts "Open the following URL in the browser and enter the resulting code after authorization:"
- puts url
- code = gets
- credentials = authorizer.get_and_store_credentials_from_code(user_id: user_id, code: code, base_url: 'urn:ietf:wg:oauth:2.0:oob')
- end
- credentials
- end
- # --- main program starts here
- SERVICE.authorization = authorize
- class YouTubePlaylist
- def initialize(id)
- @id = id
- end
- def include?(video_id)
- begin
- item = SERVICE.list_playlist_items('snippet', playlist_id: @id, video_id: video_id)
- rescue Google::Apis::ClientError => e
- if e.status_code
- return false
- end
- end
- item.items.size > 0
- end
- def add_video(video_id)
- playlist_item = Google::Apis::YoutubeV3::PlaylistItem.new
- playlist_item.snippet = Google::Apis::YoutubeV3::PlaylistItemSnippet.new(playlist_id: @id)
- playlist_item.snippet.resource_id = Google::Apis::YoutubeV3::ResourceId.new(video_id: video_id, kind: 'youtube#video')
- begin
- SERVICE.insert_playlist_item('snippet', playlist_item)
- return true
- rescue
- return false
- end
- end
- def add_video_unique(video_id)
- add_video(video_id) unless self.include?(video_id)
- end
- end
- class YouTube
- def initialize
- @client = SERVICE
- end
- def get_video(video_id)
- vid = SERVICE.list_videos('snippet,contentDetails', id: video_id).items.first
- title = vid.snippet.title
- duration_parts = vid.content_details.duration.match(/(\d+)M(\d+)S/)
- duration_in_seconds = (duration_parts[1].to_i * 60) + duration_parts[2].to_i
- { title: title, duration: duration_in_seconds }
- rescue
- nil
- end
- end
- REDDIT = Redd.it(:script, ENV['REDDIT_CLIENT_ID'], ENV['REDDIT_SECRET'], ENV['REDDIT_USERNAME'], ENV['REDDIT_PASSWORD'], user_agent: ENV['REDDIT_USER_AGENT'])
- playlist = YouTubePlaylist.new(PLAYLIST_ID)
- items = REDDIT.get_top(SUBREDDIT, t: INTERVAL, limit: 100)
- items.each do |item|
- next unless item.url =~ /youtube\.com\/watch/
- next if item.title =~ /(interview|trailer)/i
- next unless item.ups > 4
- video_id = item.url[/v=(.{11})/, 1]
- if DONE_IDS.include?(video_id)
- STDERR.puts "Already done #{video_id} - skipping"
- next
- end
- File.open('/tmp/youtube-' + SUBREDDIT + '.txt', 'a') do |f|
- f.puts video_id
- end
- STDERR.puts "Doing #{video_id}"
- video = YouTube.new.get_video(video_id)
- if video && !video[:duration].between?(120, 480)
- STDERR.puts "- video is too short or long at #{video[:duration]} seconds, skipping"
- next
- end
- if playlist.add_video_unique(video_id)
- STDERR.puts "- Done"
- else
- STDERR.puts "- Already in playlist, or failed"
- end
- end
Add Comment
Please, Sign In to add comment