appydave-tools 0.9.3 → 0.9.4
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 +8 -0
- data/bin/youtube_manager.rb +13 -6
- 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 +4 -3
- data/lib/appydave/tools/youtube_manager/get_video.rb +63 -3
- data/lib/appydave/tools/youtube_manager/models/captions.rb +23 -0
- data/lib/appydave/tools/youtube_manager/models/youtube_details.rb +45 -0
- data/lib/appydave/tools/youtube_manager/reports/video_content_report.rb +7 -7
- data/lib/appydave/tools.rb +10 -1
- data/package-lock.json +2 -2
- data/package.json +1 -1
- metadata +20 -2
- 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: 8b6d7348b11097175604d3e0dfa967ad9667a36955b825f3ada9042229d35b86
|
4
|
+
data.tar.gz: 91997ead7011056d971b85e7680ee8a099dee006b944210e0766db23d2a40986
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c454d6b2b206b188cff7529094e9cf5b1895933083e7d712e43d55289e3d93be06b0307bb9dd66f13b4910e625e8108b88e58660df15eeb96abaa28f4e439a6
|
7
|
+
data.tar.gz: 1d1c25c9cf722bea8db372b6edca5d2fa3da909d097b0401e7f12e5d66a2dbb6dc15fe001f0b42a8e484ca4866f7755cd86d1f090608960bc4b980aacd34992b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## [0.9.3](https://github.com/klueless-io/appydave-tools/compare/v0.9.2...v0.9.3) (2024-06-12)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* preperation fo the youtube automation tool ([42c1e1d](https://github.com/klueless-io/appydave-tools/commit/42c1e1d3a4ea53491b72140bbf35850e41ce0f1c))
|
7
|
+
* update rubocop version number ([b64739d](https://github.com/klueless-io/appydave-tools/commit/b64739d46a5b3ea6177c2f7512c720b6ed4e6257))
|
8
|
+
|
1
9
|
## [0.9.2](https://github.com/klueless-io/appydave-tools/compare/v0.9.1...v0.9.2) (2024-06-11)
|
2
10
|
|
3
11
|
|
data/bin/youtube_manager.rb
CHANGED
@@ -7,6 +7,8 @@ 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
14
|
'get' => method(:fetch_video_details)
|
@@ -30,14 +32,19 @@ class YouTubeVideoManagerCLI
|
|
30
32
|
options = parse_options(args, 'get')
|
31
33
|
manager = Appydave::Tools::YouTubeManager::GetVideo.new
|
32
34
|
manager.get(options[:video_id])
|
33
|
-
# json = JSON.pretty_generate(details)
|
34
|
-
# puts json
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
if manager.video?
|
37
|
+
# json = JSON.pretty_generate(details)
|
38
|
+
# puts json
|
39
|
+
|
40
|
+
# report = Appydave::Tools::YouTubeManager::Reports::VideoDetailsReport.new
|
41
|
+
# report.print(manager.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
|
41
48
|
end
|
42
49
|
|
43
50
|
def parse_options(args, command)
|
@@ -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,8 @@ 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'
|
15
16
|
].freeze
|
16
17
|
|
17
18
|
def self.authorize
|
@@ -22,11 +23,11 @@ module Appydave
|
|
22
23
|
authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store)
|
23
24
|
user_id = 'default'
|
24
25
|
credentials = authorizer.get_credentials(user_id)
|
25
|
-
credentials = wait_for_authorization(authorizer) if credentials.nil?
|
26
|
+
credentials = wait_for_authorization(authorizer, user_id) if credentials.nil?
|
26
27
|
credentials
|
27
28
|
end
|
28
29
|
|
29
|
-
def self.wait_for_authorization(authorizer)
|
30
|
+
def self.wait_for_authorization(authorizer, user_id)
|
30
31
|
url = authorizer.get_authorization_url(base_url: REDIRECT_URI)
|
31
32
|
puts 'Open the following URL in your browser and authorize the application:'
|
32
33
|
puts url
|
@@ -7,13 +7,25 @@ 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
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)
|
17
29
|
data = {
|
18
30
|
id: video.id,
|
19
31
|
title: video.snippet.title,
|
@@ -37,8 +49,56 @@ module Appydave
|
|
37
49
|
caption: video.content_details.caption,
|
38
50
|
licensed_content: video.content_details.licensed_content
|
39
51
|
}
|
52
|
+
# HAVE NOT FIGURED OUT THE PERMISSION ISSUE WITH THIS YET
|
53
|
+
# captions: get_captions(video.id) # Fetch captions and associate them
|
54
|
+
@data = Appydave::Tools::YouTubeManager::Models::YouTubeDetails.new(data)
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_captions(video_id)
|
58
|
+
captions_response = @service.list_captions('snippet', video_id)
|
59
|
+
captions_response.items.map do |caption|
|
60
|
+
puts "Caption ID: #{caption.id}"
|
61
|
+
puts "Language: #{caption.snippet.language}"
|
62
|
+
puts "Status: #{caption.snippet.status}"
|
63
|
+
puts "Track Kind: #{caption.snippet.track_kind}"
|
64
|
+
puts "Name: #{caption.snippet.name}"
|
65
|
+
puts "Is Auto-Synced: #{caption.snippet.is_auto_synced}"
|
66
|
+
puts "Is CC: #{caption.snippet.is_cc}"
|
67
|
+
puts "Is Draft: #{caption.snippet.is_draft}"
|
68
|
+
puts "Last Updated: #{caption.snippet.last_updated}"
|
69
|
+
|
70
|
+
next unless caption.snippet.status == 'serving'
|
71
|
+
|
72
|
+
caption_data = {
|
73
|
+
caption_id: caption.id,
|
74
|
+
language: caption.snippet.language,
|
75
|
+
name: caption.snippet.name,
|
76
|
+
status: caption.snippet.status,
|
77
|
+
content: download_caption(caption)
|
78
|
+
}
|
79
|
+
caption_data
|
80
|
+
end.compact
|
81
|
+
end
|
82
|
+
|
83
|
+
def download_caption(caption)
|
84
|
+
content = ''
|
85
|
+
formats = %w[srv1 vtt srt ttml] # Try multiple formats to find a compatible one
|
86
|
+
formats.each do |format|
|
87
|
+
break if content.present?
|
40
88
|
|
41
|
-
|
89
|
+
begin
|
90
|
+
@service.download_caption(caption.id, tfmt: format) do |result, error|
|
91
|
+
if error.nil?
|
92
|
+
content = result
|
93
|
+
else
|
94
|
+
puts "An error occurred while downloading caption #{caption.id} with format #{format}: #{error.message}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
rescue Google::Apis::ClientError => e
|
98
|
+
puts "An error occurred while downloading caption #{caption.id} with format #{format}: #{e.message}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
content
|
42
102
|
end
|
43
103
|
end
|
44
104
|
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,45 @@
|
|
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
|
16
|
+
attribute :description, :string
|
17
|
+
attribute :published_at, :datetime
|
18
|
+
attribute :channel_id, :string
|
19
|
+
attribute :channel_title, :string
|
20
|
+
attribute :view_count, :integer
|
21
|
+
attribute :like_count, :integer
|
22
|
+
attribute :dislike_count, :integer
|
23
|
+
attribute :comment_count, :integer
|
24
|
+
attribute :privacy_status, :string
|
25
|
+
attribute :embeddable, :boolean
|
26
|
+
attribute :license, :string
|
27
|
+
attribute :recording_location, :string
|
28
|
+
attribute :recording_date, :datetime
|
29
|
+
attribute :tags, array: true
|
30
|
+
attribute :thumbnails, :hash
|
31
|
+
attribute :duration, :string
|
32
|
+
attribute :definition, :string
|
33
|
+
attribute :caption, :boolean
|
34
|
+
attribute :licensed_content, :boolean
|
35
|
+
# attribute :captions, :array, default: []
|
36
|
+
|
37
|
+
# def initialize(attributes = {})
|
38
|
+
# super
|
39
|
+
# self.captions = attributes[:captions].map { |caption| Captions.new(caption) } if attributes[:captions]
|
40
|
+
# end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
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
|
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,6 +44,9 @@ 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'
|
data/package-lock.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "appydave-tools",
|
3
|
-
"version": "0.9.
|
3
|
+
"version": "0.9.4",
|
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.4",
|
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,7 +1,7 @@
|
|
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.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Cruwys
|
@@ -10,6 +10,20 @@ bindir: exe
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2024-06-12 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,17 +183,21 @@ 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
|
185
203
|
- lib/appydave/tools/youtube_manager/youtube_base.rb
|
@@ -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
|