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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d25de201fe246c80fe143f7414bfa76a4c8dc35a4d4ba26086ad4597b699a26
4
- data.tar.gz: 9785e23d8743eb724082ceb7d9b699df06ca88e9ebc81401dc00f0af457527d3
3
+ metadata.gz: 8b6d7348b11097175604d3e0dfa967ad9667a36955b825f3ada9042229d35b86
4
+ data.tar.gz: 91997ead7011056d971b85e7680ee8a099dee006b944210e0766db23d2a40986
5
5
  SHA512:
6
- metadata.gz: 83964602096a76ca0dde6ad5362e5e521ac2fae2c2041f1cb1a989b11ac351892e9a47cc1b4d00afb3ed08d76b108a3192b04437a675c6bcf1d75ad19c423de0
7
- data.tar.gz: a902575b0e19003e6326b2605ee3a31636a0d70b399b7180a3464c532e5b3ca603bed1cded2b1999b4406905b584cae3cc40eff0946d1bdf44395223527a67a2
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
 
@@ -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
- # report = Appydave::Tools::YouTubeManager::Reports::VideoDetailsReport.new
37
- # report.print(manager.data)
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
- report = Appydave::Tools::YouTubeManager::Reports::VideoContentReport.new
40
- report.print(manager.data)
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Appydave
4
4
  module Tools
5
- VERSION = '0.9.3'
5
+ VERSION = '0.9.4'
6
6
  end
7
7
  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
- @video = response.items.first
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
- @data = Appydave::Tools::IndifferentAccessHash.new(data)
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[: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(', ')
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[:description]
20
+ puts data.description
21
21
  log.line
22
22
  end
23
23
  end
@@ -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",
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.3",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "description": "AppyDave YouTube Automation Tools",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
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.3
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