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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/CLAUDE.md +537 -28
- data/README.md +262 -86
- data/bin/subtitle_manager.rb +18 -12
- data/bin/subtitle_processor.rb +158 -0
- data/docs/archive/codebase-audit-2025-01.md +424 -0
- data/docs/archive/documentation-framework-proposal.md +808 -0
- data/docs/archive/purpose-and-philosophy.md +110 -0
- data/docs/archive/test-coverage-quick-wins.md +342 -0
- data/docs/archive/tool-discovery.md +199 -0
- data/docs/archive/tool-documentation-analysis.md +592 -0
- data/docs/tools/bank-reconciliation.md +269 -0
- data/docs/tools/cli-actions.md +444 -0
- data/docs/tools/configuration.md +329 -0
- data/docs/{usage → tools}/gpt-context.md +118 -7
- data/docs/tools/index.md +324 -0
- data/docs/tools/move-images.md +295 -0
- data/docs/tools/name-manager.md +322 -0
- data/docs/tools/prompt-tools.md +209 -0
- data/docs/tools/subtitle-processor.md +242 -0
- data/docs/tools/youtube-automation.md +258 -0
- data/docs/tools/youtube-manager.md +248 -0
- data/exe/ad_config +6 -0
- data/exe/gpt_context +6 -0
- data/exe/prompt_tools +6 -0
- data/exe/subtitle_manager +6 -0
- data/exe/youtube_automation +6 -0
- data/exe/youtube_manager +6 -0
- data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/clean.rb +1 -1
- data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/join.rb +5 -2
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools.rb +2 -4
- data/package.json +1 -1
- metadata +43 -14
- data/lib/mj-paste-test/main.rb +0 -35
- data/lib/mj-paste-test/prompts.txt +0 -18
- data/lib/mj-paste-test/readme-leonardo.md +0 -0
- /data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/_doc-clean.md +0 -0
- /data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/_doc-join.md +0 -0
- /data/lib/appydave/tools/{subtitle_manager → subtitle_processor}/_doc-todo.md +0 -0
data/README.md
CHANGED
|
@@ -1,157 +1,333 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AppyDave Tools
|
|
2
2
|
|
|
3
|
-
> AppyDave YouTube
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
23
|
-
|
|
62
|
+
# Get video details (title, description, tags, category, captions)
|
|
63
|
+
youtube_manager get --video-id YOUR_VIDEO_ID
|
|
24
64
|
|
|
25
|
-
|
|
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
|
-
|
|
70
|
+
# Update tags (replaces existing tags)
|
|
71
|
+
youtube_manager update --video-id YOUR_VIDEO_ID --tags "tutorial,productivity,automation"
|
|
28
72
|
|
|
29
|
-
|
|
73
|
+
# Update category
|
|
74
|
+
youtube_manager update --video-id YOUR_VIDEO_ID --category-id 28
|
|
75
|
+
```
|
|
30
76
|
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
98
|
+
---
|
|
37
99
|
|
|
38
|
-
|
|
100
|
+
### 📝 Subtitle Processor
|
|
39
101
|
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
48
|
-
|
|
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
|
-
#
|
|
51
|
-
|
|
110
|
+
# Merge multiple subtitle files with timeline synchronization
|
|
111
|
+
subtitle_processor join -d ./parts -f "*.srt" -o final.srt
|
|
52
112
|
|
|
53
|
-
#
|
|
54
|
-
|
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
71
|
-
|
|
167
|
+
# Run automation sequence (requires configuration)
|
|
168
|
+
youtube_automation -s 01-1
|
|
72
169
|
|
|
73
|
-
#
|
|
74
|
-
|
|
170
|
+
# With debug output
|
|
171
|
+
youtube_automation -s 01-1 -d
|
|
75
172
|
```
|
|
76
173
|
|
|
77
|
-
|
|
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
|
-
#
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
247
|
+
**Use cases:** B-roll organization, thumbnail preparation.
|
|
93
248
|
|
|
94
|
-
|
|
249
|
+
---
|
|
95
250
|
|
|
96
|
-
|
|
97
|
-
bin/console
|
|
251
|
+
## Philosophy
|
|
98
252
|
|
|
99
|
-
|
|
100
|
-
# => "0.14.0"
|
|
253
|
+
**One codebase, multiple tools.** Easier to maintain than dozens of repos.
|
|
101
254
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
263
|
+
---
|
|
108
264
|
|
|
109
|
-
|
|
265
|
+
## Development
|
|
110
266
|
|
|
111
267
|
```bash
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
284
|
+
### Semantic Versioning
|
|
117
285
|
|
|
118
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
-
|
|
321
|
+
MIT License - Copyright (c) David Cruwys
|
|
322
|
+
|
|
323
|
+
See [LICENSE.txt](LICENSE.txt) for details.
|
|
150
324
|
|
|
151
|
-
|
|
325
|
+
---
|
|
152
326
|
|
|
153
|
-
|
|
327
|
+
## Connect
|
|
154
328
|
|
|
155
|
-
|
|
329
|
+
- 🌐 Website: [appydave.com](http://appydave.com)
|
|
330
|
+
- 📺 YouTube: [@AppyDave](https://youtube.com/@appydave)
|
|
331
|
+
- 🐙 GitHub: [appydave](https://github.com/appydave)
|
|
156
332
|
|
|
157
|
-
|
|
333
|
+
Built with ☕ by [David Cruwys](https://davidcruwys.com)
|
data/bin/subtitle_manager.rb
CHANGED
|
@@ -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
|
|
11
|
-
class
|
|
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:
|
|
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::
|
|
74
|
-
cleaner = Appydave::Tools::
|
|
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:
|
|
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::
|
|
138
|
-
joiner = Appydave::Tools::
|
|
139
|
-
|
|
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:
|
|
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 '
|
|
154
|
+
puts "Run 'subtitle_processor.rb [command] --help' for more information on a command."
|
|
149
155
|
end
|
|
150
156
|
end
|
|
151
157
|
|
|
152
|
-
|
|
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
|