Compare commits
43 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c46189ff83 | ||
|
c416918a1a | ||
|
7a3bf1fb45 | ||
|
cd8a4c4d69 | ||
9c7f7eace1 | |||
5066c3ba7a | |||
a833c43713 | |||
a18fbb8614 | |||
|
bb233f7cb8 | ||
|
2f502b2530 | ||
|
c32cc4d3e7 | ||
|
5fc6b0700a | ||
|
b94d5ffc19 | ||
|
267da475a6 | ||
|
82aac1d3b9 | ||
56ef54b119 | |||
|
d21d4d57a9 | ||
214619ec3f | |||
|
18adf9a6a3 | ||
|
66196979cc | ||
|
4d0eaed688 | ||
|
6003e59aaa | ||
|
99ae01f895 | ||
|
9f8b49515e | ||
|
c7d65ee49a | ||
|
84feab36dc | ||
|
728db51c59 | ||
|
c3072322d1 | ||
|
565612cf30 | ||
77d1d7331d | |||
ebf597fea6 | |||
|
7dc90c4c27 | ||
|
96d59113bc | ||
|
e0fbca1e6d | ||
2899def330 | |||
|
e4dffe691c | ||
|
c55524221a | ||
|
1f5a6613d0 | ||
a4bec2cb38 | |||
|
f080ccc912 | ||
|
8e37875442 | ||
af9c2084eb | |||
13ba9fd1a1 |
6 changed files with 482 additions and 476 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||

|
||||

|
||||

|
||||
|
||||
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.
|
||||
|
||||
|
|
796
package-lock.json
generated
796
package-lock.json
generated
File diff suppressed because it is too large
Load diff
38
package.json
38
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "dl.emersa.it",
|
||||
"private": true,
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.3-c",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
|
@ -15,34 +15,34 @@
|
|||
"lint": "prettier --check . && eslint ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.2.7",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@eslint/compat": "^1.2.8",
|
||||
"@eslint/js": "^9.24.0",
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@sveltejs/kit": "^2.17.3",
|
||||
"@sveltejs/kit": "^2.20.5",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@tailwindcss/vite": "^4.0.9",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-svelte": "^2.46.1",
|
||||
"@tailwindcss/vite": "^4.1.3",
|
||||
"eslint": "^9.24.0",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-plugin-svelte": "^3.5.1",
|
||||
"globals": "^16.0.0",
|
||||
"mdsvex": "^0.12.3",
|
||||
"prettier": "^3.5.2",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"svelte": "^5.20.4",
|
||||
"svelte-check": "^4.1.4",
|
||||
"sveltekit-sse": "^0.13.14",
|
||||
"tailwindcss": "^4.0.9",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.25.0",
|
||||
"vite": "^6.2.0"
|
||||
"svelte": "^5.26.1",
|
||||
"svelte-check": "^4.1.5",
|
||||
"sveltekit-sse": "^0.13.16",
|
||||
"tailwindcss": "^4.1.3",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.29.1",
|
||||
"vite": "^6.2.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tailwindcss/postcss": "^4.0.9",
|
||||
"@tailwindcss/postcss": "^4.1.3",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@types/node": "^22.13.5",
|
||||
"@types/node": "^22.14.1",
|
||||
"winston": "^3.17.0",
|
||||
"youtube-dl-exec": "^3.0.16"
|
||||
"youtube-dl-exec": "^3.0.20"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,11 @@
|
|||
transform: rotate(180deg);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@media screen and (max-height: 600px) {
|
||||
/* Your CSS rules here */
|
||||
footer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
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;
|
||||
|
@ -90,7 +94,7 @@
|
|||
|
||||
<div
|
||||
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
|
||||
id="loader"
|
||||
|
@ -118,47 +122,40 @@
|
|||
|
||||
<p id="title" class="mb-6 text-center text-[#00e5ff]">🐙 Scaricatore 🐙</p>
|
||||
<form class="space-y-6">
|
||||
<!-- Source Selection -->
|
||||
<fieldset class="space-y-4">
|
||||
<legend class="text-[#00e5ff]">Choose Source:</legend>
|
||||
|
||||
<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"
|
||||
<!-- Source selection -->
|
||||
<div class="flex justify-between">
|
||||
<div class="w-2/6 lg:w-3/6">
|
||||
<label for="source" class="mb-2 block text-[#00e5ff]"> Choose Source: </label>
|
||||
<select
|
||||
id="source"
|
||||
name="source"
|
||||
value="spotify"
|
||||
bind:group={source}
|
||||
class="retro-radio"
|
||||
/>
|
||||
<span class="not-available">Spotify</span>
|
||||
</label>
|
||||
|
||||
<label class="flex items-center space-x-3">
|
||||
<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>
|
||||
bind:value={source}
|
||||
class="w-full rounded-lg border-4 border-[#00ff7f] bg-[#001a00] px-4 py-3 text-[#00ff7f] focus:border-[#ff3399] focus:outline-none"
|
||||
>
|
||||
{#each sources as source}
|
||||
<option value={source.value}>{source.label}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 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 -->
|
||||
<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
|
||||
name="link"
|
||||
type="url"
|
||||
|
@ -170,21 +167,6 @@
|
|||
/>
|
||||
</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 -->
|
||||
<div>
|
||||
<label for="metadata" class="mb-2 block text-[#00e5ff]"
|
||||
|
@ -249,7 +231,8 @@
|
|||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
@media (min-width: 1400px) {
|
||||
* {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
@ -258,31 +241,12 @@
|
|||
#loader {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loader.downloading {
|
||||
display: grid;
|
||||
justify-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'],
|
||||
select {
|
||||
|
|
|
@ -38,7 +38,7 @@ const validateRequest = (url: URL) => {
|
|||
};
|
||||
export const GET: RequestHandler = async ({ 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) {
|
||||
try {
|
||||
|
@ -59,7 +59,7 @@ export const GET: RequestHandler = async ({ url }) => {
|
|||
// Stream video/audio
|
||||
return new Response(streamYouTube(link, format), {
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Content-Type': `${mimeTypeMap.get(format)}`,
|
||||
'Content-Disposition': `attachment; filename="${filename}"`,
|
||||
'Set-Cookie': 'downloading=0'
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue