appydave-tools 0.9.2 → 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: 82602602047f9464bbce7c2c4ab93bfd7cf016173ea63f0b02a3400a36f93551
4
- data.tar.gz: 23b6e5cfeb756b2f5aa063247900d11d1c54e323436dc966b1c6f2d935745e2f
3
+ metadata.gz: 8b6d7348b11097175604d3e0dfa967ad9667a36955b825f3ada9042229d35b86
4
+ data.tar.gz: 91997ead7011056d971b85e7680ee8a099dee006b944210e0766db23d2a40986
5
5
  SHA512:
6
- metadata.gz: 50601f0240c72cbffe0ca0e80077c57902a6a9ecb5f01d25d5c0741cab5688a8fb0d898a15af3b3962c83868f224ab2a518d9fcc9243957d2a37d5b71c9b576f
7
- data.tar.gz: e71429f51e98106be1a934cdf498a80cd99d7a3475476af0722b64d1fdaff1dbab7909414a8bbbfe937addaef6328a6bcb9f7a2257e2faaeb475559b77ddebde
6
+ metadata.gz: 8c454d6b2b206b188cff7529094e9cf5b1895933083e7d712e43d55289e3d93be06b0307bb9dd66f13b4910e625e8108b88e58660df15eeb96abaa28f4e439a6
7
+ data.tar.gz: 1d1c25c9cf722bea8db372b6edca5d2fa3da909d097b0401e7f12e5d66a2dbb6dc15fe001f0b42a8e484ca4866f7755cd86d1f090608960bc4b980aacd34992b
data/.rubocop.yml CHANGED
@@ -75,8 +75,17 @@ Naming/MethodParameterName:
75
75
  Style/EmptyMethod:
76
76
  Exclude:
77
77
  - "**/spec/**/*"
78
- Style/EmptyFile:
78
+ Lint/EmptyFile:
79
79
  Enabled: false
80
+
81
+ RSpec/SpecFilePathFormat:
82
+ Exclude:
83
+ - "**/spec/**/*"
84
+
85
+ RSpec/SpecFilePathSuffix:
86
+ Exclude:
87
+ - "**/spec/**/*"
88
+
80
89
  Metrics/ParameterLists:
81
90
  Exclude:
82
91
  - "**/spec/**/*"
@@ -97,10 +106,6 @@ Layout/SpaceBeforeComma:
97
106
  # My Preferences - End
98
107
 
99
108
  # RSpec Cops
100
- RSpec/FilePath:
101
- Exclude:
102
- - "**/spec/**/*"
103
-
104
109
  RSpec/NamedSubject:
105
110
  Exclude:
106
111
  - "**/spec/**/*"
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
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
+
9
+ ## [0.9.2](https://github.com/klueless-io/appydave-tools/compare/v0.9.1...v0.9.2) (2024-06-11)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * check for ci errors with openai ([2a9d549](https://github.com/klueless-io/appydave-tools/commit/2a9d549eb95246568ca54c1ec0fb9735cc26cac9))
15
+ * prepare openai for CI testing ([09c0d5a](https://github.com/klueless-io/appydave-tools/commit/09c0d5a998d00abb52eb3f09125bb955af1917d9))
16
+ * prepare openai for CI testing [#2](https://github.com/klueless-io/appydave-tools/issues/2) ([82247fc](https://github.com/klueless-io/appydave-tools/commit/82247fc2f421bd88859d25b0fbe88493b6e6d87e))
17
+
1
18
  ## [0.9.1](https://github.com/klueless-io/appydave-tools/compare/v0.9.0...v0.9.1) (2024-06-11)
2
19
 
3
20
 
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
+
6
+ require 'appydave/tools'
7
+
8
+ options = {
9
+ sequence: nil,
10
+ debug: false
11
+ }
12
+
13
+ OptionParser.new do |opts|
14
+ opts.banner = 'Usage: youtube_automation.rb [options]'
15
+
16
+ opts.on('-s', '--sequence SEQUENCE', 'Sequence number (e.g., 01-1)') do |sequence|
17
+ options[:sequence] = sequence
18
+ end
19
+
20
+ opts.on('-d', '--debug', 'Enable debug mode') do
21
+ options[:debug] = true
22
+ end
23
+
24
+ opts.on_tail('-h', '--help', 'Show this message') do
25
+ puts opts
26
+ exit
27
+ end
28
+ end.parse!
29
+
30
+ if options[:sequence].nil?
31
+ puts 'Error: Sequence number is required. Use -h for help.'
32
+ exit 1
33
+ end
34
+
35
+ Appydave::Tools::Configuration::Config.configure
36
+
37
+ automation = Appydave::Tools::YoutubeAutomation::GptAgent.new(options[:sequence], options[:debug])
38
+ automation.run
@@ -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)
@@ -2,6 +2,7 @@
2
2
 
3
3
  [ChatGPT conversation](https://chatgpt.com/g/g-4dMsIRK3E-ruby-script-assistant/c/d8ea5960-071b-48aa-9fd9-554ca302c7dd)
4
4
  [ChatGPT conversation for Schema](https://chatgpt.com/c/bb93e7ac-f139-44f9-8b9c-4e74ac2fa461)
5
+ [ChatGPT conversation for the YoutubeAutomationConfig][https://chatgpt.com/c/a7993d3f-35c9-4ec6-8cd6-5a506bfa22df]
5
6
 
6
7
 
7
8
  ## Schema
@@ -15,6 +15,7 @@ module Appydave
15
15
 
16
16
  def initialize
17
17
  @config_path = File.join(Config.config_path, "#{config_name}.json")
18
+ puts "Config path: #{config_path}"
18
19
  @data = load
19
20
  end
20
21
 
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module Configuration
6
+ module Models
7
+ # Configuration model for Youtube automation
8
+ class YoutubeAutomationConfig < ConfigBase
9
+ def workflow_groups
10
+ data['workflow_groups'].map do |group|
11
+ WorkflowGroup.new(group)
12
+ end
13
+ end
14
+
15
+ def workflow_steps
16
+ data['workflow_steps'].map do |step|
17
+ WorkflowStep.new(step)
18
+ end
19
+ end
20
+
21
+ def get_workflow_group(group_id)
22
+ group_data = data['workflow_groups'].find { |group| group['group'] == group_id }
23
+ WorkflowGroup.new(group_data) if group_data
24
+ end
25
+
26
+ def get_workflow_steps(group_id)
27
+ data['workflow_steps'].select { |step| step['group'] == group_id }.map do |step|
28
+ WorkflowStep.new(step)
29
+ end
30
+ end
31
+
32
+ def get_sequence(sequence)
33
+ group, seq = sequence.split('-')
34
+ workflow_steps.find { |step| step.group == group && step.sequence == seq }
35
+ end
36
+
37
+ def next_sequence(sequence)
38
+ group, seq = sequence.split('-')
39
+ current_index = workflow_steps.find_index { |step| step.group == group && step.sequence == seq }
40
+ workflow_steps[current_index + 1] if current_index && current_index < workflow_steps.size - 1
41
+ end
42
+
43
+ def previous_sequence(sequence)
44
+ group, seq = sequence.split('-')
45
+ current_index = workflow_steps.find_index { |step| step.group == group && step.sequence == seq }
46
+ workflow_steps[current_index - 1] if current_index&.positive?
47
+ end
48
+
49
+ private
50
+
51
+ def default_data
52
+ {
53
+ 'workflow_groups' => [],
54
+ 'workflow_steps' => []
55
+ }
56
+ end
57
+
58
+ # Model for workflow groups
59
+ class WorkflowGroup
60
+ attr_accessor :group, :description
61
+
62
+ def initialize(data)
63
+ @group = data['group']
64
+ @description = data['description']
65
+ end
66
+
67
+ def to_h
68
+ {
69
+ 'group' => @group,
70
+ 'description' => @description
71
+ }
72
+ end
73
+ end
74
+
75
+ # Model for workflow steps
76
+ class WorkflowStep
77
+ attr_accessor :group, :sequence, :name, :description
78
+
79
+ def initialize(data)
80
+ @group = data['group']
81
+ @sequence = data['sequence']
82
+ @name = data['name']
83
+ @description = data['description']
84
+ end
85
+
86
+ def filename(ext)
87
+ "#{@group}-#{@sequence}-#{@name}.#{ext}"
88
+ end
89
+
90
+ def to_h
91
+ {
92
+ 'group' => @group,
93
+ 'sequence' => @sequence,
94
+ 'name' => @name,
95
+ 'description' => @description
96
+ }
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ 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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Appydave
4
4
  module Tools
5
- VERSION = '0.9.2'
5
+ VERSION = '0.9.4'
6
6
  end
7
7
  end
@@ -0,0 +1,12 @@
1
+ # Youtube Automation
2
+
3
+ ChatGPT: https://chatgpt.com/c/2971aaeb-71f7-4981-9c85-21f1dabef9d9
4
+
5
+ YouTube automation is a set of tools for building YouTube videos automatically. The tools are designed to help with the following tasks:
6
+
7
+ [REWRITE THIS INFORMATION ONCE WE HAVE MORE DETAILS]
8
+
9
+ - Take a video concept or topic as simple
10
+ - Build out a simple title based on the topic
11
+ - Develop basic research around the area of keyboards
12
+ - Develop a fat sheet that has the basic information about the topic
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module YoutubeAutomation
6
+ # GPT Agent interacts with OpenAI's GPT API to generate responses based on prompts for YouTube automation.
7
+ class GptAgent
8
+ include Appydave::Tools::Configuration::Configurable
9
+
10
+ def initialize(sequence, debug: false)
11
+ @sequence = sequence
12
+ @debug = debug
13
+ @prompts_path = '/Users/davidcruwys/Library/CloudStorage/Dropbox/team-tldr/_common/raw_prompts'
14
+ end
15
+
16
+ def run
17
+ step = config.youtube_automation.get_sequence(@sequence)
18
+ unless step
19
+ puts "Error: Step #{@sequence} not found in the configuration."
20
+ exit 1
21
+ end
22
+
23
+ prompt_content = read_prompt(step)
24
+
25
+ puts "Running sequence: #{@sequence}"
26
+ puts "Prompt file: #{prompt_file}"
27
+ puts "Prompt content:\n#{prompt_content}" if @debug
28
+
29
+ response = run_prompt(prompt_content)
30
+
31
+ puts "Response:\n#{response}"
32
+ save_response(prompt_file, response)
33
+ end
34
+
35
+ private
36
+
37
+ def read_prompt(_step)
38
+ File.read(filename)
39
+ rescue Errno::ENOENT
40
+ puts "Error: Prompt file #{filename} not found."
41
+ exit 1
42
+ end
43
+
44
+ def run_prompt(prompt_content)
45
+ client = OpenAI::Client.new(access_token: ENV.fetch('OPENAI_ACCESS_TOKEN', nil))
46
+ response = client.completions(
47
+ engine: 'davinci-codex',
48
+ prompt: prompt_content,
49
+ max_tokens: 1000
50
+ )
51
+ response['choices'][0]['text'].strip
52
+ rescue StandardError => e
53
+ puts "Error: Failed to run prompt. #{e.message}"
54
+ exit 1
55
+ end
56
+
57
+ def save_response(filename, response)
58
+ output_filename = filename.gsub('.md', '-output.md')
59
+ File.write(output_filename, response)
60
+ puts "Response saved to #{output_filename}"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ # Youtube Manager
2
+
3
+ Service classes for interacting with the YouTube API.
@@ -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
 
@@ -28,6 +34,7 @@ require 'appydave/tools/configuration/models/config_base'
28
34
  require 'appydave/tools/configuration/models/settings_config'
29
35
  require 'appydave/tools/configuration/models/bank_reconciliation_config'
30
36
  require 'appydave/tools/configuration/models/channels_config'
37
+ require 'appydave/tools/configuration/models/youtube_automation_config'
31
38
  require 'appydave/tools/name_manager/project_name'
32
39
  require 'appydave/tools/bank_reconciliation/clean/clean_transactions'
33
40
  require 'appydave/tools/bank_reconciliation/clean/read_transactions'
@@ -36,6 +43,10 @@ require 'appydave/tools/bank_reconciliation/models/transaction'
36
43
 
37
44
  require 'appydave/tools/subtitle_master/clean'
38
45
 
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'
39
50
  require 'appydave/tools/youtube_manager/youtube_base'
40
51
  require 'appydave/tools/youtube_manager/authorization'
41
52
  require 'appydave/tools/youtube_manager/get_video'
@@ -47,6 +58,7 @@ Appydave::Tools::Configuration::Config.set_default do |config|
47
58
  config.register(:settings, Appydave::Tools::Configuration::Models::SettingsConfig)
48
59
  config.register(:bank_reconciliation, Appydave::Tools::Configuration::Models::BankReconciliationConfig)
49
60
  config.register(:channels, Appydave::Tools::Configuration::Models::ChannelsConfig)
61
+ config.register(:youtube_automation, Appydave::Tools::Configuration::Models::YoutubeAutomationConfig)
50
62
  end
51
63
 
52
64
  module Appydave
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.9.2",
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.2",
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.2",
3
+ "version": "0.9.4",
4
4
  "description": "AppyDave YouTube Automation Tools",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
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.2
4
+ version: 0.9.4
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 00:00:00.000000000 Z
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
@@ -148,6 +162,7 @@ files:
148
162
  - bin/gpt_context.rb
149
163
  - bin/setup
150
164
  - bin/subtitle_master.rb
165
+ - bin/youtube_automation.rb
151
166
  - bin/youtube_manager.rb
152
167
  - images.log
153
168
  - lib/appydave/tools.rb
@@ -164,17 +179,25 @@ files:
164
179
  - lib/appydave/tools/configuration/models/config_base.rb
165
180
  - lib/appydave/tools/configuration/models/settings_config copy.xrb
166
181
  - lib/appydave/tools/configuration/models/settings_config.rb
182
+ - lib/appydave/tools/configuration/models/youtube_automation_config.rb
167
183
  - lib/appydave/tools/configuration/openai.rb
168
184
  - lib/appydave/tools/gpt_context/_doc.md
169
185
  - lib/appydave/tools/gpt_context/file_collector.rb
170
- - lib/appydave/tools/indifferent_access_hash.rb
171
186
  - lib/appydave/tools/name_manager/_doc.md
172
187
  - lib/appydave/tools/name_manager/project_name.rb
173
188
  - lib/appydave/tools/subtitle_master/_doc.md
174
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
175
193
  - lib/appydave/tools/version.rb
194
+ - lib/appydave/tools/youtube_automation/_doc.md
195
+ - lib/appydave/tools/youtube_automation/gpt_agent.rb
196
+ - lib/appydave/tools/youtube_manager/_doc.md
176
197
  - lib/appydave/tools/youtube_manager/authorization.rb
177
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
178
201
  - lib/appydave/tools/youtube_manager/reports/video_content_report.rb
179
202
  - lib/appydave/tools/youtube_manager/reports/video_details_report.rb
180
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