From ebe1ccf9cdfbfe8125f4597f99072e06d6c06039 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 4 Dec 2024 15:12:22 -0800 Subject: [PATCH] Claude built a Claude interface for me --- chan.dev/package.json | 3 +- chan.dev/pnpm-lock.yaml | 151 ++++++++++++++++++ chan.dev/src/env.d.ts | 12 ++ chan.dev/src/middleware.ts | 3 +- .../src/pages/api/generate-youtube-content.ts | 91 +++++++++++ chan.dev/src/pages/dashboard/index.astro | 3 + .../src/pages/dashboard/metadata/new.astro | 132 +++++++++++++++ 7 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 chan.dev/src/pages/api/generate-youtube-content.ts create mode 100644 chan.dev/src/pages/dashboard/metadata/new.astro diff --git a/chan.dev/package.json b/chan.dev/package.json index e204438b..3a540406 100644 --- a/chan.dev/package.json +++ b/chan.dev/package.json @@ -64,7 +64,8 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "sharp": "0.33.4", - "shiki-magic-move": "^0.5.0" + "shiki-magic-move": "^0.5.0", + "@anthropic-ai/sdk": "^0.17.1" }, "engine": { "node": ">=20.0.0" diff --git a/chan.dev/pnpm-lock.yaml b/chan.dev/pnpm-lock.yaml index aa2847a7..bd23a6dd 100644 --- a/chan.dev/pnpm-lock.yaml +++ b/chan.dev/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@anthropic-ai/sdk': + specifier: ^0.17.1 + version: 0.17.2(encoding@0.1.13) '@astrojs/cloudflare': specifier: ^9.2.1 version: 9.2.1(astro@4.12.3(@types/node@22.0.0)(typescript@5.5.4)) @@ -161,6 +164,9 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@anthropic-ai/sdk@0.17.2': + resolution: {integrity: sha512-xDfL/OblarYcwTSN2xBhynXJTkaTaxr8/v1fRKdT3grOZ4TrzIdrFfaTM771proR4g3uLe76PFSF3+gPjI6Gpw==} + '@astrojs/cloudflare@9.2.1': resolution: {integrity: sha512-IPsfuqy3r0OR0CvCdQw72J0iC4dhOW4WXByi2s3vAE3py8RQQtiyJXY8a4rAT/LRUz7WVlpzkm7FxORtmIeKVw==} peerDependencies: @@ -1436,6 +1442,9 @@ packages: '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + '@types/node@18.19.67': + resolution: {integrity: sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==} + '@types/node@22.0.0': resolution: {integrity: sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==} @@ -1500,6 +1509,10 @@ packages: resolution: {integrity: sha512-ey5/hn93ZMXer+Q9sjl03/ukVDKir6U3EDLPqUQwoc8bnMD1lT2w8fOoNUnUT+L1gr0+h3AMg6PHuHLz+XsUSg==} engines: {node: '>=16'} + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + acorn-walk@8.3.3: resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} engines: {node: '>=0.4.0'} @@ -1513,6 +1526,10 @@ packages: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} + agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -1603,6 +1620,9 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base-64@0.1.0: + resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} + base-64@1.0.0: resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} @@ -1689,6 +1709,9 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -1809,6 +1832,9 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + css-selector-parser@3.0.5: resolution: {integrity: sha512-3itoDFbKUNx1eKmVpYMFyqKX04Ww9osZ+dLgrk6GEv6KMVeXUhUnp4I5X+evw+u3ZxVU6RFXSSRxlTeMh8bA+g==} @@ -1900,6 +1926,9 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + digest-fetch@1.3.0: + resolution: {integrity: sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==} + direction@2.0.1: resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} hasBin: true @@ -2092,6 +2121,10 @@ packages: estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} @@ -2155,10 +2188,17 @@ packages: resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} engines: {node: '>=14'} + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} @@ -2313,6 +2353,9 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2376,6 +2419,9 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + is-buffer@2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} @@ -2586,6 +2632,9 @@ packages: markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + mdast-util-definitions@5.1.2: resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} @@ -2932,6 +2981,15 @@ packages: node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + node-fetch@3.3.2: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3576,6 +3634,9 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -3619,6 +3680,9 @@ packages: uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.11.1: resolution: {integrity: sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==} @@ -3754,9 +3818,19 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + webcrypto-core@1.8.0: resolution: {integrity: sha512-kR1UQNH8MD42CYuLzvibfakG5Ew5seG85dMMoAM/1LqvckxaF6pUiidLuraIu4V+YCIFabYecUZAW0TuxAoaqw==} + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-pm-runs@1.1.0: resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} engines: {node: '>=4'} @@ -3859,6 +3933,20 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + '@anthropic-ai/sdk@0.17.2(encoding@0.1.13)': + dependencies: + '@types/node': 18.19.67 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + digest-fetch: 1.3.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0(encoding@0.1.13) + web-streams-polyfill: 3.3.3 + transitivePeerDependencies: + - encoding + '@astrojs/cloudflare@9.2.1(astro@4.12.3(@types/node@22.0.0)(typescript@5.5.4))': dependencies: '@astrojs/underscore-redirects': 0.3.4 @@ -4964,6 +5052,10 @@ snapshots: '@types/node@17.0.45': {} + '@types/node@18.19.67': + dependencies: + undici-types: 5.26.5 + '@types/node@22.0.0': dependencies: undici-types: 6.11.1 @@ -5048,6 +5140,10 @@ snapshots: - koa - next + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + acorn-walk@8.3.3: dependencies: acorn: 8.12.1 @@ -5060,6 +5156,10 @@ snapshots: transitivePeerDependencies: - supports-color + agentkeepalive@4.5.0: + dependencies: + humanize-ms: 1.2.1 + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 @@ -5216,6 +5316,8 @@ snapshots: balanced-match@1.0.2: {} + base-64@0.1.0: {} + base-64@1.0.0: {} base64-js@1.5.1: {} @@ -5311,6 +5413,8 @@ snapshots: character-reference-invalid@2.0.1: {} + charenc@0.0.2: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -5402,6 +5506,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypt@0.0.2: {} + css-selector-parser@3.0.5: {} cssesc@3.0.0: {} @@ -5461,6 +5567,11 @@ snapshots: diff@5.2.0: {} + digest-fetch@1.3.0: + dependencies: + base-64: 0.1.0 + md5: 2.3.0 + direction@2.0.1: {} dlv@1.1.3: {} @@ -5637,6 +5748,8 @@ snapshots: dependencies: '@types/estree': 1.0.5 + event-target-shim@5.0.1: {} + eventemitter3@5.0.1: {} execa@8.0.1: @@ -5715,12 +5828,19 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + form-data-encoder@1.7.2: {} + form-data@4.0.0: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + formdata-polyfill@4.0.10: dependencies: fetch-blob: 3.2.0 @@ -5951,6 +6071,10 @@ snapshots: human-signals@5.0.0: {} + humanize-ms@1.2.1: + dependencies: + ms: 2.1.2 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -6006,6 +6130,8 @@ snapshots: dependencies: binary-extensions: 2.3.0 + is-buffer@1.1.6: {} + is-buffer@2.0.5: {} is-core-module@2.15.0: @@ -6192,6 +6318,12 @@ snapshots: markdown-table@3.0.3: {} + md5@2.3.0: + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + mdast-util-definitions@5.1.2: dependencies: '@types/mdast': 3.0.15 @@ -6847,6 +6979,12 @@ snapshots: node-fetch-native@1.6.4: {} + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + node-fetch@3.3.2: dependencies: data-uri-to-buffer: 4.0.1 @@ -7608,6 +7746,8 @@ snapshots: dependencies: is-number: 7.0.0 + tr46@0.0.3: {} + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -7632,6 +7772,8 @@ snapshots: uncrypto@0.1.3: {} + undici-types@5.26.5: {} + undici-types@6.11.1: {} undici@5.28.4: @@ -7796,6 +7938,8 @@ snapshots: web-streams-polyfill@3.3.3: {} + web-streams-polyfill@4.0.0-beta.3: {} + webcrypto-core@1.8.0: dependencies: '@peculiar/asn1-schema': 2.3.8 @@ -7804,6 +7948,13 @@ snapshots: pvtsutils: 1.3.5 tslib: 2.6.3 + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which-pm-runs@1.1.0: {} which-pm@3.0.0: diff --git a/chan.dev/src/env.d.ts b/chan.dev/src/env.d.ts index c1162c89..c1e2d7bd 100644 --- a/chan.dev/src/env.d.ts +++ b/chan.dev/src/env.d.ts @@ -12,3 +12,15 @@ declare global { } } } + +interface ImportMetaEnv { + readonly WORKOS_API_KEY: string + readonly WORKOS_CLIENT_ID: string + readonly WORKOS_REDIRECT_URI?: string + readonly WORKOS_COOKIE_PASSWORD: string + readonly ANTHROPIC_API_KEY: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/chan.dev/src/middleware.ts b/chan.dev/src/middleware.ts index 76aaef16..4b038bfa 100644 --- a/chan.dev/src/middleware.ts +++ b/chan.dev/src/middleware.ts @@ -1,12 +1,11 @@ import type {APIContext, MiddlewareNext} from 'astro' import {defineMiddleware} from 'astro/middleware' import * as AUTHKIT from '#lib/authkit' -import {minimatch} from 'minimatch' export const onRequest = defineMiddleware((context, next) => { const {pathname} = new URL(context.request.url) - if (minimatch(pathname, '/dashboard*')) { + if (pathname.startsWith('/dashboard')) { return withAuth(context, next) } diff --git a/chan.dev/src/pages/api/generate-youtube-content.ts b/chan.dev/src/pages/api/generate-youtube-content.ts new file mode 100644 index 00000000..fec8af52 --- /dev/null +++ b/chan.dev/src/pages/api/generate-youtube-content.ts @@ -0,0 +1,91 @@ +export const prerender = false + +import type { APIRoute } from 'astro'; +import { authenticateWithSessionCookie, COOKIE_NAME } from '../../lib/authkit'; +import Anthropic from '@anthropic-ai/sdk'; + +export const POST: APIRoute = async ({ request, cookies }) => { + // Auth check + const cookie = cookies.get(COOKIE_NAME); + if (!cookie) { + return new Response(JSON.stringify({ message: 'Unauthorized' }), { status: 401 }); + } + + try { + await authenticateWithSessionCookie({ value: cookie.value }); + } catch { + return new Response(JSON.stringify({ message: 'Unauthorized' }), { status: 401 }); + } + + try { + const formData = await request.formData(); + const srtFile = formData.get('srtFile') as File; + const prompt = formData.get('prompt') as string; + + if (!srtFile) { + return new Response( + JSON.stringify({ message: 'No SRT file provided' }), + { status: 400 } + ); + } + + // Read the SRT file content + const srtContent = await srtFile.text(); + + // Initialize Anthropic client + const anthropic = new Anthropic({ + apiKey: import.meta.env.ANTHROPIC_API_KEY, + }); + + // Prepare the prompt for Claude + const systemPrompt = `You are a YouTube content optimization expert. Based on the provided SRT file and context, generate: +1. 5 viral title ideas +2. An engaging description with keywords +3. Chapter markers based on the SRT timestamps +4. Relevant tags for maximum discoverability + +SRT Content: +${srtContent} + +Additional Context: +${prompt} + +Please format your response as JSON with the following structure: +{ + "titles": ["title1", "title2", ...], + "description": "full description", + "chapters": "00:00 Introduction\\n05:23 Next Chapter\\n...", + "tags": ["tag1", "tag2", ...] +}`; + + const response = await anthropic.messages.create({ + model: 'claude-3-sonnet-20240229', + max_tokens: 4000, + temperature: 0.7, + system: systemPrompt, + messages: [ + { + role: 'user', + content: 'Please analyze the content and provide the YouTube optimization details.', + }, + ], + }); + + // Parse Claude's response + const content = response.content[0].text; + const result = JSON.parse(content); + + return new Response(JSON.stringify(result), { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + }); + } catch (error) { + console.error('Error:', error); + return new Response( + JSON.stringify({ message: 'Failed to process request' }), + { status: 500 } + ); + } +}; \ No newline at end of file diff --git a/chan.dev/src/pages/dashboard/index.astro b/chan.dev/src/pages/dashboard/index.astro index 5b53104a..ab45cfa7 100644 --- a/chan.dev/src/pages/dashboard/index.astro +++ b/chan.dev/src/pages/dashboard/index.astro @@ -14,6 +14,9 @@ const {user} = Astro.locals Hello {user.firstName}! Create a habit + Create title and description diff --git a/chan.dev/src/pages/dashboard/metadata/new.astro b/chan.dev/src/pages/dashboard/metadata/new.astro new file mode 100644 index 00000000..f71deb70 --- /dev/null +++ b/chan.dev/src/pages/dashboard/metadata/new.astro @@ -0,0 +1,132 @@ +--- +export const prerender = false +import Layout from '#layouts/Layout.astro' +const {user} = Astro.locals +--- + + +
+

+ YouTube Content Helper +

+ +
+
+ + +
+ +
+ + +
+ + +
+ +
+ +
+
+
+ +