Compare commits

...

49 commits
v0.9.0 ... main

Author SHA1 Message Date
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
6 changed files with 654 additions and 561 deletions

View file

@ -2,6 +2,7 @@
![version](https://git.pweapon.org/odo/dl.emersa.it/badges/release.svg 'version') ![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') ![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)
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. 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.

1053
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{ {
"name": "dl.emersa.it", "name": "dl.emersa.it",
"private": true, "private": true,
"version": "0.9.0", "version": "0.9.3-c",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
@ -15,34 +15,34 @@
"lint": "prettier --check . && eslint ." "lint": "prettier --check . && eslint ."
}, },
"devDependencies": { "devDependencies": {
"@eslint/compat": "^1.2.7", "@eslint/compat": "^1.2.8",
"@eslint/js": "^9.21.0", "@eslint/js": "^9.24.0",
"@sveltejs/adapter-node": "^5.2.12", "@sveltejs/adapter-node": "^5.2.12",
"@sveltejs/kit": "^2.17.3", "@sveltejs/kit": "^2.20.7",
"@sveltejs/vite-plugin-svelte": "^5.0.3", "@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/vite": "^4.0.9", "@tailwindcss/vite": "^4.1.4",
"eslint": "^9.21.0", "eslint": "^9.24.0",
"eslint-config-prettier": "^10.0.1", "eslint-config-prettier": "^10.1.2",
"eslint-plugin-svelte": "^2.46.1", "eslint-plugin-svelte": "^3.5.1",
"globals": "^16.0.0", "globals": "^16.0.0",
"mdsvex": "^0.12.3", "mdsvex": "^0.12.3",
"prettier": "^3.5.2", "prettier": "^3.5.3",
"prettier-plugin-svelte": "^3.3.3", "prettier-plugin-svelte": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.11", "prettier-plugin-tailwindcss": "^0.6.11",
"svelte": "^5.20.4", "svelte": "^5.27.2",
"svelte-check": "^4.1.4", "svelte-check": "^4.1.6",
"sveltekit-sse": "^0.13.14", "sveltekit-sse": "^0.13.18",
"tailwindcss": "^4.0.9", "tailwindcss": "^4.1.4",
"typescript": "^5.7.3", "typescript": "^5.8.3",
"typescript-eslint": "^8.25.0", "typescript-eslint": "^8.30.1",
"vite": "^6.2.0" "vite": "^6.3.1"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.10",
"@tailwindcss/postcss": "^4.0.9", "@tailwindcss/postcss": "^4.1.4",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@types/node": "^22.13.5", "@types/node": "^22.14.1",
"winston": "^3.17.0", "winston": "^3.17.0",
"youtube-dl-exec": "^3.0.16" "youtube-dl-exec": "^3.0.20"
} }
} }

View file

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

View file

@ -18,6 +18,10 @@
const formats = Object.keys(supportedFormats).map((f) => { const formats = Object.keys(supportedFormats).map((f) => {
return { value: f, label: f.toUpperCase() }; return { value: f, label: f.toUpperCase() };
}); });
const sources = [
{ value: 'youtube', label: 'YouTube' },
{ value: 'youtube', label: 'Any Other Website' }
];
const toggleModal = () => { const toggleModal = () => {
showModal = !showModal; showModal = !showModal;
@ -90,7 +94,7 @@
<div <div
id="wrapper" id="wrapper"
class="relative mx-auto rounded-lg bg-black p-6 text-[#00ff7f] shadow-lg sm:max-w-sm sm:border-4 sm:border-[#00ff7f] md:mt-10 md:max-w-md lg:max-w-lg 2xl:max-w-2xl" class="relative mx-auto rounded-lg bg-black p-6 text-[#00ff7f] shadow-lg sm:mt-10 sm:max-w-sm sm:border-4 sm:border-[#00ff7f] lg:max-w-lg 2xl:max-w-2xl"
> >
<div <div
id="loader" id="loader"
@ -118,47 +122,40 @@
<p id="title" class="mb-6 text-center text-[#00e5ff]">🐙 Scaricatore 🐙</p> <p id="title" class="mb-6 text-center text-[#00e5ff]">🐙 Scaricatore 🐙</p>
<form class="space-y-6"> <form class="space-y-6">
<!-- Source Selection --> <!-- Source selection -->
<fieldset class="space-y-4"> <div class="flex justify-between">
<legend class="text-[#00e5ff]">Choose Source:</legend> <div class="w-2/6 lg:w-3/6">
<label for="source" class="mb-2 block text-[#00e5ff]"> Choose Source: </label>
<label class="flex items-center space-x-3"> <select
<input type="radio" name="source" value="youtube" bind:group={source} class="retro-radio" /> id="source"
<span>YouTube</span>
</label>
<label class="flex items-center space-x-3">
<input
disabled
type="radio"
name="source" name="source"
value="spotify" bind:value={source}
bind:group={source} class="w-full rounded-lg border-4 border-[#00ff7f] bg-[#001a00] px-4 py-3 text-[#00ff7f] focus:border-[#ff3399] focus:outline-none"
class="retro-radio" >
/> {#each sources as source}
<span class="not-available">Spotify</span> <option value={source.value}>{source.label}</option>
</label> {/each}
</select>
<label class="flex items-center space-x-3"> </div>
<input type="radio" name="source" value="other" bind:group={source} class="retro-radio" />
<span>
Any other website
<!--
(<a
href="https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md"
target="_blank"
rel="noopener noreferrer"
class="text-[#ff3399] hover:underline"
>supported sites
</a>)
-->
</span>
</label>
</fieldset>
<!-- Format Selection -->
<div class="w-2/6">
<label for="format" class="mb-2 block text-[#00e5ff]"> Choose Format: </label>
<select
id="format"
name="format"
bind:value={format}
class="w-full rounded-lg border-4 border-[#00ff7f] bg-[#001a00] px-4 py-3 text-[#00ff7f] focus:border-[#ff3399] focus:outline-none"
>
{#each formats as format}
<option value={format.value}>{format.label}</option>
{/each}
</select>
</div>
</div>
<!-- Link Input --> <!-- Link Input -->
<div> <div>
<label for="link" class="mb-2 block text-[#00e5ff]"> Enter Playlist or Video Link: </label> <label for="link" class="mb-2 block text-[#00e5ff]"> Enter Video Link: </label>
<input <input
name="link" name="link"
type="url" type="url"
@ -170,21 +167,6 @@
/> />
</div> </div>
<!-- Format Selection -->
<div>
<label for="format" class="mb-2 block text-[#00e5ff]"> Choose Format: </label>
<select
id="format"
name="format"
bind:value={format}
class="w-full rounded-lg border-4 border-[#00ff7f] bg-[#001a00] px-4 py-3 text-[#00ff7f] focus:border-[#ff3399] focus:outline-none"
>
{#each formats as format}
<option value={format.value}>{format.label}</option>
{/each}
</select>
</div>
<!-- Metadata --> <!-- Metadata -->
<div> <div>
<label for="metadata" class="mb-2 block text-[#00e5ff]" <label for="metadata" class="mb-2 block text-[#00e5ff]"
@ -249,7 +231,8 @@
font-size: 10px; font-size: 10px;
} }
} }
@media (min-width: 1024px) {
@media (min-width: 1400px) {
* { * {
font-size: 12px; font-size: 12px;
} }
@ -258,31 +241,12 @@
#loader { #loader {
display: none; display: none;
} }
#loader.downloading { #loader.downloading {
display: grid; display: grid;
justify-items: center; justify-items: center;
align-items: center; align-items: center;
} }
.not-available {
text-decoration-line: line-through;
text-decoration-color: red;
}
.retro-radio {
appearance: none;
background-color: #000;
border: 2px solid #00ff7f;
width: 20px;
height: 20px;
cursor: pointer;
}
.retro-radio:checked {
background-color: #00ff7f;
box-shadow:
0 0 4px #00ff7f,
0 0 10px #00ff7f;
}
input[type='url'], input[type='url'],
select { select {

View file

@ -38,7 +38,7 @@ const validateRequest = (url: URL) => {
}; };
export const GET: RequestHandler = async ({ url }) => { export const GET: RequestHandler = async ({ url }) => {
const { format, source, metadata, link } = validateRequest(url); const { format, source, metadata, link } = validateRequest(url);
let filename = `you-clicked-no-metadata-so-i-cant-put-a-correct-name.${format}`; let filename = `noname.${format}`;
if (!!metadata) { if (!!metadata) {
try { try {
@ -59,7 +59,7 @@ export const GET: RequestHandler = async ({ url }) => {
// Stream video/audio // Stream video/audio
return new Response(streamYouTube(link, format), { return new Response(streamYouTube(link, format), {
headers: { headers: {
'Content-Type': 'text/event-stream', 'Content-Type': `${mimeTypeMap.get(format)}`,
'Content-Disposition': `attachment; filename="${filename}"`, 'Content-Disposition': `attachment; filename="${filename}"`,
'Set-Cookie': 'downloading=0' 'Set-Cookie': 'downloading=0'
} }