appydave-tools 0.9.3 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/bin/youtube_manager.rb +60 -12
- data/lib/appydave/tools/types/array_type.rb +25 -0
- data/lib/appydave/tools/types/hash_type.rb +25 -0
- data/lib/appydave/tools/types/indifferent_access_hash.rb +43 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools/youtube_manager/authorization.rb +6 -3
- data/lib/appydave/tools/youtube_manager/get_video.rb +84 -5
- data/lib/appydave/tools/youtube_manager/models/captions.rb +23 -0
- data/lib/appydave/tools/youtube_manager/models/youtube_details.rb +95 -0
- data/lib/appydave/tools/youtube_manager/reports/video_content_report.rb +7 -7
- data/lib/appydave/tools/youtube_manager/reports/video_details_report.rb +21 -16
- data/lib/appydave/tools/youtube_manager/update_video.rb +53 -0
- data/lib/appydave/tools.rb +11 -1
- data/package-lock.json +2 -2
- data/package.json +1 -1
- metadata +22 -3
- data/lib/appydave/tools/indifferent_access_hash.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed51cab9a76cb09289bbcfa80eb759c3f5d70f656043d25bce0b106f74757aef
|
4
|
+
data.tar.gz: c498125bae1ee080aebe7fd88c0d7c4ceabcb477c0cbd59d8d741c880010bfe6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1520df315b862ca20f306e4e0e0f6ec06b05372858252f3f143e9ba0a7f10fdea18aacc368dd887ad308cdd559ee8664c4b1ad0922d70c89800dfb21124d2a27
|
7
|
+
data.tar.gz: 2b1e3fb4877bb919b3786e56042d2fde5850d85f8e78d7fa6cf2226dc08edc2bd61dac81e73c4de14e181bc784675d981e59277bbabdd31e34c937e2aef6336b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## [0.9.4](https://github.com/klueless-io/appydave-tools/compare/v0.9.3...v0.9.4) (2024-06-12)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* move youtube management data to activemodel ([12d3351](https://github.com/klueless-io/appydave-tools/commit/12d3351b2243c436d0f59e2f2822d9d82cc6ebd6))
|
7
|
+
|
8
|
+
## [0.9.3](https://github.com/klueless-io/appydave-tools/compare/v0.9.2...v0.9.3) (2024-06-12)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* preperation fo the youtube automation tool ([42c1e1d](https://github.com/klueless-io/appydave-tools/commit/42c1e1d3a4ea53491b72140bbf35850e41ce0f1c))
|
14
|
+
* update rubocop version number ([b64739d](https://github.com/klueless-io/appydave-tools/commit/b64739d46a5b3ea6177c2f7512c720b6ed4e6257))
|
15
|
+
|
1
16
|
## [0.9.2](https://github.com/klueless-io/appydave-tools/compare/v0.9.1...v0.9.2) (2024-06-11)
|
2
17
|
|
3
18
|
|
data/bin/youtube_manager.rb
CHANGED
@@ -7,10 +7,12 @@ require 'appydave/tools'
|
|
7
7
|
|
8
8
|
# Process command line arguments for YouTubeVideoManager operations
|
9
9
|
class YouTubeVideoManagerCLI
|
10
|
+
include KLog::Logging
|
11
|
+
|
10
12
|
def initialize
|
11
13
|
@commands = {
|
12
|
-
'get' => method(:fetch_video_details)
|
13
|
-
|
14
|
+
'get' => method(:fetch_video_details),
|
15
|
+
'update' => method(:update_video_details)
|
14
16
|
}
|
15
17
|
end
|
16
18
|
|
@@ -28,16 +30,37 @@ class YouTubeVideoManagerCLI
|
|
28
30
|
|
29
31
|
def fetch_video_details(args)
|
30
32
|
options = parse_options(args, 'get')
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
get_video = Appydave::Tools::YouTubeManager::GetVideo.new
|
34
|
+
get_video.get(options[:video_id])
|
35
|
+
|
36
|
+
if get_video.video?
|
37
|
+
# json = JSON.pretty_generate(details)
|
38
|
+
# puts json
|
35
39
|
|
36
|
-
|
37
|
-
|
40
|
+
report = Appydave::Tools::YouTubeManager::Reports::VideoDetailsReport.new
|
41
|
+
report.print(get_video.data)
|
38
42
|
|
39
|
-
|
40
|
-
|
43
|
+
# report = Appydave::Tools::YouTubeManager::Reports::VideoContentReport.new
|
44
|
+
# report.print(manager.data)
|
45
|
+
else
|
46
|
+
log.error "Video not found! Maybe it's private or deleted. ID: #{options[:video_id]}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def update_video_details(args)
|
51
|
+
options = parse_update_options(args)
|
52
|
+
|
53
|
+
get_video = Appydave::Tools::YouTubeManager::GetVideo.new
|
54
|
+
get_video.get(options[:video_id])
|
55
|
+
|
56
|
+
update_video = Appydave::Tools::YouTubeManager::UpdateVideo.new(get_video.data)
|
57
|
+
|
58
|
+
update_video.title(options[:title]) if options[:title]
|
59
|
+
update_video.description(options[:description]) if options[:description]
|
60
|
+
update_video.tags(options[:tags]) if options[:tags]
|
61
|
+
update_video.category_id(options[:category_id]) if options[:category_id]
|
62
|
+
|
63
|
+
update_video.save
|
41
64
|
end
|
42
65
|
|
43
66
|
def parse_options(args, command)
|
@@ -61,11 +84,36 @@ class YouTubeVideoManagerCLI
|
|
61
84
|
options
|
62
85
|
end
|
63
86
|
|
87
|
+
def parse_update_options(args)
|
88
|
+
options = { video_id: nil }
|
89
|
+
OptionParser.new do |opts|
|
90
|
+
opts.banner = 'Usage: youtube_video_manager.rb update [options]'
|
91
|
+
|
92
|
+
opts.on('-v', '--video-id ID', 'YouTube Video ID') { |v| options[:video_id] = v }
|
93
|
+
opts.on('-t', '--title TITLE', 'Video Title') { |t| options[:title] = t }
|
94
|
+
opts.on('-d', '--description DESCRIPTION', 'Video Description') { |d| options[:description] = d }
|
95
|
+
opts.on('-g', '--tags TAGS', 'Video Tags (comma-separated)') { |g| options[:tags] = g.split(',') }
|
96
|
+
opts.on('-c', '--category-id CATEGORY_ID', 'Video Category ID') { |c| options[:category_id] = c }
|
97
|
+
|
98
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
99
|
+
puts opts
|
100
|
+
exit
|
101
|
+
end
|
102
|
+
end.parse!(args)
|
103
|
+
|
104
|
+
unless options[:video_id]
|
105
|
+
puts 'Missing required options. Use -h for help.'
|
106
|
+
exit
|
107
|
+
end
|
108
|
+
|
109
|
+
options
|
110
|
+
end
|
111
|
+
|
64
112
|
def print_help
|
65
113
|
puts 'Usage: youtube_video_manager.rb [command] [options]'
|
66
114
|
puts 'Commands:'
|
67
|
-
puts ' get
|
68
|
-
|
115
|
+
puts ' get Get details for a YouTube video'
|
116
|
+
puts ' update Update details for a YouTube video'
|
69
117
|
puts "Run 'youtube_video_manager.rb [command] --help' for more information on a command."
|
70
118
|
end
|
71
119
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appydave
|
4
|
+
module Tools
|
5
|
+
module Types
|
6
|
+
# Used by the ActiveModel attributes API to cast values to arrays
|
7
|
+
class ArrayType < ActiveModel::Type::Value
|
8
|
+
def cast(value)
|
9
|
+
case value
|
10
|
+
when String
|
11
|
+
value.split(',')
|
12
|
+
when Array
|
13
|
+
value
|
14
|
+
else
|
15
|
+
raise ArgumentError, "Cannot cast #{value.class} to Array"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def serialize(value)
|
20
|
+
value.join(',')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appydave
|
4
|
+
module Tools
|
5
|
+
module Types
|
6
|
+
# Used by the ActiveModel attributes API to cast values to hashes
|
7
|
+
class HashType < ActiveModel::Type::Value
|
8
|
+
def cast(value)
|
9
|
+
case value
|
10
|
+
when String
|
11
|
+
JSON.parse(value)
|
12
|
+
when Hash
|
13
|
+
value
|
14
|
+
else
|
15
|
+
raise ArgumentError, "Cannot cast #{value.class} to Hash"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def serialize(value)
|
20
|
+
value.to_json
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appydave
|
4
|
+
module Tools
|
5
|
+
module Types
|
6
|
+
# Hash with indifferent access
|
7
|
+
class IndifferentAccessHash < Hash
|
8
|
+
def initialize(initial_hash = {})
|
9
|
+
super()
|
10
|
+
update(initial_hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](key)
|
14
|
+
super(convert_key(key))
|
15
|
+
end
|
16
|
+
|
17
|
+
def []=(key, value)
|
18
|
+
super(convert_key(key), value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def fetch(key, *args)
|
22
|
+
super(convert_key(key), *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete(key)
|
26
|
+
super(convert_key(key))
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def convert_key(key)
|
32
|
+
key.is_a?(Symbol) ? key.to_s : key
|
33
|
+
end
|
34
|
+
|
35
|
+
def update(initial_hash)
|
36
|
+
initial_hash.each do |key, value|
|
37
|
+
self[convert_key(key)] = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -11,7 +11,10 @@ module Appydave
|
|
11
11
|
|
12
12
|
SCOPE = [
|
13
13
|
'https://www.googleapis.com/auth/youtube.readonly',
|
14
|
-
'https://www.googleapis.com/auth/youtube'
|
14
|
+
'https://www.googleapis.com/auth/youtube',
|
15
|
+
'https://www.googleapis.com/auth/youtube.force-ssl',
|
16
|
+
'https://www.googleapis.com/auth/youtubepartner',
|
17
|
+
'https://www.googleapis.com/auth/youtubepartner-channel-audit'
|
15
18
|
].freeze
|
16
19
|
|
17
20
|
def self.authorize
|
@@ -22,11 +25,11 @@ module Appydave
|
|
22
25
|
authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store)
|
23
26
|
user_id = 'default'
|
24
27
|
credentials = authorizer.get_credentials(user_id)
|
25
|
-
credentials = wait_for_authorization(authorizer) if credentials.nil?
|
28
|
+
credentials = wait_for_authorization(authorizer, user_id) if credentials.nil?
|
26
29
|
credentials
|
27
30
|
end
|
28
31
|
|
29
|
-
def self.wait_for_authorization(authorizer)
|
32
|
+
def self.wait_for_authorization(authorizer, user_id)
|
30
33
|
url = authorizer.get_authorization_url(base_url: REDIRECT_URI)
|
31
34
|
puts 'Open the following URL in your browser and authorize the application:'
|
32
35
|
puts url
|
@@ -7,12 +7,26 @@ module Appydave
|
|
7
7
|
class GetVideo < YouTubeBase
|
8
8
|
attr_reader :video_id
|
9
9
|
attr_reader :data
|
10
|
-
attr_reader :video
|
11
10
|
|
12
11
|
def get(video_id)
|
12
|
+
@data = nil
|
13
13
|
@video_id = video_id
|
14
14
|
response = @service.list_videos('snippet,contentDetails,status,statistics', id: video_id)
|
15
|
-
|
15
|
+
video = response.items.first
|
16
|
+
|
17
|
+
return unless video
|
18
|
+
|
19
|
+
build_data(video)
|
20
|
+
end
|
21
|
+
|
22
|
+
def video?
|
23
|
+
!data.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def build_data(video)
|
29
|
+
category_title = get_category_title(video.snippet.category_id)
|
16
30
|
|
17
31
|
data = {
|
18
32
|
id: video.id,
|
@@ -21,6 +35,13 @@ module Appydave
|
|
21
35
|
published_at: video.snippet.published_at,
|
22
36
|
channel_id: video.snippet.channel_id,
|
23
37
|
channel_title: video.snippet.channel_title,
|
38
|
+
category_id: video.snippet.category_id,
|
39
|
+
tags: video.snippet.tags,
|
40
|
+
thumbnails: video.snippet.thumbnails.to_h,
|
41
|
+
default_audio_language: video.snippet.default_audio_language,
|
42
|
+
default_language: video.snippet.default_language,
|
43
|
+
live_broadcast_content: video.snippet.live_broadcast_content,
|
44
|
+
category_title: category_title,
|
24
45
|
view_count: video.statistics.view_count,
|
25
46
|
like_count: video.statistics.like_count,
|
26
47
|
dislike_count: video.statistics.dislike_count,
|
@@ -30,15 +51,73 @@ module Appydave
|
|
30
51
|
license: video.status.license,
|
31
52
|
recording_location: video.recording_details&.location,
|
32
53
|
recording_date: video.recording_details&.recording_date,
|
33
|
-
tags: video.snippet.tags,
|
34
|
-
thumbnails: video.snippet.thumbnails.to_h,
|
35
54
|
duration: video.content_details.duration,
|
36
55
|
definition: video.content_details.definition,
|
37
56
|
caption: video.content_details.caption,
|
38
57
|
licensed_content: video.content_details.licensed_content
|
39
58
|
}
|
59
|
+
get_captions(video.id) # Fetch captions and associate them
|
60
|
+
# HAVE NOT FIGURED OUT THE PERMISSION ISSUE WITH THIS YET
|
61
|
+
# captions: get_captions(video.id) # Fetch captions and associate them
|
62
|
+
@data = Appydave::Tools::YouTubeManager::Models::YouTubeDetails.new(data)
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_category_title(category_id)
|
66
|
+
response = @service.list_video_categories('snippet', id: category_id)
|
67
|
+
category = response.items.first
|
68
|
+
category&.snippet&.title
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_captions(video_id)
|
72
|
+
captions_response = @service.list_captions('id,snippet', video_id)
|
73
|
+
captions_response.items.map do |caption|
|
74
|
+
# puts "Caption ID: #{caption.id}"
|
75
|
+
# puts "Language: #{caption.snippet.language}"
|
76
|
+
# puts "Status: #{caption.snippet.status}"
|
77
|
+
# puts "Track Kind: #{caption.snippet.track_kind}"
|
78
|
+
# puts "Name: #{caption.snippet.name}"
|
79
|
+
# puts "Is Auto-Synced: #{caption.snippet.is_auto_synced}"
|
80
|
+
# puts "Is CC: #{caption.snippet.is_cc}"
|
81
|
+
# puts "Is Draft: #{caption.snippet.is_draft}"
|
82
|
+
# puts "Last Updated: #{caption.snippet.last_updated}"
|
83
|
+
|
84
|
+
next unless caption.snippet.status == 'serving'
|
85
|
+
|
86
|
+
caption_data = {
|
87
|
+
caption_id: caption.id,
|
88
|
+
language: caption.snippet.language,
|
89
|
+
name: caption.snippet.name,
|
90
|
+
status: caption.snippet.status,
|
91
|
+
content: download_caption(caption)
|
92
|
+
}
|
93
|
+
caption_data
|
94
|
+
end.compact
|
95
|
+
end
|
96
|
+
|
97
|
+
def download_caption(caption)
|
98
|
+
content = ''
|
99
|
+
formats = %w[srv1 vtt srt ttml] # Try multiple formats to find a compatible one
|
100
|
+
success = false
|
101
|
+
formats.each do |format|
|
102
|
+
break if content.present?
|
103
|
+
|
104
|
+
begin
|
105
|
+
@service.download_caption(caption.id, tfmt: format) do |result, error|
|
106
|
+
if error.nil?
|
107
|
+
content = result
|
108
|
+
success = true
|
109
|
+
# else
|
110
|
+
# log.info "An error occurred while downloading caption #{caption.id} with format #{format}: #{error.message}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
rescue Google::Apis::ClientError => e
|
114
|
+
log.error "An error occurred while downloading caption #{caption.id} with format #{format}: #{e.message}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
log.error 'Error occurred while downloading captions, make sure you have the correct permissions.' unless success
|
40
119
|
|
41
|
-
|
120
|
+
content
|
42
121
|
end
|
43
122
|
end
|
44
123
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
|
5
|
+
module Appydave
|
6
|
+
module Tools
|
7
|
+
module YouTubeManager
|
8
|
+
module Models
|
9
|
+
# Model to store YouTube video captions (subtitles)
|
10
|
+
class Captions
|
11
|
+
include ActiveModel::Model
|
12
|
+
include ActiveModel::Attributes
|
13
|
+
|
14
|
+
attribute :caption_id, :string
|
15
|
+
attribute :language, :string
|
16
|
+
attribute :name, :string
|
17
|
+
attribute :status, :string
|
18
|
+
attribute :content, :string
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
|
5
|
+
module Appydave
|
6
|
+
module Tools
|
7
|
+
module YouTubeManager
|
8
|
+
module Models
|
9
|
+
# Model to store YouTube video details
|
10
|
+
class YouTubeDetails
|
11
|
+
include ActiveModel::Model
|
12
|
+
include ActiveModel::Attributes
|
13
|
+
|
14
|
+
attribute :id, :string
|
15
|
+
attribute :title, :string # snippet
|
16
|
+
attribute :description, :string # snippet
|
17
|
+
attribute :published_at, :datetime # snippet
|
18
|
+
attribute :channel_id, :string # snippet
|
19
|
+
attribute :channel_title, :string # snippet
|
20
|
+
attribute :category_id, :string # snippet
|
21
|
+
|
22
|
+
attribute :default_audio_language # snippet
|
23
|
+
attribute :default_language # snippet
|
24
|
+
attribute :live_broadcast_content # snippet
|
25
|
+
|
26
|
+
attribute :tags, array: true # snippet
|
27
|
+
attribute :thumbnails, :hash # snippet
|
28
|
+
|
29
|
+
attribute :category_title, :string
|
30
|
+
attribute :view_count, :integer
|
31
|
+
attribute :like_count, :integer
|
32
|
+
attribute :dislike_count, :integer
|
33
|
+
attribute :comment_count, :integer
|
34
|
+
attribute :privacy_status, :string
|
35
|
+
attribute :embeddable, :boolean
|
36
|
+
attribute :license, :string
|
37
|
+
attribute :recording_location, :string
|
38
|
+
attribute :recording_date, :datetime
|
39
|
+
attribute :duration, :string
|
40
|
+
attribute :definition, :string
|
41
|
+
attribute :caption, :boolean
|
42
|
+
attribute :licensed_content, :boolean
|
43
|
+
attribute :captions, :array # , default: []
|
44
|
+
|
45
|
+
def initialize(attributes = {})
|
46
|
+
super
|
47
|
+
self.captions = attributes[:captions].map { |caption| Captions.new(caption) } if attributes[:captions]
|
48
|
+
end
|
49
|
+
|
50
|
+
def map_video_snippet
|
51
|
+
{
|
52
|
+
title: title,
|
53
|
+
description: description,
|
54
|
+
category_id: category_id,
|
55
|
+
tags: tags || [],
|
56
|
+
thumbnails: thumbnails
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_h
|
61
|
+
{
|
62
|
+
id: id,
|
63
|
+
title: title,
|
64
|
+
description: description,
|
65
|
+
published_at: published_at,
|
66
|
+
channel_id: channel_id,
|
67
|
+
channel_title: channel_title,
|
68
|
+
category_id: category_id,
|
69
|
+
category_title: category_title,
|
70
|
+
default_audio_language: default_audio_language,
|
71
|
+
default_language: default_language,
|
72
|
+
live_broadcast_content: live_broadcast_content,
|
73
|
+
tags: tags,
|
74
|
+
thumbnails: thumbnails,
|
75
|
+
view_count: view_count,
|
76
|
+
like_count: like_count,
|
77
|
+
dislike_count: dislike_count,
|
78
|
+
comment_count: comment_count,
|
79
|
+
privacy_status: privacy_status,
|
80
|
+
embeddable: embeddable,
|
81
|
+
license: license,
|
82
|
+
recording_location: recording_location,
|
83
|
+
recording_date: recording_date,
|
84
|
+
duration: duration,
|
85
|
+
definition: definition,
|
86
|
+
caption: caption,
|
87
|
+
licensed_content: licensed_content
|
88
|
+
}
|
89
|
+
# captions: captions.map(&:to_h)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -10,14 +10,14 @@ module Appydave
|
|
10
10
|
|
11
11
|
def print(data)
|
12
12
|
# log.heading 'Video Details Report'
|
13
|
-
log.subheading data
|
14
|
-
log.kv 'Published At', data
|
15
|
-
log.kv 'View Count', data
|
16
|
-
log.kv 'Like Count', data
|
17
|
-
log.kv 'Dislike Count', data
|
18
|
-
log.kv 'Tags', data
|
13
|
+
log.subheading data.title
|
14
|
+
log.kv 'Published At', data.published_at
|
15
|
+
log.kv 'View Count', data.view_count
|
16
|
+
log.kv 'Like Count', data.like_count
|
17
|
+
log.kv 'Dislike Count', data.dislike_count
|
18
|
+
log.kv 'Tags', data.tags.join(', ')
|
19
19
|
log.line
|
20
|
-
puts data
|
20
|
+
puts data.description
|
21
21
|
log.line
|
22
22
|
end
|
23
23
|
end
|
@@ -12,22 +12,27 @@ module Appydave
|
|
12
12
|
# log.heading 'Video Details Report'
|
13
13
|
# log.subheading 'Video Details Report'
|
14
14
|
log.section_heading 'Video Details Report'
|
15
|
-
log.kv 'ID', data
|
16
|
-
log.kv 'Title', data
|
17
|
-
log.kv '
|
18
|
-
log.kv '
|
19
|
-
log.kv '
|
20
|
-
log.kv '
|
21
|
-
log.kv '
|
22
|
-
log.kv '
|
23
|
-
log.kv '
|
24
|
-
log.kv 'Channel
|
25
|
-
log.kv '
|
26
|
-
log.kv '
|
27
|
-
log.kv '
|
28
|
-
log.kv '
|
29
|
-
log.kv '
|
30
|
-
log.kv '
|
15
|
+
log.kv 'ID', data.id
|
16
|
+
log.kv 'Title', data.title
|
17
|
+
log.kv 'Description', data.description[0..100]
|
18
|
+
log.kv 'Published At', data.published_at
|
19
|
+
log.kv 'View Count', data.view_count
|
20
|
+
log.kv 'Like Count', data.like_count
|
21
|
+
log.kv 'Dislike Count', data.dislike_count
|
22
|
+
log.kv 'Comment Count', data.comment_count
|
23
|
+
log.kv 'Privacy Status', data.privacy_status
|
24
|
+
log.kv 'Channel ID', data.channel_id
|
25
|
+
log.kv 'Channel Title', data.channel_title
|
26
|
+
log.kv 'Category ID', data.category_id
|
27
|
+
log.kv 'Category Title', data.category_title
|
28
|
+
log.kv 'Default Audio Language', data.default_audio_language
|
29
|
+
log.kv 'Default Language', data.default_language
|
30
|
+
log.kv 'Live Broadcast Content', data.live_broadcast_content
|
31
|
+
log.kv 'Embeddable', data.embeddable
|
32
|
+
log.kv 'License', data.license
|
33
|
+
log.kv 'Recording Location', data.recording_location
|
34
|
+
log.kv 'Recording Date', data.recording_date
|
35
|
+
log.kv 'Tags', data.tags&.join(', ')
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appydave
|
4
|
+
module Tools
|
5
|
+
module YouTubeManager
|
6
|
+
# Update YouTube video details
|
7
|
+
class UpdateVideo < YouTubeBase
|
8
|
+
attr_reader :video_details
|
9
|
+
attr_reader :snippet
|
10
|
+
|
11
|
+
def initialize(video_details)
|
12
|
+
super()
|
13
|
+
@video_details = video_details
|
14
|
+
end
|
15
|
+
|
16
|
+
def title(title)
|
17
|
+
video_details.title = title
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def description(description)
|
23
|
+
video_details.description = description
|
24
|
+
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def tags(tags)
|
29
|
+
video_details.tags = tags
|
30
|
+
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def category_id(category_id)
|
35
|
+
video_details.category_id = category_id
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def save
|
41
|
+
snippet = video_details.map_video_snippet
|
42
|
+
|
43
|
+
video = Google::Apis::YoutubeV3::Video.new(
|
44
|
+
id: video_details.id,
|
45
|
+
snippet: snippet
|
46
|
+
)
|
47
|
+
|
48
|
+
@service.update_video('snippet', video)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/appydave/tools.rb
CHANGED
@@ -8,6 +8,7 @@ require 'open3'
|
|
8
8
|
require 'openai'
|
9
9
|
require 'optparse'
|
10
10
|
require 'k_log'
|
11
|
+
require 'active_model'
|
11
12
|
|
12
13
|
require 'google/apis/youtube_v3'
|
13
14
|
require 'googleauth'
|
@@ -17,7 +18,12 @@ require 'webrick'
|
|
17
18
|
require 'pry'
|
18
19
|
|
19
20
|
require 'appydave/tools/version'
|
20
|
-
require 'appydave/tools/indifferent_access_hash'
|
21
|
+
require 'appydave/tools/types/indifferent_access_hash'
|
22
|
+
require 'appydave/tools/types/hash_type'
|
23
|
+
require 'appydave/tools/types/array_type'
|
24
|
+
|
25
|
+
ActiveModel::Type.register(:array, Appydave::Tools::Types::ArrayType)
|
26
|
+
ActiveModel::Type.register(:hash, Appydave::Tools::Types::HashType)
|
21
27
|
|
22
28
|
require 'appydave/tools/gpt_context/file_collector'
|
23
29
|
|
@@ -38,9 +44,13 @@ require 'appydave/tools/bank_reconciliation/models/transaction'
|
|
38
44
|
require 'appydave/tools/subtitle_master/clean'
|
39
45
|
|
40
46
|
require 'appydave/tools/youtube_automation/gpt_agent'
|
47
|
+
|
48
|
+
require 'appydave/tools/youtube_manager/models/youtube_details'
|
49
|
+
require 'appydave/tools/youtube_manager/models/captions'
|
41
50
|
require 'appydave/tools/youtube_manager/youtube_base'
|
42
51
|
require 'appydave/tools/youtube_manager/authorization'
|
43
52
|
require 'appydave/tools/youtube_manager/get_video'
|
53
|
+
require 'appydave/tools/youtube_manager/update_video'
|
44
54
|
require 'appydave/tools/youtube_manager/reports/video_details_report'
|
45
55
|
require 'appydave/tools/youtube_manager/reports/video_content_report'
|
46
56
|
|
data/package-lock.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "appydave-tools",
|
3
|
-
"version": "0.9.
|
3
|
+
"version": "0.9.5",
|
4
4
|
"lockfileVersion": 3,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "appydave-tools",
|
9
|
-
"version": "0.9.
|
9
|
+
"version": "0.9.5",
|
10
10
|
"devDependencies": {
|
11
11
|
"@klueless-js/semantic-release-rubygem": "github:klueless-js/semantic-release-rubygem",
|
12
12
|
"@semantic-release/changelog": "^6.0.3",
|
data/package.json
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appydave-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Cruwys
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activemodel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: clipboard
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -169,19 +183,24 @@ files:
|
|
169
183
|
- lib/appydave/tools/configuration/openai.rb
|
170
184
|
- lib/appydave/tools/gpt_context/_doc.md
|
171
185
|
- lib/appydave/tools/gpt_context/file_collector.rb
|
172
|
-
- lib/appydave/tools/indifferent_access_hash.rb
|
173
186
|
- lib/appydave/tools/name_manager/_doc.md
|
174
187
|
- lib/appydave/tools/name_manager/project_name.rb
|
175
188
|
- lib/appydave/tools/subtitle_master/_doc.md
|
176
189
|
- lib/appydave/tools/subtitle_master/clean.rb
|
190
|
+
- lib/appydave/tools/types/array_type.rb
|
191
|
+
- lib/appydave/tools/types/hash_type.rb
|
192
|
+
- lib/appydave/tools/types/indifferent_access_hash.rb
|
177
193
|
- lib/appydave/tools/version.rb
|
178
194
|
- lib/appydave/tools/youtube_automation/_doc.md
|
179
195
|
- lib/appydave/tools/youtube_automation/gpt_agent.rb
|
180
196
|
- lib/appydave/tools/youtube_manager/_doc.md
|
181
197
|
- lib/appydave/tools/youtube_manager/authorization.rb
|
182
198
|
- lib/appydave/tools/youtube_manager/get_video.rb
|
199
|
+
- lib/appydave/tools/youtube_manager/models/captions.rb
|
200
|
+
- lib/appydave/tools/youtube_manager/models/youtube_details.rb
|
183
201
|
- lib/appydave/tools/youtube_manager/reports/video_content_report.rb
|
184
202
|
- lib/appydave/tools/youtube_manager/reports/video_details_report.rb
|
203
|
+
- lib/appydave/tools/youtube_manager/update_video.rb
|
185
204
|
- lib/appydave/tools/youtube_manager/youtube_base.rb
|
186
205
|
- package-lock.json
|
187
206
|
- package.json
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Appydave
|
4
|
-
module Tools
|
5
|
-
# Hash with indifferent access
|
6
|
-
class IndifferentAccessHash < Hash
|
7
|
-
def initialize(initial_hash = {})
|
8
|
-
super()
|
9
|
-
update(initial_hash)
|
10
|
-
end
|
11
|
-
|
12
|
-
def [](key)
|
13
|
-
super(convert_key(key))
|
14
|
-
end
|
15
|
-
|
16
|
-
def []=(key, value)
|
17
|
-
super(convert_key(key), value)
|
18
|
-
end
|
19
|
-
|
20
|
-
def fetch(key, *args)
|
21
|
-
super(convert_key(key), *args)
|
22
|
-
end
|
23
|
-
|
24
|
-
def delete(key)
|
25
|
-
super(convert_key(key))
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def convert_key(key)
|
31
|
-
key.is_a?(Symbol) ? key.to_s : key
|
32
|
-
end
|
33
|
-
|
34
|
-
def update(initial_hash)
|
35
|
-
initial_hash.each do |key, value|
|
36
|
-
self[convert_key(key)] = value
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|