Skip to content

Instantly share code, notes, and snippets.

@2called-chaos
Created April 20, 2012 10:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2called-chaos/2427498 to your computer and use it in GitHub Desktop.
Save 2called-chaos/2427498 to your computer and use it in GitHub Desktop.
Bad example of how to use the gem YoutubeIt
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
# 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