Compare commits

..

195 commits

Author SHA1 Message Date
0d0
b43ee05ecf 1.0.0-c
All checks were successful
Create Release / create-release (push) Successful in 30s
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-04-19 18:50:59 +02:00
0d0
57d2adbdbc remove useless log
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 30s
2025-04-19 18:50:31 +02:00
0d0
716ebe9ecd just log everything sadly 2025-04-19 18:50:10 +02:00
0d0
e3c0c7d1f9 1.0.0-b
All checks were successful
Create Release / create-release (push) Successful in 32s
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-04-19 18:21:33 +02:00
0d0
d43db45617 Update env file creation
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 29s
2025-04-19 18:20:23 +02:00
0d0
67e521b7b4 update
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-04-19 18:18:45 +02:00
0d0
3dc834daf0 1.0.0
All checks were successful
Create Release / create-release (push) Successful in 36s
Bump deps (only minor versions) / ci (push) Successful in 26s
2025-04-19 17:58:43 +02:00
0d0
5bcbfc70ec Update download method
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-04-19 17:58:24 +02:00
0d0
08578eef0b Update download method 2025-04-19 17:58:13 +02:00
0d0
e82c027ad9 trailing lf
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 34s
2025-04-19 16:35:13 +02:00
0d0
4303614237 new layout 2025-04-19 16:34:55 +02:00
0d0
4bf9d97345 remove unused cookie 2025-04-19 16:31:24 +02:00
0d0
99263fd14c fix comment 2025-04-19 16:31:24 +02:00
forgejo-bot
691e294546 chore: update minor dependencies 2025-04-18 23:00:25 +00:00
forgejo-bot
885c802da6 chore: update minor dependencies 2025-04-17 23:00:58 +00:00
forgejo-bot
6d0d7ccecc chore: update minor dependencies 2025-04-16 23:00:47 +00:00
forgejo-bot
ff5cef233d chore: update minor dependencies 2025-04-15 23:00:57 +00:00
forgejo-bot
2b81cb2fa5 chore: update minor dependencies 2025-04-14 23:01:16 +00:00
forgejo-bot
9ffcd5f596 chore: update minor dependencies 2025-04-13 23:18:23 +00:00
forgejo-bot
1bd6d90814 chore: update minor dependencies 2025-04-12 23:01:12 +00:00
forgejo-bot
c46189ff83 chore: update minor dependencies 2025-04-11 23:01:16 +00:00
forgejo-bot
c416918a1a chore: update minor dependencies 2025-04-10 23:01:11 +00:00
forgejo-bot
7a3bf1fb45 chore: update minor dependencies 2025-04-09 23:01:13 +00:00
forgejo-bot
cd8a4c4d69 chore: update minor dependencies 2025-04-08 23:01:09 +00:00
0d0
9c7f7eace1 maybe its better like this
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 23s
2025-04-08 21:34:12 +02:00
0d0
5066c3ba7a better css 2025-04-08 21:31:34 +02:00
0d0
a833c43713 change tmp name 2025-04-08 21:18:48 +02:00
0d0
a18fbb8614 0.9.3-c
All checks were successful
Create Release / create-release (push) Successful in 32s
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-04-08 20:33:08 +02:00
forgejo-bot
bb233f7cb8 chore: update minor dependencies 2025-04-07 23:01:13 +00:00
forgejo-bot
2f502b2530 chore: update minor dependencies 2025-04-05 23:00:17 +00:00
forgejo-bot
c32cc4d3e7 chore: update minor dependencies 2025-04-04 23:00:53 +00:00
forgejo-bot
5fc6b0700a chore: update minor dependencies 2025-04-03 23:00:53 +00:00
forgejo-bot
b94d5ffc19 chore: update minor dependencies 2025-04-02 23:01:04 +00:00
forgejo-bot
267da475a6 chore: update minor dependencies 2025-04-01 23:01:09 +00:00
forgejo-bot
82aac1d3b9 chore: update minor dependencies 2025-03-31 23:01:13 +00:00
odo
56ef54b119 Aggiorna README.md
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 28s
2025-03-31 08:31:50 +00:00
forgejo-bot
d21d4d57a9 chore: update minor dependencies 2025-03-29 23:00:51 +00:00
0d0
214619ec3f 0.9.3-b
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-03-29 17:18:07 +01:00
forgejo-bot
18adf9a6a3 chore: update minor dependencies 2025-03-28 23:00:51 +00:00
forgejo-bot
66196979cc chore: update minor dependencies 2025-03-27 23:00:54 +00:00
forgejo-bot
4d0eaed688 chore: update minor dependencies 2025-03-26 23:00:41 +00:00
forgejo-bot
6003e59aaa chore: update minor dependencies 2025-03-25 23:00:44 +00:00
forgejo-bot
99ae01f895 chore: update minor dependencies 2025-03-24 23:00:45 +00:00
forgejo-bot
9f8b49515e chore: update minor dependencies 2025-03-23 23:00:39 +00:00
forgejo-bot
c7d65ee49a chore: update minor dependencies 2025-03-22 23:00:42 +00:00
forgejo-bot
84feab36dc chore: update minor dependencies 2025-03-21 23:00:46 +00:00
forgejo-bot
728db51c59 chore: update minor dependencies 2025-03-20 23:00:47 +00:00
forgejo-bot
c3072322d1 chore: update minor dependencies 2025-03-18 23:00:43 +00:00
forgejo-bot
565612cf30 chore: update minor dependencies 2025-03-17 23:00:46 +00:00
0d0
77d1d7331d 0.9.3
All checks were successful
Create Release / create-release (push) Successful in 30s
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-03-16 21:35:06 +01:00
0d0
ebf597fea6 Bump deps 2025-03-16 21:33:34 +01:00
forgejo-bot
7dc90c4c27 chore: update minor dependencies 2025-03-15 23:00:23 +00:00
forgejo-bot
96d59113bc chore: update minor dependencies 2025-03-14 23:00:29 +00:00
forgejo-bot
e0fbca1e6d chore: update minor dependencies 2025-03-13 23:01:04 +00:00
0d0
2899def330 0.9.2
All checks were successful
Create Release / create-release (push) Successful in 32s
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-03-12 19:50:21 +01:00
forgejo-bot
e4dffe691c chore: update minor dependencies 2025-03-12 18:35:39 +00:00
forgejo-bot
c55524221a chore: update minor dependencies 2025-03-03 23:00:42 +00:00
forgejo-bot
1f5a6613d0 chore: update minor dependencies 2025-02-28 23:00:48 +00:00
0d0
a4bec2cb38 Put correct mime-type
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-28 07:47:53 +01:00
forgejo-bot
f080ccc912 chore: update minor dependencies 2025-02-27 23:00:13 +00:00
forgejo-bot
8e37875442 chore: update minor dependencies 2025-02-26 23:00:16 +00:00
0d0
af9c2084eb 0.9.1
All checks were successful
Create Release / create-release (push) Successful in 54s
Bump deps (only minor versions) / ci (push) Successful in 33s
2025-02-26 16:52:55 +01:00
0d0
13ba9fd1a1 Ops fix wording
Some checks failed
Bump deps (only minor versions) / ci (push) Has been cancelled
2025-02-26 16:52:43 +01:00
0d0
3888d9d481 0.9.0
All checks were successful
Create Release / create-release (push) Successful in 37s
Bump deps (only minor versions) / ci (push) Successful in 38s
2025-02-26 16:19:04 +01:00
0d0
5ff4dc73de Update install script to accept proxy
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 37s
2025-02-26 16:18:52 +01:00
0d0
2f25ccf600 Lint and format
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 34s
2025-02-26 16:11:16 +01:00
0d0
84d4379f16 Add support for proxies 2025-02-26 16:11:16 +01:00
forgejo-bot
9f4a2bc560 chore: update minor dependencies 2025-02-25 23:00:47 +00:00
0d0
e525eb8a41 add .dockerignore
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-25 17:56:11 +01:00
0d0
5b278b75c0 Write only error logs on production
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 21s
2025-02-25 17:10:10 +01:00
0d0
652208aa57 it's cool that we have format
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-25 17:06:41 +01:00
0d0
760812c692 Update docs 2025-02-25 17:06:17 +01:00
0d0
3aaadc2b92 Remove the
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-25 16:56:25 +01:00
0d0
4aaaa4eedc Add better readme
Some checks failed
Bump deps (only minor versions) / ci (push) Has been cancelled
2025-02-25 16:56:07 +01:00
0d0
da528e3a81 Add better coloring
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-25 16:52:11 +01:00
0d0
cf3733530b Remove sse helpres
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-25 16:50:10 +01:00
0d0
1b76d4de4b Add type of request to logs 2025-02-25 16:50:03 +01:00
0d0
8224e620eb Add SSE Buffer Helper 2025-02-25 16:08:02 +01:00
0d0
c16790699c Update loader 2025-02-25 16:07:52 +01:00
0d0
25312ec595 Add sveltekit-sse
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-25 14:29:52 +01:00
0d0
24ff0a0738 Use winston and error management of stream controller
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-25 14:26:07 +01:00
0d0
0b58d9251e Add metadata if used 2025-02-25 14:25:40 +01:00
0d0
e4b1bcc677 Configure winston 2025-02-25 14:25:27 +01:00
0d0
f81083dec6 Add winston 2025-02-25 14:25:20 +01:00
0d0
942e6ed59a Add package-lock to deps check also
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-25 13:35:47 +01:00
0d0
a155cdf791 Update supported formats 2025-02-25 13:34:48 +01:00
0d0
aca6510197 wops deps
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
Create Release / create-release (push) Successful in 31s
2025-02-25 01:20:37 +01:00
0d0
af971bec5d 0.8.3
Some checks failed
Create Release / create-release (push) Failing after 20s
Bump deps (only minor versions) / ci (push) Successful in 24s
2025-02-25 01:19:11 +01:00
0d0
217a9b1028 change wording
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 22s
2025-02-25 01:17:35 +01:00
0d0
d1b80f2cc9 Add link to image
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 22s
2025-02-25 01:16:48 +01:00
0d0
89b2e4aaa2 Invert image and title
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 25s
2025-02-25 01:16:18 +01:00
0d0
697a8a73fe Remove ci from prepare check and lint action
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 23s
2025-02-25 01:15:35 +01:00
0d0
575fdc6386 Update readme
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 15s
2025-02-25 01:14:53 +01:00
0d0
1c893617dd OPS 2025-02-25 01:13:23 +01:00
0d0
90eaa0cbf1 Remove unused logs
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 14s
2025-02-25 01:06:44 +01:00
0d0
728d8f45cf Update default metadata and wording
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 13s
2025-02-25 01:02:01 +01:00
0d0
c8648b5cfe Fix font size of title
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 15s
2025-02-25 00:58:43 +01:00
0d0
3a5b705d5f Add excplict ssr,csr,prerender
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 14s
2025-02-25 00:57:02 +01:00
forgejo-bot
220244e26f chore: update minor dependencies 2025-02-24 23:00:38 +00:00
0d0
61e08c5bb9 0.8.2
All checks were successful
Create Release / create-release (push) Successful in 31s
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-24 20:14:22 +01:00
0d0
3be5e67018 Update manifest and logo
Some checks failed
Bump deps (only minor versions) / ci (push) Has been cancelled
2025-02-24 20:13:53 +01:00
0d0
e3e914882f update name
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-24 20:08:43 +01:00
0d0
b0ed4a7cc4 Do not use npm ci on deps check
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-24 20:07:51 +01:00
0d0
26a68fc102 Update readme
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-24 20:05:43 +01:00
0d0
4a12828571 Update screen
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-24 20:05:10 +01:00
0d0
bb548befc5 update README
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-24 19:59:55 +01:00
0d0
e9040bbf2b 0.8.1
All checks were successful
Create Release / create-release (push) Successful in 32s
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-24 19:45:28 +01:00
0d0
f2673d112b this should do it
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 26s
2025-02-24 19:43:11 +01:00
0d0
fa24bc435d YTDLP_PATH everywhere
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-23 07:55:42 +01:00
0d0
da95e2024f 0.8.0
All checks were successful
Create Release / create-release (push) Successful in 29s
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 06:37:43 +01:00
0d0
6f93574e8a Remove useless helper
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 21s
2025-02-23 06:37:13 +01:00
0d0
5d0fa4e951 update systemd unit file
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-23 06:18:50 +01:00
0d0
0d3b797ec8 Remove others
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 16s
2025-02-23 06:12:33 +01:00
0d0
284313259a 0.7.2
All checks were successful
Create Release / create-release (push) Successful in 29s
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 06:06:26 +01:00
0d0
b5cbef9de7 use path also on spawn
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 15s
2025-02-23 06:05:57 +01:00
0d0
109a668413 New deploy method
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 16s
2025-02-23 06:05:06 +01:00
0d0
631b9e44f0 update name
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-23 05:38:29 +01:00
0d0
99096f3d24 0.7.1
All checks were successful
Create Release / create-release (push) Successful in 27s
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-23 05:26:29 +01:00
0d0
6b8779f527 better code
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 16s
2025-02-23 05:22:37 +01:00
0d0
b16b84e5a3 0.7.0
All checks were successful
Create Release / create-release (push) Successful in 29s
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-23 05:10:22 +01:00
0d0
45b85fed1d Way better UI
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 16s
2025-02-23 05:09:56 +01:00
0d0
d523c4853f Update release pipeline names
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 04:59:09 +01:00
0d0
c7e99846b1 0.6.9
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
Create Release / create-release (push) Successful in 31s
2025-02-23 04:56:21 +01:00
0d0
4b9018ecbb Forgotten package lock
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 16s
2025-02-23 04:56:00 +01:00
0d0
dcb7cfec27 Add loader and new formats
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 11s
2025-02-23 04:55:09 +01:00
0d0
204bceeee3 Add +x to downloaded yt-dlp 2025-02-23 04:54:48 +01:00
0d0
151b5432cd Update globals 2025-02-23 02:35:00 +01:00
0d0
10d8ce8a15 fix dc
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-23 02:31:18 +01:00
forgejo-bot
79c3c820a4 chore: update minor dependencies 2025-02-23 01:23:58 +00:00
0d0
15cb677910 try
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-23 02:21:20 +01:00
0d0
6e86aa7f8c maybe
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-23 02:12:19 +01:00
0d0
7c9b80917f lol
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 02:11:40 +01:00
0d0
f20b9869cc should work
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-23 02:08:08 +01:00
0d0
11b0b9f6a2 test
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 02:04:53 +01:00
0d0
7213189744 test
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-23 02:03:40 +01:00
0d0
a5e3e310b7 test
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 02:03:07 +01:00
0d0
e06d04f387 every minute
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 18s
2025-02-23 02:01:54 +01:00
0d0
4c08c6ee4a 0.6.7
All checks were successful
Create Release / create-release (push) Successful in 30s
Bump deps (only minor versions) / ci (push) Successful in 16s
2025-02-23 01:55:42 +01:00
0d0
6924e8e082 new release pipeline
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 01:55:25 +01:00
0d0
87746bdcac We were using install instead of clean install
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 16s
2025-02-23 01:40:40 +01:00
0d0
b13e27d7e5 0.6.6
All checks were successful
Create Release / create-release (push) Successful in 30s
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 01:37:04 +01:00
0d0
64e3e21621 fix
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 17s
2025-02-23 01:36:52 +01:00
0d0
51b61f53c8 0.6.5
Some checks failed
Bump deps (only minor versions) / ci (push) Successful in 16s
Create Release / create-release (push) Failing after 25s
2025-02-23 01:35:28 +01:00
0d0
96e12b90f0 no need to prepare
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-23 01:34:16 +01:00
0d0
bf92e60d2b update release pipeline
Some checks failed
Bump deps (only minor versions) / ci (push) Has been cancelled
2025-02-23 01:32:53 +01:00
0d0
6a731be767 test
Some checks failed
Bump deps (only minor versions) / ci (push) Has been cancelled
2025-02-23 01:24:57 +01:00
0d0
48bd9a40e0 prepare does not need to be done here
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 23s
2025-02-23 01:22:27 +01:00
0d0
074320ba0e test ci
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 20s
2025-02-23 01:20:00 +01:00
0d0
5a3ca7d8a8 Add node types
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 31s
2025-02-23 01:00:01 +01:00
0d0
750050f8cc 0.6.2
Some checks failed
Create Release / create-release (push) Successful in 30s
Bump deps (only minor versions) / ci (push) Failing after 19s
2025-02-23 00:56:55 +01:00
0d0
966e8ae14c the migration is complete 2025-02-23 00:56:14 +01:00
0d0
5c8c68077c the migration is completed 2025-02-23 00:54:13 +01:00
0d0
771eb0429b the migration is completed 2025-02-23 00:53:57 +01:00
0d0
0fcf0562cb fmt
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-22 23:59:50 +01:00
0d0
0ecdd76aab update to tailwind4 2025-02-22 23:59:41 +01:00
0d0
7d1cc1d1d8 some lint and format
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 20s
2025-02-22 23:51:11 +01:00
0d0
7f8b192a99 bump deps
Some checks failed
Bump deps (only minor versions) / ci (push) Failing after 20s
2025-02-22 23:50:50 +01:00
0d0
dcad7b652d 0.6.0
All checks were successful
Create Release / create-release (push) Successful in 29s
Bump deps (only minor versions) / ci (push) Successful in 19s
2025-02-18 12:44:16 +01:00
0d0
69ceff6793 Remove container build from action
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-18 12:39:28 +01:00
0d0
2a866596ea 0.5.6
Some checks failed
Create Release / create-release (push) Successful in 30s
Create Release / build-container (push) Failing after 11s
Bump deps (only minor versions) / ci (push) Successful in 22s
2025-02-15 18:55:41 +01:00
0d0
d55b0abfd6 0.5.5
Some checks failed
Bump deps (only minor versions) / ci (push) Successful in 21s
Create Release / create-release (push) Successful in 28s
Create Release / build-container (push) Failing after 51s
2025-02-15 18:53:37 +01:00
0d0
28b169dbb7 Lint and format
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 24s
2025-02-15 18:51:40 +01:00
0d0
428c187618 Add container build action 2025-02-15 18:51:17 +01:00
0d0
62eb38601b fix sizd
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 21s
2025-02-15 00:50:59 +01:00
0d0
66e5e37690 Fix height
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-15 00:50:31 +01:00
0d0
bab94d8d8e fix quality
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 20s
2025-02-15 00:48:31 +01:00
0d0
95e5c3811f 0.5.2
All checks were successful
Bump deps (only minor versions) / ci (push) Successful in 23s
Create Release / create-release (push) Successful in 31s
2025-02-15 00:45:28 +01:00
0d0
b34240cf21 rename action ci 2025-02-15 00:37:24 +01:00
0d0
9aab1f1ca9 0.5.1
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 23s
Create Release / create-release (push) Successful in 29s
2025-02-15 00:36:36 +01:00
0d0
4948502487 Add .env
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 24s
2025-02-15 00:35:24 +01:00
0d0
0a92c120f4 add .env
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 21s
2025-02-15 00:30:38 +01:00
0d0
ccd4ccdcc4 Add env to readme and example
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 24s
2025-02-15 00:25:10 +01:00
0d0
7f423e378a Add deploy section
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 21s
2025-02-15 00:21:31 +01:00
0d0
f1bb8f6d50 rename folder
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 22s
2025-02-15 00:12:31 +01:00
0d0
6f1d01e624 Lint everything
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 22s
2025-02-14 21:42:56 +01:00
0d0
22a7dd13da pre commit is now executable 2025-02-14 21:42:06 +01:00
0d0
0055de6b47 Update readme 2025-02-14 21:41:14 +01:00
0d0
c76590a5ef Update readme
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 20s
2025-02-14 21:03:40 +01:00
0d0
3640d67b0a add status badge
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 21s
2025-02-14 20:58:16 +01:00
0d0
812f11bb5d fix readme
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 22s
2025-02-14 20:57:38 +01:00
0d0
0963d805a1 fix readme
Some checks failed
Bump deps (only minor versions) / update-dependencies (push) Has been cancelled
2025-02-14 20:57:22 +01:00
0d0
7399e1df7e add status badge
Some checks failed
Bump deps (only minor versions) / update-dependencies (push) Has been cancelled
2025-02-14 20:56:56 +01:00
0d0
626c8fb812 fix image
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 20s
2025-02-14 20:55:26 +01:00
0d0
85fdba1af4 Add version tag 2025-02-14 20:54:57 +01:00
0d0
09bc58d3b4 Add .env.example
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 19s
2025-02-14 20:44:43 +01:00
0d0
d121d6c71c do not trigger release when pushing to main
All checks were successful
Bump deps (only minor versions) / update-dependencies (push) Successful in 17s
2025-02-14 20:39:40 +01:00
0d0
44776b7ec7 check prepare and things
Some checks failed
Bump deps (only minor versions) / update-dependencies (push) Successful in 18s
Create Release / create-release (push) Failing after 25s
2025-02-14 20:38:09 +01:00
0d0
d65310fb85 ci
Some checks failed
Bump deps (only minor versions) / update-dependencies (push) Failing after 18s
Create Release / create-release (push) Failing after 27s
2025-02-14 20:31:57 +01:00
0d0
75bfadf2f4 Add release script 2025-02-14 20:31:47 +01:00
0d0
c5b1f9c3b0 0.5.0
All checks were successful
Create Release / create-release (push) Successful in 25s
2025-02-14 20:30:12 +01:00
0d0
3b8b173333 remove version 2025-02-14 20:30:02 +01:00
0d0
5bfd56a608 0.5.0 2025-02-14 20:29:16 +01:00
0d0
1966e0034e wrong version 2025-02-14 20:29:06 +01:00
0d0
75ac3b647d 0.5.0 2025-02-14 20:20:30 +01:00
0d0
505bcf89bc 0.4.1 2025-02-14 20:14:49 +01:00
35 changed files with 2113 additions and 1770 deletions

23
.dockerignore Normal file
View file

@ -0,0 +1,23 @@
Dockerfile
.dockerignore
.git
.gitignore
.gitattributes
README.md
.npmrc
.prettierrc
.eslintrc.cjs
.graphqlrc
.editorconfig
.svelte-kit
.vscode
node_modules
build
package
**/.env
scripts/
downloads
yt-dlp
build.tar.gz

6
.env.example Normal file
View file

@ -0,0 +1,6 @@
NODE_ENV=development
HOST=0.0.0.0
ORIGIN=https://dl.emersa.it
YTDLP_PATH=./yt-dlp
PUBLIC_VERSION=0.6.3
HTTPS_PROXY=

View file

@ -0,0 +1,21 @@
name: Bump deps (only minor versions)
on: [push]
jobs:
ci:
runs-on: docker
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
token: ${{ secrets.FORGEJO_TOKEN }}
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Prepare, Check, Lint and Format
run: |
npm i
npm run prepare

View file

@ -2,7 +2,7 @@ name: Bump deps (only minor versions)
on:
schedule:
- cron: '0 0 * * *' # Runs every night at midnight (UTC)
- cron: '0 23 * * *' # Runs every night at midnight
workflow_dispatch:
jobs:
@ -26,7 +26,7 @@ jobs:
npm install
git config --global user.name "forgejo-bot"
git config --global user.email "bot@pweapon.org"
git add package.json || exit 0
git add package* || exit 0
git commit -m "chore: update minor dependencies"
git push origin HEAD:${GITHUB_REF#refs/heads/}
env:

View file

@ -2,10 +2,8 @@ name: Create Release
on:
push:
branches:
- main
tags:
- "v*"
- 'v*'
workflow_dispatch:
jobs:
@ -23,13 +21,26 @@ jobs:
with:
node-version: '20'
- name: Prepare, Check, Lint and Format
- name: Install JQ for extracting package.json version
run: |
npm install
apt-get update
apt-get install -y jq
- name: Create Release
run: |
npm ci
touch .env.production
echo "HOST=0.0.0.0" >> .env.production
echo "PORT=3000" >> .env.production
echo "ORIGIN=https://dl.emersa.it" >> .env.production
echo "PUBLIC_VERSION=$(cat package.json | jq .version)" >> .env.production
echo "NODE_ENV=production" >> .env.production
npm run build
cp package* build/
cp .env.production build/
mkdir releases
tar czvf releases/build.tar.gz build/
cd build/
tar czvf ../releases/build.tar.gz .
- name: Upload release
uses: actions/forgejo-release@v2

20
Dockerfile Normal file
View file

@ -0,0 +1,20 @@
FROM node:20 AS build
WORKDIR /usr
COPY package.json ./
COPY package-lock.json ./
RUN npm ci
COPY . ./
RUN npm run build
FROM node:20
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
RUN npm ci
COPY . ./
COPY --from=build /usr/build /app
EXPOSE 8000
CMD ["node", "/app"]

View file

@ -1,20 +1,42 @@
## a frontend to yt-dlp
# scaricatore
It's a svelte(kit) frontend that uses `yt-dlp` to let the user download things from the web.
![version](https://git.pweapon.org/odo/dl.emersa.it/badges/release.svg 'version')
![status](https://git.pweapon.org/odo/dl.emersa.it/badges/workflows/ci.yaml/badge.svg 'status')
![GNU](https://img.shields.io/badge/license-GPL--3.0-green?logo=gnu)
- `youtube-dl-exec`: to download video data
- `yt-dlp`: to stream the file the user requested
It's a svelte(kit) frontend + backend that uses [`yt-dlp`](https://github.com/yt-dlp/yt-dlp) to let people download audio/video files from the web.
### Getting started
[`... we don't have the concept of users, when we refer to people, we call them people.`](https://ar.al/2020/08/07/what-is-the-small-web/)
- Clone the repo
- Run `npm install` (you have to have node installed)
<a href='https://dl.emersa.it'><img src='./static/screen.webp' alt='screen' height=300></a>
## Self-Hosting
### Node
- Install NodeJS
- Create a new directory (`"${PROJECT_ROOT}"`)
- run `scripts/install.sh "${PROJECT_ROOT}"`
Edit `scripts/deploy_example.sh` if you need to deploy `scaricatore` to some server using `SSH`.
### Docker
(currently not supported)
## Development: getting started
- run `git clone git@git.pweapon.org:odo/dl.emersa.it.git`
- Run `cd dl.emersa.it; npm install` (you have to have node installed)
- Run `npm run download-yt-dlp`
- Copy `.env.example` to `.env`
- Change `.env` to set `YTDLP_PATH` to the yt-dlp binary previously downloaded
- Run `npm run dev`
- Now you can write code
### Missing
## To do:
- Proper logs
- Containerfile
- Containerfile for container build
- Source spotify (spotdl)
- Parse URL info without `youtube-dl-exec`
- Dockerfile inside the forgejo release action

View file

@ -5,9 +5,9 @@ After=network.target
[Service]
User=user
Group=user
WorkingDirectory=<PROJECT_ROOT>
ExecStart=/usr/bin/node <PROJECT_ROOT>
Environment=ORIGIN=http://example.com
WorkingDirectory=/home/user/downloader
EnvironmentFile=/home/user/downloader/.env
ExecStart=/usr/bin/node /home/user/downloader
Restart=always
RestartSec=10
StandardOutput=syslog
@ -16,3 +16,4 @@ SyslogIdentifier=downloader
[Install]
WantedBy=multi-user.target

2942
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,13 @@
{
"name": "dl.emersa.it",
"private": true,
"version": "0.1.0",
"version": "1.0.0-c",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"download-yt-dlp": "wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux -O yt-dlp",
"download-yt-dlp": "wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux -O yt-dlp ; chmod +x yt-dlp",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
@ -14,31 +15,34 @@
"lint": "prettier --check . && eslint ."
},
"devDependencies": {
"@eslint/compat": "^1.2.6",
"@eslint/js": "^9.20.0",
"@sveltejs/adapter-auto": "^4.0.0",
"@eslint/compat": "^1.2.8",
"@eslint/js": "^9.25.0",
"@sveltejs/adapter-node": "^5.2.12",
"@sveltejs/kit": "^2.17.1",
"@sveltejs/kit": "^2.20.7",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"@types/node": "^22.13.4",
"autoprefixer": "^10.4.20",
"eslint": "^9.20.1",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^2.46.1",
"globals": "^15.15.0",
"prettier": "^3.5.1",
"@tailwindcss/vite": "^4.1.4",
"eslint": "^9.25.0",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-svelte": "^3.5.1",
"globals": "^16.0.0",
"mdsvex": "^0.12.3",
"prettier": "^3.5.3",
"prettier-plugin-svelte": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"svelte": "^5.20.0",
"svelte-check": "^4.1.4",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3",
"typescript-eslint": "^8.24.0",
"vite": "^6.1.0"
"svelte": "^5.28.1",
"svelte-check": "^4.1.6",
"sveltekit-sse": "^0.13.18",
"tailwindcss": "^4.1.4",
"typescript": "^5.8.3",
"typescript-eslint": "^8.30.1",
"vite": "^6.3.2"
},
"dependencies": {
"youtube-dl-exec": "^3.0.15"
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/postcss": "^4.1.4",
"@tailwindcss/typography": "^0.5.16",
"@types/node": "^22.14.1",
"winston": "^3.17.0",
"youtube-dl-exec": "^3.0.20"
}
}

View file

@ -1,6 +1,5 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {}
'@tailwindcss/postcss': {}
}
};

View file

@ -1,11 +1,8 @@
#!/bin/bash
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
## Prepares the current environment:
## - Installing dependencies
## - Configuring git hooks
set -e

View file

@ -1,32 +1,23 @@
#!/usr/bin/bash
# This is a script for running `install.sh`
# in a remote server using SSH.
# Configure SSH_SERVER and PROJECT_ROOT variables
# for using this script.
###### ATTENTION ######
# The install.sh script has a confirmation prompt
# because it deletes the content of the PROJECT_ROOT folder,
# just put "yes | install.sh" to automatically confirm.
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
NO_DELETE=false
SSH_SERVER="example"
PROJECT_ROOT=example_directory
SSH_REMOTE_DIR="${SSH_SERVER}:${PROJECT_ROOT}"
for arg in "$@"
do
if [ "$arg" == "--no-delete" ]; then
NO_DELETE=true
fi
done
if [ "$NO_DELETE" = false ]; then
echo "Deleting node_modules..."
rm -rf node_modules/
else
echo "Skipping deletion of node_modules."
fi
npm ci
npm run build
rsync -r --delete --progress build/ "${SSH_REMOTE_DIR}"
rsync package.json "${SSH_REMOTE_DIR}"
rsync package-lock.json "${SSH_REMOTE_DIR}"
ssh "${SSH_SERVER}" "cd ${PROJECT_ROOT}; npm ci"
ssh "${SSH_SERVER}" "systemctl restart downloader"
ssh "${SSH_SERVER}" "mkdir -p ${PROJECT_ROOT}"
rsync "${__dir}/install.sh" "${SSH_SERVER}:${PROJECT_ROOT}/install.sh"
ssh "${SSH_SERVER}" "${PROJECT_ROOT}/install.sh ${PROJECT_ROOT}"
ssh "${SSH_SERVER}" "systemctl restart downloader"

33
scripts/install.sh Executable file
View file

@ -0,0 +1,33 @@
#!/usr/bin/bash
### This is a script for installing the latest release
### of `scaricatore`.
PROJECT_ROOT=$1
PROXY=$2
if [ -z ${PROJECT_ROOT+x} ]; then
echo "ERROR: No PROJECT_ROOT set (first argument to ${0})"
exit 1
fi
if [ -z ${PROXY+x} ]; then
echo "INFO: no proxy given"
fi
mkdir -p "${PROJECT_ROOT}"
cd "${PROJECT_ROOT}" || exit 1
read -p "We're about to run rm -rf ${PROJECT_ROOT}/*. Are you sure?" -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then
rm -rf ./*
fi
wget https://git.pweapon.org/odo/dl.emersa.it/releases/download/latest/build.tar.gz
tar -xvf build.tar.gz -C .
rm build.tar.gz
npm ci
npm run download-yt-dlp
echo "YTDLP_PATH=$(readlink -f yt-dlp)" >> .env.production
echo "HTTPS_PROXY=${PROXY}" >> .env.production

17
scripts/release.sh Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
set -e
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
version="${1:?Error: No argument provided. Usage: $0 <version>}"
npm version "v${version}"
git push --tags

3
scripts/src/pre-commit.sh Normal file → Executable file
View file

@ -9,7 +9,4 @@
set -e
npm run prepare
npm run check
npm run format
npm run lint

View file

@ -1,3 +1,22 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
@import 'tailwindcss';
@plugin '@tailwindcss/typography';
@plugin '@tailwindcss/forms';
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}

View file

@ -7,28 +7,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
<style>
@font-face {
font-family: 'Press Start 2P';
src: url('/fonts/PressStart2P-Regular.ttf');
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
font-family: 'Fira Code', monospace;
}
body {
background: black; /* Fallback */
/* background-image:
radial-gradient(circle, #37ff1456 8%, transparent 8%),
radial-gradient(circle, #37ff1456 8%, transparent 8%); */
background-size:
60px 60px,
30px 30px; /* Larger grid sizes for more spacing */
background-position:
0 0,
15px 15px; /* Offset the smaller pattern slightly */
font-family: 'Press Start 2P', sans-serif;
color: #37ff1456; /* Retro green text */
margin: 0;
}

7
src/hooks.server.ts Normal file
View file

@ -0,0 +1,7 @@
import { logger } from '$lib/server/helpers';
export async function handle({ event, resolve }) {
logger.info(`Received ${event.request.method} request: ${event.url}`);
return await resolve(event);
}

View file

@ -0,0 +1,21 @@
const createAnchorElement = (url: string, filename: string): HTMLAnchorElement => {
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = filename;
return anchor;
};
export const download = async (url: string, filename: string) => {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const blob = await response.blob();
const objectURL = window.URL.createObjectURL(blob);
const anchor = createAnchorElement(url, filename);
document.body.appendChild(anchor);
anchor.click();
anchor.remove();
window.URL.revokeObjectURL(objectURL);
};

View file

@ -0,0 +1,6 @@
{
"mp3": "audio/mpeg",
"opus": "audio/ogg",
"wav": "audio/wav",
"mp4": "video/mp4"
}

View file

@ -1,3 +1,73 @@
<script lang="ts">
let props = $props();
import { onMount } from 'svelte';
let { url, dismiss } = $props();
let visible = $state(false);
let progress = $state(0);
let filename = $state('');
onMount(async () => {
if (!url) return;
try {
visible = true;
const response = await fetch(url);
if (!response.ok) throw new Error('Download failed');
const contentDisposition: string = response?.headers?.get('content-disposition');
filename = contentDisposition.split('filename=')[1];
const contentLength: number = Number(response?.headers?.get('content-length'));
const reader = response?.body?.getReader();
const chunks: Uint8Array[] = [];
let receivedLength = 0;
while (true) {
const { done, value }: ReadableStreamReadResult<Uint8Array> = await reader.read();
if (done) break;
if (value) {
chunks.push(value);
receivedLength += value.length;
progress = Math.round((receivedLength / contentLength) * 100);
}
}
const blob = new Blob(chunks);
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = downloadUrl;
a.download = filename;
a.click();
URL.revokeObjectURL(downloadUrl);
setTimeout(() => {
visible = false;
}, 1500); // auto-dismiss
} catch (err) {
console.error(err);
visible = false;
}
});
</script>
{#if visible}
<div
class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 font-mono backdrop-blur-sm"
>
<div
class="w-[90%] max-w-sm rounded-2xl border border-green-400 bg-[#000f00] p-6 text-sm text-green-300 shadow-2xl"
>
<p class="mb-2 text-center text-cyan-300">
Downloading <span class="font-semibold text-green-400">{filename}</span>
</p>
<div class="h-4 w-full overflow-hidden rounded-md border border-green-500 bg-black">
<div
class="h-full bg-gradient-to-r from-green-400 to-green-600 transition-all duration-300"
style="width: {progress}%"
/>
</div>
<p class="mt-2 text-center text-pink-400">{progress}%</p>
</div>
</div>
{/if}

View file

@ -1,6 +1,28 @@
<div
class="absolute inset-0 z-10 flex items-center justify-center bg-white bg-opacity-50"
id="spinner"
>
<div class="h-20 w-20 animate-spin rounded-full border-b-2 border-t-2 border-gray-900"></div>
<div class="w-[150px]">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"
><linearGradient id="a3"
><stop offset="0" stop-color="#FF156D" stop-opacity="0"></stop><stop
offset="1"
stop-color="#FF156D"
></stop></linearGradient
><circle
fill="none"
stroke="url(#a3)"
stroke-width="15"
stroke-linecap="round"
stroke-dasharray="0 44 0 44 0 44 0 44 0 360"
cx="100"
cy="100"
r="70"
transform-origin="center"
><animateTransform
type="rotate"
attributeName="transform"
calcMode="discrete"
dur="2"
values="360;324;288;252;216;180;144;108;72;36"
repeatCount="indefinite"
></animateTransform></circle
></svg
>
</div>

19
src/lib/server/helpers.ts Normal file
View file

@ -0,0 +1,19 @@
import formats from '$lib/common/supportedFormats.json';
import winston from 'winston';
export const logger = winston.createLogger({
level: 'debug',
format: winston.format.json(),
transports: [new winston.transports.Console()]
});
const formatMime = new Map(Object.entries(formats));
export const isURLValid = (url: string) => {
try {
new URL(url);
} catch {
return false;
}
return true;
};
export const mimeTypeMap = formatMime;

View file

@ -1,7 +1,11 @@
import { create } from 'youtube-dl-exec';
import { env } from '$env/dynamic/private';
import { spawn } from 'node:child_process';
const YTDLP_PATH: string = env.YTDLP_PATH as string
import supportedFormats from '$lib/common/supportedFormats.json';
import { logger, mimeTypeMap } from '$lib/server/helpers';
const YTDLP_PATH: string = env.YTDLP_PATH as string;
const HTTPS_PROXY: string = env.HTTPS_PROXY as string;
export const ytdl = create(YTDLP_PATH);
@ -9,37 +13,73 @@ export const ytdl = create(YTDLP_PATH);
* Fetch YouTube metadata (title, uploader/artist)
*/
export async function getYouTubeMetadata(link: string) {
return await ytdl(link, {
const options = {
dumpSingleJson: true,
noCheckCertificates: true,
noWarnings: true,
preferFreeFormats: true
});
};
if (HTTPS_PROXY) {
options.proxy = HTTPS_PROXY;
}
return await ytdl(link, options);
}
/**
* Streams the YouTube video/audio using youtube-dl-exec
*/
export function streamYouTube(link: string, format: string): ReadableStream<Uint8Array> {
logger.debug(`Starting to stream: ${link}`);
const mimeType: string | undefined = mimeTypeMap.get(format);
if (!mimeType) {
throw new Error('Unsupported format');
}
logger.debug(`Given format is compatible: ${mimeType}`);
return new ReadableStream({
start(controller) {
const args = [
'-o',
'-',
format === 'mp3' ? '--embed-metadata' : '',
'--format',
format === 'mp3' ? 'bestaudio' : 'best',
'--audio-format',
format === 'mp3' ? 'mp3' : '',
'--no-playlist'
].filter(Boolean);
const args = ['--no-write-thumbnail', '-o', '-'];
const process = spawn('yt-dlp', [...args, link], { stdio: ['ignore', 'pipe', 'ignore'] });
if (HTTPS_PROXY) {
args.push('--proxy', HTTPS_PROXY);
}
process.stdout.on('data', (chunk) => controller.enqueue(chunk));
process.stdout.on('end', () => controller.close());
if (mimeType?.includes('audio')) {
args.push(
...['--extract-audio', '--embed-metadata', '--embed-thumbnail', '--audio-format', format]
);
} else if (mimeType.includes('video')) {
args.push(...['--embed-metadata', '--embed-thumbnail', '--format', format]);
}
const cmd = `${YTDLP_PATH} ${args.join(' ')} ${link}`;
logger.debug(`Running: ${cmd}`);
const process = spawn(YTDLP_PATH, [...args, link], {
cwd: '/tmp',
stdio: ['ignore', 'pipe', 'pipe']
});
process.stdout.on('data', (chunk) => {
try {
controller.enqueue(chunk);
} catch (ex) {
process.kill();
}
});
process.stderr.on('data', (chunk) => logger.debug(chunk.toString()));
process.stdout.on('end', () => {
try {
controller.close();
} catch (ex) {
logger.error(ex);
}
});
process.stdout.on('error', (err) => {
console.error('Stream error:', err);
logger.error('Stream error:', err);
controller.error(err);
});
}

View file

@ -17,4 +17,11 @@
transform: rotate(180deg);
display: inline-block;
}
@media screen and (max-height: 600px) {
/* Your CSS rules here */
footer {
display: none;
}
}
</style>

View file

@ -0,0 +1,3 @@
export const prerender = true;
export const ssr = true;
export const csr = true;

View file

@ -1,34 +1,77 @@
<script>
<script lang="ts">
import { PUBLIC_VERSION } from '$env/static/public';
import supportedFormats from '$lib/common/supportedFormats.json';
import Loader from '$lib/components/Loader.svelte';
import { download } from '$lib/client/downloader';
import DownloadManager from '$lib/components/DownloadManager.svelte';
import { mount, unmount } from 'svelte';
let source = $state('youtube');
let link = $state('');
let format = $state('mp3');
let showModal = $state(false);
let href = $state('');
// let formats = ['ogg', 'mp3', 'mp4']
const formats = [{ value: 'mp3', label: 'MP3' }];
let disabled = $state(true);
let metadata = $state(false);
let logs = $state('');
let downloadManager: DownloadManager | null = null;
const formats = Object.keys(supportedFormats).map((f) => {
return { value: f, label: f.toUpperCase() };
});
const sources = [
{ value: 'youtube', label: 'YouTube' },
{ value: 'youtube', label: 'Any Other Website' }
];
const toggleModal = () => {
showModal = !showModal;
};
const handleSubmit = async (e) => {
e.preventDefault();
const dismiss = () => {
unmount(downloadManager);
};
console.log({
source,
link,
format
});
const onClick = async (evt) => {
evt.preventDefault();
const props = $state({ url: href });
downloadManager = mount(DownloadManager, { target: document.body, props, events: { dismiss } });
link = '';
};
const createAnchor = () => {
if (!(source && link && format)) {
disabled = true;
return;
}
try {
new URL(link);
disabled = false;
} catch (err) {
/*
if (err.code === 'ERR_INVALID_URL') {
}
*/
disabled = true;
return;
}
const searchParams = new URLSearchParams();
searchParams.append('source', source);
searchParams.append('link', link);
searchParams.append('format', format);
if (metadata) searchParams.append('metadata', '1');
href = `/download?${searchParams.toString()}`;
};
$effect(() => {
createAnchor();
// Auto selected the radio button based on url regex
if (link.includes('spotify')) {
source = 'spotify';
@ -40,166 +83,130 @@
<div
id="wrapper"
class="relative mx-auto rounded-lg bg-black p-6 text-green-500 shadow-lg sm:max-w-sm sm:border-4 sm:border-green-500 md:mt-10 md:max-w-md lg:max-w-lg 2xl:max-w-2xl"
class="relative mx-auto max-w-full rounded-2xl bg-black p-4 text-green-400 shadow-xl sm:max-w-sm md:max-w-md lg:max-w-lg"
>
<!-- Info Icon -->
<!-- Loader Overlay -->
<div
id="loader"
class="absolute inset-0 z-10 hidden items-center justify-center bg-black/80 backdrop-blur-sm"
>
<Loader />
{@html logs}
</div>
<!-- Info Button -->
<button
onclick={toggleModal}
class="absolute right-3 top-3 text-pink-500 transition hover:text-pink-300"
class="absolute top-3 right-3 text-pink-500 transition hover:text-pink-400"
aria-label="Open Info Modal"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="h-6 w-6" viewBox="0 0 24 24">
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="h-5 w-5" viewBox="0 0 24 24">
<path
d="M12 0C5.373 0 0 5.373 0 12c0 6.627 5.373 12 12 12s12-5.373 12-12C24 5.373 18.627 0 12 0zm.75 18h-1.5v-6h1.5v6zm0-8h-1.5V8h1.5v2z"
/>
</svg>
</button>
<h1 id="title" class="mb-6 text-center text-xl">🐙 Scaricatore 🐙</h1>
<form class="space-y-6" onsubmit={handleSubmit}>
<!-- Source Selection -->
<fieldset class="space-y-4">
<legend class="text-green-400">Choose Source:</legend>
<!-- Title -->
<p id="title" class="mb-4 text-center font-mono text-xl tracking-tight text-cyan-300">
🐙 Scaricatore 🐙
</p>
<label class="flex items-center space-x-3">
<input type="radio" name="source" value="youtube" bind:group={source} class="retro-radio" />
<span>YouTube</span>
</label>
<label class="flex items-center space-x-3">
<input
disabled
type="radio"
<!-- Form -->
<form class="space-y-5 font-mono text-sm">
<!-- Source & Format -->
<div class="flex flex-col gap-4 sm:flex-row">
<div class="flex-1">
<label for="source" class="mb-1 block text-cyan-300">Source</label>
<select
id="source"
name="source"
value="spotify"
bind:group={source}
class="retro-radio"
/>
<span class="not-available">Spotify</span>
</label>
bind:value={source}
class="w-full rounded-md border border-green-400 bg-[#000f00] px-3 py-2 text-green-300 focus:border-pink-400 focus:outline-none"
>
{#each sources as source}
<option value={source.value}>{source.label}</option>
{/each}
</select>
</div>
<label class="flex items-center space-x-3">
<input type="radio" name="source" value="other" bind:group={source} class="retro-radio" />
<span>
Other (<a
href="https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md"
target="_blank"
rel="noopener noreferrer"
class="text-pink-500 hover:underline"
>supported sites
</a>)
</span>
</label>
</fieldset>
<div class="flex-1">
<label for="format" class="mb-1 block text-cyan-300">Format</label>
<select
id="format"
name="format"
bind:value={format}
class="w-full rounded-md border border-green-400 bg-[#000f00] px-3 py-2 text-green-300 focus:border-pink-400 focus:outline-none"
>
{#each formats as format}
<option value={format.value}>{format.label}</option>
{/each}
</select>
</div>
</div>
<!-- Link Input -->
<!-- Video Link -->
<div>
<label for="link" class="mb-2 block text-green-400"> Enter Playlist or Video Link: </label>
<label for="link" class="mb-1 block text-cyan-300">Video Link</label>
<input
name="link"
type="url"
id="link"
name="link"
bind:value={link}
required
placeholder="Paste your link here"
class="w-full rounded-lg border-4 border-green-500 bg-green-200 px-4 py-3 text-black focus:border-pink-500 focus:outline-none"
placeholder="https://..."
class="w-full rounded-md border border-green-400 bg-[#000f00] px-3 py-2 text-green-300 placeholder:text-green-600 focus:border-pink-400 focus:outline-none"
/>
</div>
<!-- Format Selection -->
<div>
<label for="format" class="mb-2 block text-green-400"> Choose Format: </label>
<select
id="format"
name="format"
bind:value={format}
class="w-full rounded-lg border-4 border-green-500 bg-green-200 px-4 py-3 text-black focus:border-pink-500 focus:outline-none"
<!-- Metadata Checkbox -->
<div class="flex items-center gap-2">
<input
type="checkbox"
id="metadata"
name="metadata"
bind:checked={metadata}
class="h-4 w-4 border border-green-400 bg-[#000f00] text-green-500 focus:ring-pink-400"
/>
<label for="metadata" class="text-cyan-300"
>Set filename (<span class="text-red-500">slow</span>)</label
>
{#each formats as format}
<option value={format.value}>{format.label}</option>
{/each}
</select>
</div>
<!-- Submit Button -->
<button
type="submit"
class="w-full rounded-lg border-4 border-pink-700 bg-pink-500 px-4 py-3 text-black transition hover:bg-pink-600 active:border-yellow-500"
<!-- Download Button -->
<a
id="btn-download"
{href}
onclick={onClick}
class="{disabled
? 'pointer-events-none opacity-50'
: ''} block w-full rounded-md border border-pink-400 bg-pink-600 px-4 py-3 text-center text-base font-bold text-black transition hover:bg-pink-500 active:border-yellow-400"
>
Create download link
</button>
{#if href}
<a class="download-link" {href}> Download </a>
{/if}
DOWNLOAD
</a>
</form>
</div>
<!-- Modal -->
{#if showModal}
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-80">
<div
class="w-4/5 max-w-lg rounded-lg border-4 border-green-500 bg-green-900 p-6 text-center text-green-100"
>
<h2 class="mb-4 text-lg">🐙 Scaricatore 🐙</h2>
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/90 text-green-300">
<div class="w-[90%] max-w-md rounded-lg border border-green-400 bg-[#001a00] p-5 text-center">
<h2 class="mb-3 text-base font-semibold">🐙 Scaricatore v{PUBLIC_VERSION} 🐙</h2>
<p>
This app allows you to download Spotify playlists and YouTube videos directly. Choose your
source, paste the link, and select a format to start downloading!
Download Spotify playlists and YouTube videos with ease. Choose your source, paste a link,
select format, go!
</p>
<span class="mt-10 block">
<a class="underline" href="https://git.pweapon.org/odo/dl.emersa.it"
>Click here for the source code</a
<p class="mt-3">
<a class="text-cyan-400 underline" href="https://git.pweapon.org/odo/dl.emersa.it"
>Source Code</a
>
</span>
</p>
<button
onclick={toggleModal}
class="mt-6 rounded-lg border-4 border-pink-700 bg-pink-500 px-4 py-2 text-black hover:bg-pink-600"
class="mt-6 rounded-md border border-pink-400 bg-pink-600 px-4 py-2 text-black hover:bg-pink-500"
>
Close
</button>
</div>
</div>
{/if}
<style>
* {
font-size: 12px;
}
.download-link {
margin: 0 auto;
padding: 5px;
display: block;
text-decoration: underline;
text-align: center;
}
.not-available {
text-decoration-line: line-through;
text-decoration-color: red;
}
.retro-radio {
appearance: none;
background-color: #000;
border: 2px solid #39ff14;
width: 20px;
height: 20px;
cursor: pointer;
}
.retro-radio:checked {
background-color: #39ff14;
box-shadow:
0 0 4px #39ff14,
0 0 10px #39ff14;
}
input[type='url'],
select {
font-family: inherit;
}
#title {
font-size: 22px;
}
</style>

View file

@ -1,12 +1,14 @@
import { error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getYouTubeMetadata, streamYouTube } from '$lib/server/ytdlp';
import { getYouTubeMetadata, streamYouTube, ytdl } from '$lib/server/ytdlp';
import { isURLValid, logger, mimeTypeMap } from '$lib/server/helpers';
export const GET: RequestHandler = async ({ url }) => {
const validateRequest = (url: URL) => {
// Get query params
const link = url.searchParams.get('link');
const format = url.searchParams.get('format'); // mp3, mp4
const source = url.searchParams.get('source'); // youtube or spotify
const metadata = url.searchParams.has('metadata');
// Validate input
if (!link || !format || !source) {
@ -17,23 +19,56 @@ export const GET: RequestHandler = async ({ url }) => {
throw error(400, 'Currently, only YouTube is supported');
}
try {
// Fetch metadata for filename
const metadata = await getYouTubeMetadata(link);
const { title, uploader } = metadata;
const safeTitle = `${uploader} - ${title}`;
const filename = `${safeTitle}.${format}`;
if (!isURLValid(link)) {
throw error(400, 'URL not valid');
}
console.log(filename);
if (!mimeTypeMap.get(format)) {
throw error(400, 'format not valid');
}
logger.debug(`Request is valid`);
return {
link,
format,
source,
metadata
};
};
export const GET: RequestHandler = async ({ url }) => {
const { format, source, metadata, link } = validateRequest(url);
let filename = '';
let contentLength = 0;
logger.debug(`Requested: ${link}`);
try {
logger.debug(`Fetching video data to set filename`);
// Fetch metadata for filename
const ytMetadata = await getYouTubeMetadata(link);
const { title, uploader, filesize_approx } = ytMetadata;
contentLength = filesize_approx;
const safeTitle = `${uploader} - ${title}`;
filename = `${safeTitle}.${format}`;
} catch (err) {
logger.error(err);
logger.error('Error fetching metadata:');
throw error(500, 'Failed to fetch video metadata');
}
try {
// Stream video/audio
return new Response(streamYouTube(link, format), {
headers: {
'Content-Type': format === 'mp3' ? 'audio/mpeg' : 'video/mp4',
'Content-Type': `${mimeTypeMap.get(format)}`,
'Content-Length': contentLength,
'Content-Disposition': `attachment; filename="${filename}"`
}
});
} catch (err) {
console.error('Error fetching metadata:', err);
throw error(500, 'Failed to fetch video metadata');
logger.error(err);
logger.error('Filed to stream file');
throw error(500, 'Failed to stream file');
}
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

View file

@ -1,16 +1,16 @@
{
"name": "EmersaDownloader",
"name": "scaricatore",
"start_url": "https://dl.emersa.it",
"theme_color": "rgb(34,197,94)",
"background": "black",
"orientation": "portrait",
"display": "fullscreen",
"short_name": "e-downloader",
"short_name": "scaricatore",
"icons": [
{
"src": "favicon.png",
"type": "image/png",
"sizes": "128x128"
"sizes": "512x512"
}
]
}

BIN
static/screen.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,3 +1,4 @@
import { mdsvex } from 'mdsvex';
import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
@ -5,14 +6,13 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(),
preprocess: [vitePreprocess(), mdsvex()],
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
}
},
extensions: ['.svelte', '.svx']
};
export default config;

View file

@ -1,13 +0,0 @@
import forms from '@tailwindcss/forms';
import typography from '@tailwindcss/typography';
import type { Config } from 'tailwindcss';
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: [typography, forms]
} satisfies Config;

View file

@ -1,6 +1,7 @@
import tailwindcss from '@tailwindcss/vite';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()]
plugins: [sveltekit(), tailwindcss()]
});