Add the edit-youtube-video script and tomlFrontmatter utility function.
This commit is contained in:
		
							parent
							
								
									b7d791c88a
								
							
						
					
					
						commit
						8f8d031f60
					
				|  | @ -0,0 +1,7 @@ | |||
| #!/usr/bin/env zsh | ||||
| 
 | ||||
| deno run \ | ||||
|   --allow-read \ | ||||
|   --allow-run="youtube3" \ | ||||
|   "$BAUKE_DIR/scripts/edit-youtube-video.ts" \ | ||||
|   "$@" | ||||
|  | @ -0,0 +1,86 @@ | |||
| import { Command } from "https://deno.land/x/cliffy@v0.25.5/command/mod.ts"; | ||||
| import { tomlFrontmatter } from "./utilities.ts"; | ||||
| 
 | ||||
| type Frontmatter = { | ||||
|   page_title: string; | ||||
|   id: string; | ||||
|   speedrun?: { | ||||
|     entry: string; | ||||
|     leaderboard: string; | ||||
|     chapters?: Array<[string, string]>; | ||||
|     mods?: string[]; | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| async function main(): Promise<void> { | ||||
|   const { options } = await new Command() | ||||
|     .name("edit-youtube-video") | ||||
|     .description("Edit a YouTube video title and description") | ||||
|     .option( | ||||
|       "--category-id <categoryId:number>", | ||||
|       "The categoryId of the video.", | ||||
|       { default: 20 }, | ||||
|     ) | ||||
|     .option("--description <description>", "The new description of the video.") | ||||
|     .option("--dry-run", "Do everything apart from calling the YouTube API.") | ||||
|     .option("--id <id>", "The ID of the video.") | ||||
|     .option( | ||||
|       "--markdown-file <file>", | ||||
|       "A Markdown file with TOML frontmatter.", | ||||
|       { | ||||
|         required: true, | ||||
|       }, | ||||
|     ) | ||||
|     .option("--title <title>", "The new title of the video.") | ||||
|     .parse(Deno.args); | ||||
| 
 | ||||
|   const frontmatter = tomlFrontmatter<Frontmatter>( | ||||
|     await Deno.readTextFile(options.markdownFile), | ||||
|   )[0]; | ||||
| 
 | ||||
|   const categoryId = options.categoryId; | ||||
|   const description = formatDescription(frontmatter); | ||||
|   const title = options.title ?? frontmatter.page_title; | ||||
|   const videoId = options.id ?? frontmatter.id; | ||||
| 
 | ||||
|   console.log({ categoryId, title, videoId }); | ||||
|   console.log(description); | ||||
|   if (options.dryRun) { | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   await Deno.run({ | ||||
|     cmd: [ | ||||
|       "youtube3", | ||||
|       "videos", | ||||
|       "update", | ||||
|       "-r", | ||||
|       `id=${videoId}`, | ||||
|       "-r", | ||||
|       `snippet.category-id=${categoryId}`, | ||||
|       "-r", | ||||
|       `snippet.description=${description}`, | ||||
|       "-r", | ||||
|       `snippet.title=${title}`, | ||||
|     ], | ||||
|   }).status(); | ||||
| } | ||||
| 
 | ||||
| function formatDescription(frontmatter: Frontmatter): string { | ||||
|   let description = "See all details on my website\n"; | ||||
|   description += `https://bauke.xyz/v/${frontmatter.id}/\n`; | ||||
| 
 | ||||
|   const chapters = frontmatter.speedrun?.chapters ?? []; | ||||
|   if (chapters.length > 0) { | ||||
|     description += `\nChapters\n`; | ||||
|     for (const [timestamp, text] of chapters) { | ||||
|       description += `${timestamp} ${text}\n`; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return description; | ||||
| } | ||||
| 
 | ||||
| if (import.meta.main) { | ||||
|   void main(); | ||||
| } | ||||
|  | @ -1,3 +1,4 @@ | |||
| import { parse } from "https://deno.land/std@0.167.0/encoding/toml.ts"; | ||||
| import { TextDecoder } from "https://deno.land/std@0.167.0/node/util.ts"; | ||||
| 
 | ||||
| export async function runAndReturnStdout( | ||||
|  | @ -6,3 +7,28 @@ export async function runAndReturnStdout( | |||
|   const process = Deno.run({ stdout: "piped", ...options }); | ||||
|   return new TextDecoder().decode(await process.output()); | ||||
| } | ||||
| 
 | ||||
| export function tomlFrontmatter<T>( | ||||
|   data: string, | ||||
| ): [T, string] { | ||||
|   const startMarker = "---toml\n"; | ||||
|   const endMarker = "\n---\n"; | ||||
| 
 | ||||
|   let start = data.indexOf(startMarker); | ||||
|   let end = data.indexOf(endMarker); | ||||
| 
 | ||||
|   if (start === -1 || end === -1) { | ||||
|     throw new Error("Missing frontmatter"); | ||||
|   } | ||||
| 
 | ||||
|   if (start !== 0) { | ||||
|     throw new Error("Frontmatter not at beginning of data"); | ||||
|   } | ||||
| 
 | ||||
|   start += startMarker.length; | ||||
|   const frontmatter = data.slice(start, end); | ||||
| 
 | ||||
|   end += endMarker.length; | ||||
|   const extra = data.slice(end); | ||||
|   return [parse(frontmatter) as T, extra.trimStart()]; | ||||
| } | ||||
|  |  | |||
		Reference in New Issue