Created
April 20, 2012 10:03
-
-
Save 2called-chaos/2427498 to your computer and use it in GitHub Desktop.
Bad example of how to use the gem YoutubeIt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def upload video | |
@app.stats.yt_videos_new +1 | |
ldata = assemble_local_data | |
result = @instance.connection.video_upload( | |
File.open(video), | |
:title => ldata[:title], | |
:description => ldata[:desc], | |
:keywords => ldata[:keywords], | |
:category => @instance.config['target_category'] | |
) | |
# save record | |
@metayml[digest(video)] = result.unique_id | |
save | |
# add to playlist (youtube has a fucking 200 videos limit on these :/) | |
begin | |
# @instance.connection.add_video_to_playlist(@instance.config['target_playlist'], remote(video)) | |
rescue Exception => e | |
if e.to_s.starts_with?('Invalid playlist id') | |
@app.out("Warning: could not add video to playlist! ".red, true, true) | |
else | |
raise e | |
end | |
end | |
@app.stats.yt_files_uploaded +1 | |
@app.stats.yt_bytes_uploaded File.size(video) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# NOTE: This code relies on a internal gem (for CLI scripts) so this code will not work as it is! | |
# This code in this state is only intended to be a help - it is bad code and was created in hurry without any considerations! | |
# encoding: UTF-8 | |
module Mgt | |
class Youtube | |
attr_accessor :connection, :config | |
def initialize app | |
# libraries | |
require 'youtube_it' | |
require 'yaml' | |
# variables | |
@app = app | |
@config = @app.config['youtube'] | |
@connection = init_connection | |
end | |
def init_connection | |
YouTubeIt::Client.new( | |
username: @config['auth']['username'], | |
password: @config['auth']['password'], | |
dev_key: @config['auth']['apikey'] | |
) | |
end | |
def process_game entry | |
# file controls and garbage collector | |
@app.file_controls do |action| | |
case action | |
when :aborted | |
@app.out " !> EXITING".red, true | |
when :paused | |
@app.out " !> PAUSED".red, true | |
when :unpaused | |
@app.out " !> UNPAUSED".green, true | |
end | |
end | |
GC.start | |
# purge old videos | |
entry.purge | |
# skip? | |
return if entry.skip? | |
# process videos | |
entry.videos.each do |v| | |
process_video(entry, v) | |
end | |
end | |
def process_video entry, video | |
@app.stats.yt_videos +1 | |
if entry.remote(video) == "skip" | |
@app.out "|~> ".yellow + "SKIPPED (marked as duplicate)".red | |
else | |
if entry.remote?(video) && entry.remote_exists?(video) | |
# Skip duplicates in future | |
if entry.duplicate?(video) | |
entry.skip_in_future(video) | |
@app.out "|~> ".yellow + "Duplicate ".red + "#{File.basename(video)}".magenta + " - will skip in future... ".yellow | |
return | |
end | |
if entry.need_update?(video) | |
# ====================== | |
# = update video title = | |
# ====================== | |
@app.out "|~> ".yellow + "Existing ".green + "#{File.basename(video)}".magenta + " - updating... ".yellow, false, true | |
entry.update(video) | |
@app.out "DONE".green, true | |
else | |
@app.out "|~> ".yellow + "Existing ".green + "#{File.basename(video)}".magenta + " - nothing to do... ".green | |
end | |
else | |
# ================ | |
# = upload video = | |
# ================ | |
@app.out "|~> ".yellow + "New video ".green + "#{File.basename(video)}".magenta + " - uploading #{File.size(video).to_filesize}... ".green, false, true | |
entry.upload(video) | |
@app.out "DONE".green, true | |
end | |
end | |
end | |
def collect_all_videos | |
page = 1 | |
base = @connection.my_videos(page: page).videos | |
while true | |
page += 1 | |
more = @connection.my_videos(page: page).videos | |
break if more.length == 0 | |
base = base + more | |
end | |
base | |
end | |
# syncs the whole shit | |
def sync | |
# stats | |
@app.stats.add :yt_games, "games scanned", :yellow | |
@app.stats.add :yt_games_with_video, "games with video files", :yellow | |
@app.stats.add :yt_videos, "videos in total", :yellow | |
@app.stats.add :yt_games_hidden, "hidden games", :yellow | |
@app.stats.add :yt_games_deleted, "deleted games", :yellow | |
@app.stats.add :yt_videos_new, "new videos" | |
@app.stats.add :yt_videos_updated, "updated videos" | |
@app.stats.add :yt_videos_updated_title, "updated video titles" | |
@app.stats.add :yt_videos_updated_description, "updated video descriptions" | |
@app.stats.add :yt_videos_updated_keywords, "updated video keywords" | |
@app.stats.add :yt_videos_deleted, "deleted videos", :red | |
@app.stats.add :yt_videos_duplicates, "videos marked as duplicates", :red | |
@app.stats.add :yt_files_uploaded, "videos uploaded" | |
@app.stats.add :yt_bytes_uploaded, "uploaded", :green, 0, :to_filesize | |
@app.out | |
@app.out "|~INFO~> Synchronize McData trunk with Youtube...".yellow | |
@app.require_mcdata | |
@app.out "|~PROC~> Collecting games... ".yellow, false, true | |
@games = Dir.glob("#{@app.mcdata_root}/[0-9][0-9][0-9][0-9]-*/[0-9][0-9][0-9][0-9]-*") | |
# @games = Dir.glob("#{@app.mcdata_root}/1021-*/[0-9][0-9][0-9][0-9]-*") | |
@app.stats.yt_games @games.length | |
@app.out("DONE (#{@app.stats.yt_games})".green, true) and @app.out | |
# iterate through games | |
i = 0 | |
@games.each do |f| | |
entry = Mgt::Youtube::Entry.new(@app, self, f) | |
i += 1 | |
@app.out "|~PROC~> Processing #{i}/#{@games.length} ".yellow + "#{entry.short}".magenta | |
@app.indent and process_game(entry) | |
@app.out and @app.deindent | |
end | |
end | |
# find broken or unpublished videos | |
def find_broken | |
# stats | |
@app.stats.add :yt_videos, "videos on youtube", :yellow | |
@app.stats.add :yt_videos_scanned, "videos scanned", :green | |
@app.stats.add :yt_videos_broken, "videos broken/unpublished", :red | |
# collect videos | |
@app.out | |
@app.out "|~INFO~> Searching for broken Youtube videos...".yellow | |
@app.out "|~PROC~> Collecting videos... ".yellow, false, true | |
all_videos = collect_all_videos | |
@app.stats.yt_videos all_videos.length | |
@app.out("DONE (#{all_videos.count})".green, true) and @app.out | |
@app.out "|~PROC~> Find broken/unpublished videos... ".yellow and @app.indent | |
all_videos.each do |v| | |
@app.stats.yt_videos_scanned +1 | |
unless v.state[:name] == "published" | |
@app.stats.yt_videos_broken +1 | |
@app.out "|~>".yellow + " #{v.unique_id.magenta} #{v.state[:name].red} " + (v.state[:copy].nil? ? "" : "– Reason: #{v.state[:copy]}".red) | |
end | |
end | |
@app.deindent | |
# iterate through games | |
# i = 0 | |
# @games.each do |f| | |
# entry = Mgt::Youtube::Entry.new(@app, self, f) | |
# i += 1 | |
# @app.out "|~PROC~> Processing #{i}/#{@games.length} ".yellow + "#{entry.short}".magenta | |
# @app.indent and process_game(entry) | |
# @app.out and @app.deindent | |
# end | |
end | |
# =============== | |
# = Entry class = | |
# =============== | |
class Entry | |
attr_accessor :path, :publisher, :game, :short, :digests | |
def initialize app, instance, path | |
@app = app | |
@instance = instance | |
@path = path | |
chunks = @path.gsub("#{@app.mcdata_root}/", "").match(/([0-9]{4})-(?:.*)\/([0-9]{4})-(?:.*)/i) | |
@publisher = chunks[1] | |
@game = chunks[2] | |
@short = @path.gsub("#{@app.mcdata_root}/", "") | |
@digests = {} | |
load_metayml | |
end | |
def upload video | |
@app.stats.yt_videos_new +1 | |
ldata = assemble_local_data | |
result = @instance.connection.video_upload( | |
File.open(video), | |
:title => ldata[:title], | |
:description => ldata[:desc], | |
:keywords => ldata[:keywords], | |
:category => @instance.config['target_category'] | |
) | |
# save record | |
@metayml[digest(video)] = result.unique_id | |
save | |
# add to playlist | |
begin | |
# @instance.connection.add_video_to_playlist(@instance.config['target_playlist'], remote(video)) | |
rescue Exception => e | |
if e.to_s.starts_with?('Invalid playlist id') | |
@app.out("Warning: could not add video to playlist! ".red, true, true) | |
else | |
raise e | |
end | |
end | |
@app.stats.yt_files_uploaded +1 | |
@app.stats.yt_bytes_uploaded File.size(video) | |
end | |
def update video | |
capture_update_stats(video) | |
ldata = assemble_local_data | |
@instance.connection.video_update( | |
remote(video), | |
:title => ldata[:title], | |
:description => ldata[:desc], | |
:keywords => ldata[:keywords], | |
:category => @instance.config['target_category'] | |
) | |
@app.stats.yt_videos_updated +1 | |
end | |
def capture_update_stats video | |
heat = 0 | |
ldata = assemble_local_data | |
rdata = assemble_remote_data(video) | |
# title | |
@app.stats.yt_videos_updated_title +1 if ldata[:title] != rdata[:title] | |
# description | |
@app.stats.yt_videos_updated_description +1 if ldata[:desc] != rdata[:desc] | |
# keywords | |
@app.stats.yt_videos_updated_keywords +1 if ldata[:keywords] != rdata[:keywords] | |
end | |
def map_videos | |
result = [] | |
unless videos == false | |
videos.each do |v| | |
result << digest(v) | |
end | |
end | |
result | |
end | |
def purge | |
map = map_videos | |
@metayml.each do |hash, vid| | |
if !map.include?(hash) || deleted? | |
@app.out "|~> ".yellow + "Deleting video ".red + "#{vid} (#{hash})".magenta + "... ".red, false, true | |
begin | |
@instance.connection.video_delete(vid) | |
@app.out "DONE".green, true | |
@app.stats.yt_videos_deleted +1 | |
rescue Exception => e | |
@app.out "FAILED".red, true | |
end | |
end | |
end | |
return true | |
end | |
def duplicate? video | |
request = @instance.connection.my_video(remote(video)) | |
request.state[:reason_code] == "duplicate" | |
end | |
def skip_in_future video | |
begin | |
# delete | |
@instance.connection.video_delete(remote(video)) | |
@app.stats.yt_videos_deleted +1 | |
# save skip as value | |
@metayml[digest(video)] = "skip" | |
save | |
@app.stats.yt_videos_duplicates +1 | |
rescue Exception => e | |
@app.out "Failed to delete video marked as duplicate".red | |
end | |
end | |
def assemble_local_data | |
data = {} | |
tpl = @instance.config['template'] | |
gamedesc = datayml | |
data[:title] = "#{tpl['title'].gsub("%GAME%", gamedesc['title'])}" | |
data[:desc] = "#{tpl['link'].gsub("%ID%", "#{publisher}#{game}")} » #{gamedesc['desc_short']}".gsub("–", "-") | |
data[:keywords] = assemble_local_keywords | |
data | |
end | |
def remote_exists? video | |
begin | |
@instance.connection.my_video(remote(video)) | |
rescue Exception => e | |
return false if e.to_s == "404" | |
raise e | |
end | |
return true | |
end | |
def assemble_remote_data video | |
data = {} | |
# check if ID exists | |
vid = remote(video) | |
return false if vid.blank? | |
request = @instance.connection.my_video(vid) | |
data[:title] = request.title | |
data[:desc] = request.description | |
data[:keywords] = request.keywords.flatten | |
data | |
end | |
def need_update? video | |
heat = 0 | |
ldata = assemble_local_data | |
rdata = assemble_remote_data(video) | |
return rdata if rdata == false | |
# title | |
heat += 1 if ldata[:title] != rdata[:title] | |
# description | |
heat += 1 if ldata[:desc] != rdata[:desc] | |
# keywords | |
heat += 1 if ldata[:keywords] != rdata[:keywords] | |
heat > 0 | |
end | |
def digest video | |
@digests[video] ||= Digest::SHA1.file(video).to_s | |
end | |
def remote? video | |
remote(video) ? true : false | |
end | |
def remote video | |
@metayml[digest(video)] || nil | |
end | |
def assemble_local_keywords | |
keywords = @instance.config['template']['keywords'] | |
data = datayml | |
# concat specific keywords | |
unless datayml['youtube_keywords'].blank? | |
keywords = keywords + datayml['youtube_keywords'] | |
end | |
# remove double keywords | |
keywords.uniq | |
end | |
def load_metayml | |
begin | |
metayml = YAML::load_file("#{@path}/videos/YOUTUBE") | |
rescue Exception => e | |
metayml = {} | |
end | |
metayml = {} if metayml.blank? | |
@metayml = metayml | |
end | |
def datayml | |
begin | |
datayml = YAML::load_file("#{@path}/description.yml") | |
rescue Exception => e | |
datayml = false | |
end | |
datayml | |
end | |
def save | |
File.open("#{@path}/videos/YOUTUBE", "w") do |f| | |
YAML::dump(@metayml, f) | |
end | |
end | |
def videos | |
videofiles = Dir.glob("#{@path}/videos/*.{mp4,flv}") | |
videofiles.length == 0 ? false : videofiles | |
end | |
def hidden? | |
@path.include?('HIDDEN') | |
end | |
def deleted? | |
@path.include?('DELETED') | |
end | |
def skip? | |
# hidden | |
if hidden? | |
@app.out "|~> ".yellow + "SKIPPED (hidden)".red | |
@app.stats.yt_games_hidden +1 | |
return true | |
end | |
# deleted | |
if deleted? | |
@app.out "|~> ".yellow + "SKIPPED (deleted)".red | |
@app.stats.yt_games_deleted +1 | |
return true | |
end | |
# no videos | |
if videos == false | |
@app.out "|~> ".yellow + "SKIPPED (no video files)".red | |
return true | |
else | |
@app.stats.yt_games_with_video +1 | |
end | |
false | |
end | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment