appydave-tools 0.14.1 → 0.16.0

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/CLAUDE.md +537 -28
  4. data/README.md +262 -86
  5. data/bin/subtitle_manager.rb +18 -12
  6. data/bin/subtitle_processor.rb +158 -0
  7. data/docs/archive/codebase-audit-2025-01.md +424 -0
  8. data/docs/archive/documentation-framework-proposal.md +808 -0
  9. data/docs/archive/purpose-and-philosophy.md +110 -0
  10. data/docs/archive/test-coverage-quick-wins.md +342 -0
  11. data/docs/archive/tool-discovery.md +199 -0
  12. data/docs/archive/tool-documentation-analysis.md +592 -0
  13. data/docs/tools/bank-reconciliation.md +269 -0
  14. data/docs/tools/cli-actions.md +444 -0
  15. data/docs/tools/configuration.md +329 -0
  16. data/docs/{usage → tools}/gpt-context.md +118 -7
  17. data/docs/tools/index.md +324 -0
  18. data/docs/tools/move-images.md +295 -0
  19. data/docs/tools/name-manager.md +322 -0
  20. data/docs/tools/prompt-tools.md +209 -0
  21. data/docs/tools/subtitle-processor.md +242 -0
  22. data/docs/tools/youtube-automation.md +258 -0
  23. data/docs/tools/youtube-manager.md +248 -0
  24. data/exe/ad_config +6 -0
  25. data/exe/gpt_context +6 -0
  26. data/exe/prompt_tools +6 -0
  27. data/exe/subtitle_manager +6 -0
  28. data/exe/youtube_automation +6 -0
  29. data/exe/youtube_manager +6 -0
  30. data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/clean.rb +1 -1
  31. data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/join.rb +5 -2
  32. data/lib/appydave/tools/version.rb +1 -1
  33. data/lib/appydave/tools.rb +2 -4
  34. data/package.json +1 -1
  35. metadata +43 -14
  36. data/lib/mj-paste-test/main.rb +0 -35
  37. data/lib/mj-paste-test/prompts.txt +0 -18
  38. data/lib/mj-paste-test/readme-leonardo.md +0 -0
  39. /data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/_doc-clean.md +0 -0
  40. /data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/_doc-join.md +0 -0
  41. /data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/_doc-todo.md +0 -0
data/README.md CHANGED
@@ -1,157 +1,333 @@
1
- # Appydave Tools
1
+ # AppyDave Tools
2
2
 
3
- > AppyDave YouTube Automation Tools
3
+ > **AppyDave's YouTube productivity toolkit** - Command-line utilities that automate the boring stuff so you can focus on creating content.
4
+
5
+ ## Why This Exists
6
+
7
+ As a YouTuber, I got tired of repetitive tasks eating into my creative time. So I built tools to handle them.
8
+
9
+ Instead of managing dozens of separate repositories, everything lives here - one codebase, easier maintenance, and each tool can be featured in its own video tutorial.
10
+
11
+ **Quick wins:**
12
+ - 🤖 Feed entire codebases to AI assistants in seconds
13
+ - 📹 Batch update YouTube video metadata without clicking through the UI (update 50 videos in 5 minutes)
14
+ - 📝 Process subtitle files - clean formatting, merge multi-part recordings, synchronize timelines
15
+ - 🖼️ Organize downloaded images into project folders automatically (video asset workflow)
16
+ - ⚙️ Manage multi-channel configurations from the command line (team-shareable JSON configs)
4
17
 
5
18
  ## Installation
6
19
 
7
- Add this line to your application's Gemfile:
20
+ ```bash
21
+ gem install appydave-tools
22
+ ```
23
+
24
+ Or add to your Gemfile:
8
25
 
9
26
  ```ruby
10
27
  gem 'appydave-tools'
11
28
  ```
12
29
 
13
- And then execute:
30
+ ## The Tools
31
+
32
+ ### 🤖 GPT Context Gatherer
33
+
34
+ **The problem:** AI assistants need context about your code, but copying files is tedious.
35
+
36
+ **The solution:** Automatically collect and format project files for AI context.
14
37
 
15
38
  ```bash
16
- bundle install
39
+ # Gather all Ruby files, skip tests, save to clipboard
40
+ gpt_context -i '**/*.rb' -e 'spec/**/*' -d
41
+
42
+ # Get project structure as a tree
43
+ gpt_context -i '**/*' -f tree -d
44
+
45
+ # Multiple file types with custom output
46
+ gpt_context -i 'apps/**/*.ts' -i 'apps/**/*.tsx' -e '**/node_modules/**/*' -o context.txt
17
47
  ```
18
48
 
19
- Or install it yourself as:
49
+ **Use cases:** Working with ChatGPT, Claude, or any AI assistant on your codebase.
50
+
51
+ [Full documentation →](./docs/usage/gpt-context.md)
52
+
53
+ ---
54
+
55
+ ### 📹 YouTube Manager
56
+
57
+ **The problem:** Updating video metadata through YouTube Studio is slow and repetitive, especially for bulk operations.
58
+
59
+ **The solution:** Manage YouTube video metadata via API from your terminal - CRUD operations on videos.
20
60
 
21
61
  ```bash
22
- gem install appydave-tools
23
- ```
62
+ # Get video details (title, description, tags, category, captions)
63
+ youtube_manager get --video-id YOUR_VIDEO_ID
24
64
 
25
- ## Stories
65
+ # Update title and description
66
+ youtube_manager update --video-id YOUR_VIDEO_ID \
67
+ --title "New Title" \
68
+ --description "Updated description"
26
69
 
27
- ### Main Story
70
+ # Update tags (replaces existing tags)
71
+ youtube_manager update --video-id YOUR_VIDEO_ID --tags "tutorial,productivity,automation"
28
72
 
29
- As a Content Creator, I want accellerate my video creation, so that I can improve speed and quality of my content
73
+ # Update category
74
+ youtube_manager update --video-id YOUR_VIDEO_ID --category-id 28
75
+ ```
30
76
 
31
- See all [stories](./STORIES.md)
77
+ **Specific use cases:**
78
+ - **Post-rebrand updates**: Changed channel name? Update 50 video descriptions in minutes
79
+ - **Tag standardization**: Ensure consistent tagging across your entire catalog
80
+ - **Metadata retrieval**: Export video details for analysis or backup
81
+ - **Batch corrections**: Fix typos in titles across multiple videos
82
+ - **Category changes**: Recategorize videos when YouTube updates categories
83
+ - **Series updates**: Add series links to descriptions across episode batches
32
84
 
85
+ **What it does:**
86
+ - **Get**: Retrieves complete video metadata including captions
87
+ - **Update**: Modifies title, description, tags, or category via YouTube Data API v3
88
+ - **Authorization**: Handles OAuth2 flow with local callback server
89
+ - **Reporting**: Generates detailed reports of video metadata
33
90
 
34
- ## Usage
91
+ **Why use this vs YouTube Studio:**
92
+ - **Speed**: Update 20 videos in 5 minutes vs 30+ minutes clicking through UI
93
+ - **Scriptable**: Integrate into automation workflows
94
+ - **Bulk operations**: Loop through video IDs from a CSV
95
+ - **Version control**: Track metadata changes in Git
96
+ - **Backup**: Export all video metadata as JSON
35
97
 
36
- ### CLI Tools
98
+ ---
37
99
 
38
- This gem provides several command-line tools for content creation and YouTube automation:
100
+ ### 📝 Subtitle Processor
39
101
 
40
- #### GPT Context Gatherer
41
- Collect and organize project files for AI context analysis:
102
+ **The problem:** Raw subtitle files need cleanup, and multi-part recordings need merged subtitles.
42
103
 
43
- ```bash
44
- # Basic usage - gather all Ruby files, exclude specs
45
- gpt_context -i '**/*.rb' -e 'spec/**/*' -d -o context.txt
104
+ **The solution:** Process and transform SRT files - clean formatting, merge duplicates, synchronize timelines.
46
105
 
47
- # Multiple patterns with tree and content output
48
- gpt_context -i 'lib/**/*.rb' -i 'bin/**/*.rb' -f tree,content -d
106
+ ```bash
107
+ # Clean auto-generated subtitles (removes HTML tags, merges duplicates, normalizes spacing)
108
+ subtitle_processor clean -f input.srt -o cleaned.srt
49
109
 
50
- # Advanced filtering for web projects
51
- gpt_context -i 'apps/**/*.ts' -i 'apps/**/*.tsx' -e '**/node_modules/**/*' -e '**/_generated/**/*' -d -f tree -o typescript-files.txt
110
+ # Merge multiple subtitle files with timeline synchronization
111
+ subtitle_processor join -d ./parts -f "*.srt" -o final.srt
52
112
 
53
- # Documentation and config files
54
- gpt_context -i 'docs/**/*' -i '**/*.json' -i '**/*.config.*' -e '**/node_modules/**/*' -d -f tree
113
+ # Custom time buffer between merged sections (in milliseconds)
114
+ subtitle_processor join -f "part1.srt,part2.srt" -b 200 -o merged.srt
55
115
  ```
56
116
 
57
- See detailed usage guide: [GPT Context Gatherer](./docs/usage/gpt-context.md)
117
+ **What it does:**
118
+ - **Clean**: Removes `<u>` tags, merges duplicate entries, normalizes line breaks and spacing
119
+ - **Join**: Parses multiple SRT files, adjusts timestamps with buffers, merges into single timeline
58
120
 
59
- #### YouTube Manager
60
- ```bash
61
- # Get video details
62
- bin/youtube_manager.rb get [options]
121
+ **Use cases:** Cleaning messy YouTube auto-captions, merging FliVideo multi-part recording subtitles.
122
+
123
+ **Note:** CLI command is `subtitle_processor` (renamed from `subtitle_manager` for accuracy - this tool *processes* files, not manages state).
124
+
125
+ ---
126
+
127
+ ### 🎯 Prompt Tools *(Experimental - Not actively used)*
128
+
129
+ **The problem:** Running OpenAI prompts with placeholder substitution and output management.
130
+
131
+ **The solution:** Execute OpenAI completion API calls with template support.
63
132
 
64
- # Update video metadata
65
- bin/youtube_manager.rb update [options]
133
+ ```bash
134
+ # Run prompt from text
135
+ prompt_tools completion -p "Your prompt here" -o output.txt
136
+
137
+ # Run prompt from file with placeholders
138
+ prompt_tools completion -f prompt_template.md -k topic=Ruby,style=tutorial -c
139
+
140
+ # Options:
141
+ # -p, --prompt Inline prompt text
142
+ # -f, --file Prompt template file
143
+ # -k, --placeholders Key-value pairs for {placeholder} substitution
144
+ # -o, --output Save to file
145
+ # -c, --clipboard Copy to clipboard
146
+ # -m, --model OpenAI model to use
66
147
  ```
67
148
 
68
- #### Subtitle Manager
149
+ **What it does:**
150
+ - Sends prompts to OpenAI Completion API (older GPT-3 models)
151
+ - Supports template files with `{placeholder}` substitution
152
+ - Outputs to file, clipboard, or stdout
153
+
154
+ **Current status:** ⚠️ **Not in active use** - Uses deprecated OpenAI Completion API (`davinci-codex`). Modern alternative: Use ChatGPT or Claude directly, or migrate to Chat API.
155
+
156
+ **Potential use cases:** Template-based content generation, automated prompt workflows (if migrated to Chat API).
157
+
158
+ ---
159
+
160
+ ### ⚡ YouTube Automation *(Internal/Experimental)*
161
+
162
+ **The problem:** Video content creation workflows involve multiple steps: research → scripting → production.
163
+
164
+ **The solution:** Run predefined prompt sequences against OpenAI API to automate research and content generation steps.
165
+
69
166
  ```bash
70
- # Clean subtitle files
71
- bin/subtitle_manager.rb clean [options]
167
+ # Run automation sequence (requires configuration)
168
+ youtube_automation -s 01-1
72
169
 
73
- # Join multiple subtitle parts
74
- bin/subtitle_manager.rb join [options]
170
+ # With debug output
171
+ youtube_automation -s 01-1 -d
75
172
  ```
76
173
 
77
- #### Prompt Tools
174
+ **What it does:**
175
+ - Loads sequence configuration from `~/.config/appydave/youtube_automation.json`
176
+ - Reads prompt templates from Dropbox (`_common/raw_prompts/`)
177
+ - Executes OpenAI API calls for each sequence step
178
+ - Saves responses to output files
179
+
180
+ **Configuration required:**
181
+ - Sequence definitions in `youtube_automation.json`
182
+ - Prompt template files in configured Dropbox path
183
+ - `OPENAI_ACCESS_TOKEN` environment variable
184
+
185
+ **Current status:** ⚠️ **Internal tool** - Hardcoded Dropbox paths, uses deprecated Completion API, not documented for external use.
186
+
187
+ **Relationship to other tools:** This is separate from **Move Images** tool (which organizes downloaded images into video project asset folders).
188
+
189
+ **Use cases:** Automated content research, script outline generation, multi-step prompt workflows.
190
+
191
+ ---
192
+
193
+ ### ⚙️ Configuration Manager
194
+
195
+ **The problem:** Managing settings for multiple YouTube channels, project paths, and automation sequences gets messy.
196
+
197
+ **The solution:** Centralized JSON-based configuration stored in `~/.config/appydave/`.
198
+
78
199
  ```bash
79
- # Run AI prompt completion
80
- bin/prompt_tools.rb completion [options]
200
+ # List all configurations
201
+ ad_config -l
202
+
203
+ # Create missing config files with templates
204
+ ad_config -c
205
+
206
+ # Edit configurations in VS Code
207
+ ad_config -e
208
+
209
+ # View specific configuration values
210
+ ad_config -p settings,channels
211
+
212
+ # View all configurations
213
+ ad_config -p
81
214
  ```
82
215
 
216
+ **What it manages:**
217
+ - **settings.json**: Project folder paths (content, video, published, abandoned)
218
+ - **channels.json**: YouTube channel definitions (code, name, youtube_handle)
219
+ - **youtube_automation.json**: Automation sequence configurations
83
220
 
84
- ## Development
221
+ **Use cases:**
222
+ - **Multi-channel management**: Switch between different YouTube channels
223
+ - **Team collaboration**: Share configuration files via Git/Dropbox (excluding secrets)
224
+ - **Workflow standardization**: Consistent paths across team members
225
+ - **Automation setup**: Define reusable prompt sequences
226
+
227
+ **Team collaboration notes:**
228
+ - Configuration files can be version-controlled (they contain no secrets)
229
+ - Each team member can maintain their own `~/.config/appydave/` directory
230
+ - Paths can be customized per developer machine
231
+ - Secrets (API keys) stored separately in `.env` files (gitignored)
232
+
233
+ ---
85
234
 
86
- Checkout the repo
235
+ ### 🖼️ Move Images *(Development tool)*
236
+
237
+ **The problem:** Downloaded images need organizing with proper naming.
238
+
239
+ **The solution:** Batch move and rename to project folders.
87
240
 
88
241
  ```bash
89
- git clone https://github.com/appydave/appydave-tools
242
+ # Organize intro images for video project
243
+ bin/move_images.rb -f b40 intro b40
244
+ # Result: b40-intro-1.jpg, b40-intro-2.jpg in assets/intro/
90
245
  ```
91
246
 
92
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
247
+ **Use cases:** B-roll organization, thumbnail preparation.
93
248
 
94
- You can also run `bin/console` for an interactive prompt that will allow you to experiment.
249
+ ---
95
250
 
96
- ```bash
97
- bin/console
251
+ ## Philosophy
98
252
 
99
- Appydave::Tools::VERSION
100
- # => "0.14.0"
253
+ **One codebase, multiple tools.** Easier to maintain than dozens of repos.
101
254
 
102
- # Access configuration
103
- config = Appydave::Tools::Configuration::Config.new
104
- # => #<Appydave::Tools::Configuration::Config:...>
105
- ```
255
+ **Single-purpose utilities.** Each tool does one thing well.
256
+
257
+ **YouTube workflow focus.** Built for content creators who code.
258
+
259
+ **Language-agnostic.** Currently Ruby, but could be rewritten if needed.
260
+
261
+ [Read the full philosophy →](./docs/purpose-and-philosophy.md)
106
262
 
107
- `appydave-tools` is setup with Guard, run `guard`, this will watch development file changes and run tests automatically, if successful, it will then run rubocop for style quality.
263
+ ---
108
264
 
109
- To release a new version, update the version number in `version.rb`, build the gem and push the `.gem` file to [rubygems.org](https://rubygems.org).
265
+ ## Development
110
266
 
111
267
  ```bash
112
- rake publish
113
- rake clean
268
+ # Clone the repo
269
+ git clone https://github.com/appydave/appydave-tools
270
+
271
+ # Setup
272
+ bin/setup
273
+
274
+ # Run tests
275
+ rake spec
276
+
277
+ # Auto-run tests on file changes
278
+ guard
279
+
280
+ # Interactive console
281
+ bin/console
114
282
  ```
115
283
 
116
- ## Git helpers used by this project
284
+ ### Semantic Versioning
117
285
 
118
- Add the follow helpers to your `alias` file
286
+ This project uses **automated versioning** via semantic-release. Don't manually edit version files.
119
287
 
288
+ **Commit message format:**
120
289
  ```bash
121
- function kcommit()
122
- {
123
- echo 'git add .'
124
- git add .
125
- echo "git commit -m "$1""
126
- git commit -m "$1"
127
- echo 'git pull'
128
- git pull
129
- echo 'git push'
130
- git push
131
- sleep 3
132
- run_id="$(gh run list --limit 1 | grep -Eo "[0-9]{9,11}")"
133
- gh run watch $run_id --exit-status && echo "run completed and successful" && git pull && git tag | sort -V | tail -1
134
- }
135
- function kchore () { kcommit "chore: $1" }
136
- function kdocs () { kcommit "docs: $1" }
137
- function kfix () { kcommit "fix: $1" }
138
- function kfeat () { kcommit "feat: $1" }
139
- function ktest () { kcommit "test: $1" }
140
- function krefactor () { kcommit "refactor: $1" }
290
+ feat: add new feature # Minor version bump
291
+ fix: bug fix # Patch version bump
292
+ chore: maintenance # No version bump
293
+
294
+ # Breaking changes
295
+ feat!: breaking change
141
296
  ```
142
297
 
298
+ CI/CD automatically handles versioning, changelog, and RubyGems publishing.
299
+
300
+ ---
301
+
143
302
  ## Contributing
144
303
 
145
- Bug reports and pull requests are welcome on GitHub at https://github.com/appydave/appydave-tools. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
304
+ **Welcome:**
305
+ - 🐛 Bug fixes
306
+ - 📝 Documentation improvements
307
+ - ⚡ Performance enhancements
308
+ - 🎯 New single-purpose tools that fit the workflow
309
+
310
+ **Not looking for:**
311
+ - ❌ Framework-style architectures
312
+ - ❌ Tools that create dependencies between utilities
313
+ - ❌ Enterprise complexity
314
+
315
+ [Code of Conduct →](./CODE_OF_CONDUCT.md)
316
+
317
+ ---
146
318
 
147
319
  ## License
148
320
 
149
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
321
+ MIT License - Copyright (c) David Cruwys
322
+
323
+ See [LICENSE.txt](LICENSE.txt) for details.
150
324
 
151
- ## Code of Conduct
325
+ ---
152
326
 
153
- Everyone interacting in the Appydave Tools project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/appydave/appydave-tools/blob/master/CODE_OF_CONDUCT.md).
327
+ ## Connect
154
328
 
155
- ## Copyright
329
+ - 🌐 Website: [appydave.com](http://appydave.com)
330
+ - 📺 YouTube: [@AppyDave](https://youtube.com/@appydave)
331
+ - 🐙 GitHub: [appydave](https://github.com/appydave)
156
332
 
157
- Copyright (c) David Cruwys. See [MIT License](LICENSE.txt) for further details.
333
+ Built with by [David Cruwys](https://davidcruwys.com)
@@ -7,8 +7,8 @@ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
7
7
 
8
8
  require 'appydave/tools'
9
9
 
10
- # Process command line arguments for SubtitleMaster operations
11
- class SubtitleMasterCLI
10
+ # Process command line arguments for SubtitleProcessor operations
11
+ class SubtitleProcessorCLI
12
12
  def initialize
13
13
  @commands = {
14
14
  'clean' => method(:clean_subtitles),
@@ -39,7 +39,7 @@ class SubtitleMasterCLI
39
39
 
40
40
  # Command-specific option parser
41
41
  clean_parser = OptionParser.new do |opts|
42
- opts.banner = 'Usage: subtitle_manager.rb clean [options]'
42
+ opts.banner = 'Usage: subtitle_processor.rb clean [options]'
43
43
 
44
44
  opts.on('-f', '--file FILE', 'SRT file to process') do |v|
45
45
  options[:file] = v
@@ -70,8 +70,8 @@ class SubtitleMasterCLI
70
70
  exit
71
71
  end
72
72
 
73
- # Assuming `Appydave::Tools::SubtitleMaster::Clean` exists
74
- cleaner = Appydave::Tools::SubtitleMaster::Clean.new(file_path: options[:file])
73
+ # Assuming `Appydave::Tools::SubtitleProcessor::Clean` exists
74
+ cleaner = Appydave::Tools::SubtitleProcessor::Clean.new(file_path: options[:file])
75
75
  cleaner.clean
76
76
  cleaner.write(options[:output])
77
77
  end
@@ -87,7 +87,7 @@ class SubtitleMasterCLI
87
87
  }
88
88
 
89
89
  join_parser = OptionParser.new do |opts|
90
- opts.banner = 'Usage: subtitle_manager.rb join [options]'
90
+ opts.banner = 'Usage: subtitle_processor.rb join [options]'
91
91
 
92
92
  opts.on('-d', '--directory DIR', 'Directory containing SRT files (default: current directory)') do |v|
93
93
  options[:folder] = v
@@ -134,19 +134,25 @@ class SubtitleMasterCLI
134
134
  exit
135
135
  end
136
136
 
137
- # Assuming `Appydave::Tools::SubtitleMaster::Join` exists
138
- joiner = Appydave::Tools::SubtitleMaster::Join.new(folder: options[:folder], files: options[:files], sort: options[:sort], buffer: options[:buffer], output: options[:output],
139
- log_level: options[:log_level])
137
+ # Assuming `Appydave::Tools::SubtitleProcessor::Join` exists
138
+ joiner = Appydave::Tools::SubtitleProcessor::Join.new(
139
+ folder: options[:folder],
140
+ files: options[:files],
141
+ sort: options[:sort],
142
+ buffer: options[:buffer],
143
+ output: options[:output],
144
+ log_level: options[:log_level]
145
+ )
140
146
  joiner.join
141
147
  end
142
148
 
143
149
  def print_help
144
- puts 'Usage: subtitle_manager.rb [command] [options]'
150
+ puts 'Usage: subtitle_processor.rb [command] [options]'
145
151
  puts 'Commands:'
146
152
  puts ' clean Clean and normalize SRT files'
147
153
  puts ' join Join multiple SRT files'
148
- puts "Run 'subtitle_manager.rb [command] --help' for more information on a command."
154
+ puts "Run 'subtitle_processor.rb [command] --help' for more information on a command."
149
155
  end
150
156
  end
151
157
 
152
- SubtitleMasterCLI.new.run
158
+ SubtitleProcessorCLI.new.run
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'optparse'
5
+
6
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
7
+
8
+ require 'appydave/tools'
9
+
10
+ # Process command line arguments for SubtitleProcessor operations
11
+ class SubtitleProcessorCLI
12
+ def initialize
13
+ @commands = {
14
+ 'clean' => method(:clean_subtitles),
15
+ 'join' => method(:join_subtitles)
16
+ }
17
+ end
18
+
19
+ def run
20
+ command, *args = ARGV
21
+ if command.nil?
22
+ puts 'No command provided. Use -h for help.'
23
+ print_help
24
+ exit
25
+ end
26
+
27
+ if @commands.key?(command)
28
+ @commands[command].call(args)
29
+ else
30
+ puts "Unknown command: #{command}"
31
+ print_help
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def clean_subtitles(args)
38
+ options = { file: nil, output: nil }
39
+
40
+ # Command-specific option parser
41
+ clean_parser = OptionParser.new do |opts|
42
+ opts.banner = 'Usage: subtitle_processor.rb clean [options]'
43
+
44
+ opts.on('-f', '--file FILE', 'SRT file to process') do |v|
45
+ options[:file] = v
46
+ end
47
+
48
+ opts.on('-o', '--output FILE', 'Output file') do |v|
49
+ options[:output] = v
50
+ end
51
+
52
+ opts.on('-h', '--help', 'Show this message') do
53
+ puts opts
54
+ exit
55
+ end
56
+ end
57
+
58
+ begin
59
+ clean_parser.parse!(args)
60
+ rescue OptionParser::InvalidOption => e
61
+ puts "Error: #{e.message}"
62
+ puts clean_parser
63
+ exit
64
+ end
65
+
66
+ # Validate required options
67
+ if options[:file].nil? || options[:output].nil?
68
+ puts 'Error: Missing required options.'
69
+ puts clean_parser
70
+ exit
71
+ end
72
+
73
+ # Assuming `Appydave::Tools::SubtitleProcessor::Clean` exists
74
+ cleaner = Appydave::Tools::SubtitleProcessor::Clean.new(file_path: options[:file])
75
+ cleaner.clean
76
+ cleaner.write(options[:output])
77
+ end
78
+
79
+ def join_subtitles(args)
80
+ options = {
81
+ folder: './',
82
+ files: '*.srt',
83
+ sort: 'inferred',
84
+ buffer: 100,
85
+ output: 'merged.srt',
86
+ verbose: false
87
+ }
88
+
89
+ join_parser = OptionParser.new do |opts|
90
+ opts.banner = 'Usage: subtitle_processor.rb join [options]'
91
+
92
+ opts.on('-d', '--directory DIR', 'Directory containing SRT files (default: current directory)') do |v|
93
+ options[:folder] = v
94
+ end
95
+
96
+ opts.on('-f', '--files PATTERN', 'File pattern (e.g., "*.srt" or "part1.srt,part2.srt")') do |v|
97
+ options[:files] = v
98
+ end
99
+
100
+ opts.on('-s', '--sort ORDER', %w[asc desc inferred], 'Sort order (asc/desc/inferred)') do |v|
101
+ options[:sort] = v
102
+ end
103
+
104
+ opts.on('-b', '--buffer MS', Integer, 'Buffer between merged files in milliseconds') do |v|
105
+ options[:buffer] = v
106
+ end
107
+
108
+ opts.on('-o', '--output FILE', 'Output file') do |v|
109
+ options[:output] = v
110
+ end
111
+
112
+ opts.on('-L', '--log-level LEVEL', %w[none info detail], 'Log level (default: info)') do |v|
113
+ options[:log_level] = v.to_sym
114
+ end
115
+
116
+ opts.on('-h', '--help', 'Show this message') do
117
+ puts opts
118
+ exit
119
+ end
120
+ end
121
+
122
+ begin
123
+ join_parser.parse!(args)
124
+ rescue OptionParser::InvalidOption => e
125
+ puts "Error: #{e.message}"
126
+ puts join_parser
127
+ exit
128
+ end
129
+
130
+ # Validate required options
131
+ if options[:folder].nil? || options[:files].nil? || options[:output].nil?
132
+ puts 'Error: Missing required options.'
133
+ puts join_parser
134
+ exit
135
+ end
136
+
137
+ # Assuming `Appydave::Tools::SubtitleProcessor::Join` exists
138
+ joiner = Appydave::Tools::SubtitleProcessor::Join.new(
139
+ folder: options[:folder],
140
+ files: options[:files],
141
+ sort: options[:sort],
142
+ buffer: options[:buffer],
143
+ output: options[:output],
144
+ log_level: options[:log_level]
145
+ )
146
+ joiner.join
147
+ end
148
+
149
+ def print_help
150
+ puts 'Usage: subtitle_processor.rb [command] [options]'
151
+ puts 'Commands:'
152
+ puts ' clean Clean and normalize SRT files'
153
+ puts ' join Join multiple SRT files'
154
+ puts "Run 'subtitle_processor.rb [command] --help' for more information on a command."
155
+ end
156
+ end
157
+
158
+ SubtitleProcessorCLI.new.run