appydave-tools 0.9.2 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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