mirror of
https://github.com/OpenSTDL/CrunchyDL.git
synced 2024-10-18 14:25:06 +02:00
added prettier
This commit is contained in:
parent
2e29f467d1
commit
9909e3b558
@ -11,7 +11,7 @@
|
|||||||
"requirePragma": false,
|
"requirePragma": false,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"tabWidth": 2,
|
"tabWidth": 4,
|
||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"vueIndentScriptAndStyle": false,
|
"vueIndentScriptAndStyle": false,
|
||||||
|
72
build.js
72
build.js
@ -1,72 +0,0 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const builder = require('electron-builder')
|
|
||||||
const Platform = builder.Platform
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {import('electron-builder').Configuration}
|
|
||||||
*/
|
|
||||||
const options = {
|
|
||||||
appId: 'com.stratum.crunchyrolldownloader',
|
|
||||||
productName: 'Crunchyroll Downloader',
|
|
||||||
|
|
||||||
compression: 'maximum',
|
|
||||||
removePackageScripts: true,
|
|
||||||
|
|
||||||
nodeGypRebuild: true,
|
|
||||||
buildDependenciesFromSource: true,
|
|
||||||
|
|
||||||
publish: {
|
|
||||||
provider: 'github',
|
|
||||||
releaseType: 'release'
|
|
||||||
},
|
|
||||||
|
|
||||||
directories: {
|
|
||||||
output: 'crunchyroll-downloader-output-${version}'
|
|
||||||
},
|
|
||||||
|
|
||||||
win: {
|
|
||||||
artifactName: 'crunchyroll-downloader-${version}-windows-installer.${ext}',
|
|
||||||
icon: 'public/favicon.ico',
|
|
||||||
target: [
|
|
||||||
{
|
|
||||||
target: 'nsis',
|
|
||||||
arch: ['x64', 'ia32']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
nsis: {
|
|
||||||
deleteAppDataOnUninstall: true
|
|
||||||
},
|
|
||||||
mac: {
|
|
||||||
category: 'public.app-category.entertainment',
|
|
||||||
hardenedRuntime: false,
|
|
||||||
gatekeeperAssess: false,
|
|
||||||
target: [
|
|
||||||
{
|
|
||||||
target: 'default',
|
|
||||||
arch: ['x64', 'arm64']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
linux: {
|
|
||||||
maintainer: 'Stratum',
|
|
||||||
desktop: {
|
|
||||||
StartupNotify: 'false',
|
|
||||||
Encoding: 'UTF-8',
|
|
||||||
MimeType: 'x-scheme-handler/deeplink'
|
|
||||||
},
|
|
||||||
target: ['AppImage', 'rpm', 'deb']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const platform = 'WINDOWS'
|
|
||||||
builder
|
|
||||||
.build({
|
|
||||||
targets: Platform[platform].createTarget(),
|
|
||||||
config: options
|
|
||||||
})
|
|
||||||
.then((result) => {
|
|
||||||
console.log('----------------------------')
|
|
||||||
console.log('Platform:', platform)
|
|
||||||
console.log('Output:', JSON.stringify(result, null, 2))
|
|
||||||
})
|
|
72
build.ts
Normal file
72
build.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const builder = require('electron-builder')
|
||||||
|
const Platform = builder.Platform
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import('electron-builder').Configuration}
|
||||||
|
*/
|
||||||
|
const options = {
|
||||||
|
appId: 'com.stratum.crunchyrolldownloader',
|
||||||
|
productName: 'Crunchyroll Downloader',
|
||||||
|
|
||||||
|
compression: 'maximum',
|
||||||
|
removePackageScripts: true,
|
||||||
|
|
||||||
|
nodeGypRebuild: true,
|
||||||
|
buildDependenciesFromSource: true,
|
||||||
|
|
||||||
|
publish: {
|
||||||
|
provider: 'github',
|
||||||
|
releaseType: 'release'
|
||||||
|
},
|
||||||
|
|
||||||
|
directories: {
|
||||||
|
output: 'crunchyroll-downloader-output-${version}'
|
||||||
|
},
|
||||||
|
|
||||||
|
win: {
|
||||||
|
artifactName: 'crunchyroll-downloader-${version}-windows-installer.${ext}',
|
||||||
|
icon: 'public/favicon.ico',
|
||||||
|
target: [
|
||||||
|
{
|
||||||
|
target: 'nsis',
|
||||||
|
arch: ['x64', 'ia32']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
nsis: {
|
||||||
|
deleteAppDataOnUninstall: true
|
||||||
|
},
|
||||||
|
mac: {
|
||||||
|
category: 'public.app-category.entertainment',
|
||||||
|
hardenedRuntime: false,
|
||||||
|
gatekeeperAssess: false,
|
||||||
|
target: [
|
||||||
|
{
|
||||||
|
target: 'default',
|
||||||
|
arch: ['x64', 'arm64']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
linux: {
|
||||||
|
maintainer: 'Stratum',
|
||||||
|
desktop: {
|
||||||
|
StartupNotify: 'false',
|
||||||
|
Encoding: 'UTF-8',
|
||||||
|
MimeType: 'x-scheme-handler/deeplink'
|
||||||
|
},
|
||||||
|
target: ['AppImage', 'rpm', 'deb']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const platform = 'WINDOWS'
|
||||||
|
builder
|
||||||
|
.build({
|
||||||
|
targets: Platform[platform].createTarget(),
|
||||||
|
config: options
|
||||||
|
})
|
||||||
|
.then((result: any) => {
|
||||||
|
console.log('----------------------------')
|
||||||
|
console.log('Platform:', platform)
|
||||||
|
console.log('Output:', JSON.stringify(result, null, 2))
|
||||||
|
})
|
@ -1,19 +1,16 @@
|
|||||||
import type { ADNSearchFetch } from "./Types";
|
import type { ADNSearchFetch } from './Types'
|
||||||
|
|
||||||
export async function searchADN(q: string) {
|
export async function searchADN(q: string) {
|
||||||
const { data: deData, error: deError } = await useFetch<ADNSearchFetch>(
|
const { data: deData, error: deError } = await useFetch<ADNSearchFetch>(`https://gw.api.animationdigitalnetwork.fr/show/catalog`, {
|
||||||
`https://gw.api.animationdigitalnetwork.fr/show/catalog`,
|
method: 'GET',
|
||||||
{
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
headers: {
|
||||||
"x-target-distribution": 'de',
|
'x-target-distribution': 'de'
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
"maxAgeCategory": "18",
|
maxAgeCategory: '18',
|
||||||
"search": q
|
search: q
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
);
|
|
||||||
|
|
||||||
if (deError.value) {
|
if (deError.value) {
|
||||||
throw new Error(deError.value?.data.message as string)
|
throw new Error(deError.value?.data.message as string)
|
||||||
@ -21,19 +18,16 @@ export async function searchADN(q: string) {
|
|||||||
|
|
||||||
if (!deData.value) return
|
if (!deData.value) return
|
||||||
|
|
||||||
const { data: frData, error: frError } = await useFetch<ADNSearchFetch>(
|
const { data: frData, error: frError } = await useFetch<ADNSearchFetch>(`https://gw.api.animationdigitalnetwork.fr/show/catalog`, {
|
||||||
`https://gw.api.animationdigitalnetwork.fr/show/catalog`,
|
method: 'GET',
|
||||||
{
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
headers: {
|
||||||
"x-target-distribution": 'fr',
|
'x-target-distribution': 'fr'
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
"maxAgeCategory": "18",
|
maxAgeCategory: '18',
|
||||||
"search": q
|
search: q
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
);
|
|
||||||
|
|
||||||
if (frError.value) {
|
if (frError.value) {
|
||||||
throw new Error(frError.value?.data.message as string)
|
throw new Error(frError.value?.data.message as string)
|
||||||
@ -41,22 +35,24 @@ export async function searchADN(q: string) {
|
|||||||
|
|
||||||
if (!frData.value) return
|
if (!frData.value) return
|
||||||
|
|
||||||
const deShows = deData.value.shows;
|
const deShows = deData.value.shows
|
||||||
const frShows = frData.value.shows;
|
const frShows = frData.value.shows
|
||||||
|
|
||||||
const mergeLanguagesOfDuplicates = (shows: {
|
const mergeLanguagesOfDuplicates = (
|
||||||
|
shows: {
|
||||||
id: number
|
id: number
|
||||||
url: string
|
url: string
|
||||||
title: string
|
title: string
|
||||||
image2x: string
|
image2x: string
|
||||||
episodeCount: number,
|
episodeCount: number
|
||||||
languages: Array<string>
|
languages: Array<string>
|
||||||
}[]) => {
|
}[]
|
||||||
shows.forEach(show => {
|
) => {
|
||||||
const existingShow = shows.find(s => s.id === show.id);
|
shows.forEach((show) => {
|
||||||
|
const existingShow = shows.find((s) => s.id === show.id)
|
||||||
if (existingShow) {
|
if (existingShow) {
|
||||||
const existingShowIndex = shows.findIndex(s=> s === existingShow);
|
const existingShowIndex = shows.findIndex((s) => s === existingShow)
|
||||||
const rawLanguages = [...show.languages, ...existingShow.languages];
|
const rawLanguages = [...show.languages, ...existingShow.languages]
|
||||||
const languages: Array<string> = []
|
const languages: Array<string> = []
|
||||||
|
|
||||||
for (const l of rawLanguages) {
|
for (const l of rawLanguages) {
|
||||||
@ -66,13 +62,13 @@ export async function searchADN(q: string) {
|
|||||||
}
|
}
|
||||||
show.languages = languages
|
show.languages = languages
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
return shows;
|
return shows
|
||||||
};
|
}
|
||||||
|
|
||||||
const allShows = mergeLanguagesOfDuplicates([...deShows, ...frShows]);
|
const allShows = mergeLanguagesOfDuplicates([...deShows, ...frShows])
|
||||||
|
|
||||||
const unique = [...new Map(allShows.map((s) => [s.id, s])).values()];
|
const unique = [...new Map(allShows.map((s) => [s.id, s])).values()]
|
||||||
|
|
||||||
return unique
|
return unique
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ export async function getEpisodesWithShowIdADN(id: number, lang: 'de' | 'fr') {
|
|||||||
const { data, error } = await useFetch<ADNEpisodesFetch>(`https://gw.api.animationdigitalnetwork.fr/video/show/${id}?offset=0&limit=-1&order=asc`, {
|
const { data, error } = await useFetch<ADNEpisodesFetch>(`https://gw.api.animationdigitalnetwork.fr/video/show/${id}?offset=0&limit=-1&order=asc`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"x-target-distribution": lang,
|
'x-target-distribution': lang
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (error.value || !data.value) {
|
if (error.value || !data.value) {
|
||||||
|
@ -4,7 +4,7 @@ export interface ADNSearchFetch {
|
|||||||
url: string
|
url: string
|
||||||
title: string
|
title: string
|
||||||
image2x: string
|
image2x: string
|
||||||
episodeCount: number,
|
episodeCount: number
|
||||||
languages: Array<string>
|
languages: Array<string>
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
@ -14,69 +14,69 @@ export interface ADNEpisodesFetch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ADNEpisode {
|
export interface ADNEpisode {
|
||||||
id: number,
|
id: number
|
||||||
title: string,
|
title: string
|
||||||
name: string,
|
name: string
|
||||||
number: string,
|
number: string
|
||||||
shortNumber: string,
|
shortNumber: string
|
||||||
season: string,
|
season: string
|
||||||
reference: string,
|
reference: string
|
||||||
type: string,
|
type: string
|
||||||
order: number,
|
order: number
|
||||||
image: string,
|
image: string
|
||||||
image2x: string,
|
image2x: string
|
||||||
summary: string,
|
summary: string
|
||||||
releaseDate: string,
|
releaseDate: string
|
||||||
duration: number,
|
duration: number
|
||||||
url: string,
|
url: string
|
||||||
urlPath: string,
|
urlPath: string
|
||||||
embeddedUrl: string,
|
embeddedUrl: string
|
||||||
languages: Array<string>,
|
languages: Array<string>
|
||||||
qualities: Array<string>,
|
qualities: Array<string>
|
||||||
rating: number,
|
rating: number
|
||||||
ratingsCount: number,
|
ratingsCount: number
|
||||||
commentsCount: number,
|
commentsCount: number
|
||||||
available: boolean,
|
available: boolean
|
||||||
download: boolean,
|
download: boolean
|
||||||
free: boolean,
|
free: boolean
|
||||||
freeWithAds: boolean,
|
freeWithAds: boolean
|
||||||
show: {
|
show: {
|
||||||
id: number,
|
id: number
|
||||||
title: string,
|
title: string
|
||||||
type: string,
|
type: string
|
||||||
originalTitle: string,
|
originalTitle: string
|
||||||
shortTitle: string,
|
shortTitle: string
|
||||||
reference: string,
|
reference: string
|
||||||
age: string,
|
age: string
|
||||||
languages: Array<string>,
|
languages: Array<string>
|
||||||
summary: string,
|
summary: string
|
||||||
image: string,
|
image: string
|
||||||
image2x: string,
|
image2x: string
|
||||||
imageHorizontal: string,
|
imageHorizontal: string
|
||||||
imageHorizontal2x: string,
|
imageHorizontal2x: string
|
||||||
url: string,
|
url: string
|
||||||
urlPath: string,
|
urlPath: string
|
||||||
episodeCount: number,
|
episodeCount: number
|
||||||
genres: Array<string>,
|
genres: Array<string>
|
||||||
copyright: string,
|
copyright: string
|
||||||
rating: number,
|
rating: number
|
||||||
ratingsCount: number,
|
ratingsCount: number
|
||||||
commentsCount: number,
|
commentsCount: number
|
||||||
qualities: Array<string>,
|
qualities: Array<string>
|
||||||
simulcast: boolean,
|
simulcast: boolean
|
||||||
free: boolean,
|
free: boolean
|
||||||
available: boolean,
|
available: boolean
|
||||||
download: boolean,
|
download: boolean
|
||||||
basedOn: string,
|
basedOn: string
|
||||||
tagline: Array<string>,
|
tagline: Array<string>
|
||||||
firstReleaseYear: string,
|
firstReleaseYear: string
|
||||||
productionStudio: string,
|
productionStudio: string
|
||||||
countryOfOrigin: string,
|
countryOfOrigin: string
|
||||||
productionTeam: Array<{
|
productionTeam: Array<{
|
||||||
role: string,
|
role: string
|
||||||
name: string,
|
name: string
|
||||||
}>,
|
}>
|
||||||
nextVideoReleaseDate: string,
|
nextVideoReleaseDate: string
|
||||||
indexable: boolean
|
indexable: boolean
|
||||||
}
|
}
|
||||||
indexable: boolean
|
indexable: boolean
|
||||||
|
@ -1,70 +1,72 @@
|
|||||||
export interface CrunchyEpisode {
|
export interface CrunchyEpisode {
|
||||||
closed_captions_available: boolean,
|
closed_captions_available: boolean
|
||||||
availability_notes: string,
|
availability_notes: string
|
||||||
next_episode_title: string,
|
next_episode_title: string
|
||||||
upload_date: string,
|
upload_date: string
|
||||||
versions: Array<{
|
versions: Array<{
|
||||||
audio_locale: string,
|
audio_locale: string
|
||||||
guid: string,
|
guid: string
|
||||||
is_premium_only: boolean,
|
is_premium_only: boolean
|
||||||
media_guid: string,
|
media_guid: string
|
||||||
original: boolean,
|
original: boolean
|
||||||
season_guid: string,
|
season_guid: string
|
||||||
variant: string
|
variant: string
|
||||||
}>,
|
}>
|
||||||
season_slug_title: string,
|
season_slug_title: string
|
||||||
series_title: string,
|
series_title: string
|
||||||
season_title: string,
|
season_title: string
|
||||||
sequence_number: number,
|
sequence_number: number
|
||||||
maturity_ratings: Array<string>,
|
maturity_ratings: Array<string>
|
||||||
slug_title: string,
|
slug_title: string
|
||||||
is_premium_only: boolean,
|
is_premium_only: boolean
|
||||||
availability_ends: string,
|
availability_ends: string
|
||||||
identifier: string,
|
identifier: string
|
||||||
recent_variant: string,
|
recent_variant: string
|
||||||
free_available_date: string,
|
free_available_date: string
|
||||||
subtitle_locales: Array<string>,
|
subtitle_locales: Array<string>
|
||||||
series_id: string,
|
series_id: string
|
||||||
mature_blocked: boolean,
|
mature_blocked: boolean
|
||||||
duration_ms: number,
|
duration_ms: number
|
||||||
availability_starts: string,
|
availability_starts: string
|
||||||
audio_locale: string,
|
audio_locale: string
|
||||||
images: {
|
images: {
|
||||||
thumbnail: Array<Array<{
|
thumbnail: Array<
|
||||||
height: number,
|
Array<{
|
||||||
source: string,
|
height: number
|
||||||
type: string,
|
source: string
|
||||||
|
type: string
|
||||||
width: number
|
width: number
|
||||||
}>>
|
}>
|
||||||
},
|
>
|
||||||
season_sequence_number: number,
|
}
|
||||||
season_id: string,
|
season_sequence_number: number
|
||||||
episode_number: number,
|
season_id: string
|
||||||
listing_id: string,
|
episode_number: number
|
||||||
available_date: string,
|
listing_id: string
|
||||||
channel_id: string,
|
available_date: string
|
||||||
season_number: number,
|
channel_id: string
|
||||||
hd_flag: boolean,
|
season_number: number
|
||||||
recent_audio_locale: string,
|
hd_flag: boolean
|
||||||
available_offline: boolean,
|
recent_audio_locale: string
|
||||||
episode: string,
|
available_offline: boolean
|
||||||
is_subbed: boolean,
|
episode: string
|
||||||
media_type: string,
|
is_subbed: boolean
|
||||||
is_clip: boolean,
|
media_type: string
|
||||||
title: string,
|
is_clip: boolean
|
||||||
streams_link: string,
|
title: string
|
||||||
slug: string,
|
streams_link: string
|
||||||
id: string,
|
slug: string
|
||||||
production_episode_id: string,
|
id: string
|
||||||
is_dubbed: boolean,
|
production_episode_id: string
|
||||||
next_episode_id: string,
|
is_dubbed: boolean
|
||||||
series_slug_title: string,
|
next_episode_id: string
|
||||||
season_tags: Array<string>,
|
series_slug_title: string
|
||||||
premium_date: string,
|
season_tags: Array<string>
|
||||||
is_mature: boolean,
|
premium_date: string
|
||||||
premium_available_date: string,
|
is_mature: boolean
|
||||||
description: string,
|
premium_available_date: string
|
||||||
episode_air_date: string,
|
description: string
|
||||||
|
episode_air_date: string
|
||||||
eligible_region: string
|
eligible_region: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fixed w-full flex flex-row px-2 bg-[#11111189] h-14 z-10 gap-1" style="-webkit-app-region: drag">
|
<div class="fixed w-full flex flex-row px-2 bg-[#11111189] h-14 z-10 gap-1" style="-webkit-app-region: drag">
|
||||||
<div class="w-full flex gap-10 flex-row items-center justify-center px-5">
|
<div class="w-full flex gap-10 flex-row items-center justify-center px-5">
|
||||||
<button @click="openAddAnime" class="flex items-center justify-center px-2 py-2 gap-1 transition-all bg-[#ffffff16] hover:bg-[#ffffff25] rounded-lg select-none" style="-webkit-app-region: no-drag">
|
<button
|
||||||
|
@click="openAddAnime"
|
||||||
|
class="flex items-center justify-center px-2 py-2 gap-1 transition-all bg-[#ffffff16] hover:bg-[#ffffff25] rounded-lg select-none"
|
||||||
|
style="-webkit-app-region: no-drag"
|
||||||
|
>
|
||||||
<Icon name="ph:plus-bold" class="h-3.5 w-3.5 text-white" />
|
<Icon name="ph:plus-bold" class="h-3.5 w-3.5 text-white" />
|
||||||
<div class="text-[11px] text-white font-dm">
|
<div class="text-[11px] text-white font-dm"> ADD DOWNLOAD </div>
|
||||||
ADD DOWNLOAD
|
|
||||||
</div>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex flex-row items-center justify-center">
|
<div class="w-full flex flex-row items-center justify-center">
|
||||||
<img src="/logo.png" class="h-8">
|
<img src="/logo.png" class="h-8" />
|
||||||
<div class="text-[10px] leading-[10px] text-opacity-90 text-white select-none">Crunchyroll <br> Downloader</div>
|
<div class="text-[10px] leading-[10px] text-opacity-90 text-white select-none"
|
||||||
|
>Crunchyroll <br />
|
||||||
|
Downloader</div
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex gap-2 flex-row items-center justify-center">
|
<div class="w-full flex gap-2 flex-row items-center justify-center">
|
||||||
<!-- <button class="flex items-center justify-center px-2 py-2 gap-1 transition-all bg-[#ffffff16] hover:bg-[#ffffff25] rounded-lg select-none" style="-webkit-app-region: no-drag">
|
<!-- <button class="flex items-center justify-center px-2 py-2 gap-1 transition-all bg-[#ffffff16] hover:bg-[#ffffff25] rounded-lg select-none" style="-webkit-app-region: no-drag">
|
||||||
@ -19,11 +24,13 @@
|
|||||||
PLAYLIST
|
PLAYLIST
|
||||||
</div>
|
</div>
|
||||||
</button> -->
|
</button> -->
|
||||||
<button @click="openSettings" class="flex items-center justify-center px-2 py-2 gap-1 transition-all bg-[#ffffff16] hover:bg-[#ffffff25] rounded-lg select-none" style="-webkit-app-region: no-drag">
|
<button
|
||||||
|
@click="openSettings"
|
||||||
|
class="flex items-center justify-center px-2 py-2 gap-1 transition-all bg-[#ffffff16] hover:bg-[#ffffff25] rounded-lg select-none"
|
||||||
|
style="-webkit-app-region: no-drag"
|
||||||
|
>
|
||||||
<Icon name="ic:round-settings" class="h-3.5 w-3.5 text-white" />
|
<Icon name="ic:round-settings" class="h-3.5 w-3.5 text-white" />
|
||||||
<div class="text-[11px] text-white font-dm">
|
<div class="text-[11px] text-white font-dm"> SETTINGS </div>
|
||||||
SETTINGS
|
|
||||||
</div>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -36,12 +43,12 @@ import { openNewWindow } from './Functions/WindowHandler'
|
|||||||
const isProduction = process.env.NODE_ENV !== 'development'
|
const isProduction = process.env.NODE_ENV !== 'development'
|
||||||
|
|
||||||
async function openSettings() {
|
async function openSettings() {
|
||||||
(window as any).myAPI.openWindow({
|
;(window as any).myAPI.openWindow({
|
||||||
title: "Settings",
|
title: 'Settings',
|
||||||
url: isProduction ? 'http://localhost:8079/settings' : 'http://localhost:3000/settings',
|
url: isProduction ? 'http://localhost:8079/settings' : 'http://localhost:3000/settings',
|
||||||
width: 600,
|
width: 600,
|
||||||
height: 700,
|
height: 700,
|
||||||
backgroundColor: "#111111"
|
backgroundColor: '#111111'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,12 +66,12 @@ async function openAddAnime() {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
(window as any).myAPI.openWindow({
|
;(window as any).myAPI.openWindow({
|
||||||
title: "Add Anime",
|
title: 'Add Anime',
|
||||||
url: isProduction ? 'http://localhost:8079/addanime' : 'http://localhost:3000/addanime',
|
url: isProduction ? 'http://localhost:8079/addanime' : 'http://localhost:3000/addanime',
|
||||||
width: 700,
|
width: 700,
|
||||||
height: 450,
|
height: 450,
|
||||||
backgroundColor: "#111111"
|
backgroundColor: '#111111'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="fixed bottom-3 right-5 p-3 flex flex-col bg-[#111111dc] w-80 min-h-24 rounded-xl font-dm text-white transition-all duration-300"
|
class="fixed bottom-3 right-5 p-3 flex flex-col bg-[#111111dc] w-80 min-h-24 rounded-xl font-dm text-white transition-all duration-300"
|
||||||
:class="data?.status === 'update-available' && !ignoreUpdate || data?.status === 'downloading' || data?.status === 'update-downloaded' ? 'opacity-100' : 'opacity-0 pointer-events-none'"
|
:class="
|
||||||
|
(data?.status === 'update-available' && !ignoreUpdate) || data?.status === 'downloading' || data?.status === 'update-downloaded'
|
||||||
|
? 'opacity-100'
|
||||||
|
: 'opacity-0 pointer-events-none'
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<button @click="ignoreUpdate = true" class="absolute right-3 top-2">
|
<button @click="ignoreUpdate = true" class="absolute right-3 top-2">
|
||||||
<Icon name="akar-icons:cross" class="h-4 w-4 text-white" />
|
<Icon name="akar-icons:cross" class="h-4 w-4 text-white" />
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
"transpile-src": "tsc -p ./src --outDir .output/src",
|
"transpile-src": "tsc -p ./src --outDir .output/src",
|
||||||
"dev:electron": "NODE_ENV=development concurrently --kill-others \"nuxt dev\" \"tsc-watch -p ./src --outDir .output/src --onSuccess 'electron ./.output/src/electron/background.js'\"",
|
"dev:electron": "NODE_ENV=development concurrently --kill-others \"nuxt dev\" \"tsc-watch -p ./src --outDir .output/src --onSuccess 'electron ./.output/src/electron/background.js'\"",
|
||||||
"dev:electron:win": "set NODE_ENV=development& concurrently --kill-others \"nuxt dev\" \"tsc-watch -p ./src --outDir .output/src --onSuccess run.electron\"",
|
"dev:electron:win": "set NODE_ENV=development& concurrently --kill-others \"nuxt dev\" \"tsc-watch -p ./src --outDir .output/src --onSuccess run.electron\"",
|
||||||
"build:electron": "pnpm build && pnpm transpile-src && node build.js"
|
"build:electron": "pnpm build && pnpm transpile-src && node build.ts",
|
||||||
|
"prettier:fix": "pnpm prettier src --write && pnpm prettier components --write && pnpm prettier pages --write && pnpm prettier build.ts --write"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"7zip-bin": "^5.2.0",
|
"7zip-bin": "^5.2.0",
|
||||||
@ -27,12 +28,11 @@
|
|||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"electron": "^30.0.1",
|
"electron": "^30.0.1",
|
||||||
"electron-builder": "^24.13.3",
|
"electron-builder": "^24.13.3",
|
||||||
"eslint": "^8.57.0",
|
|
||||||
"eslint-config-prettier": "^8.10.0",
|
"eslint-config-prettier": "^8.10.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"nuxt": "^3.11.2",
|
"nuxt": "^3.11.2",
|
||||||
"nuxt-icon": "^0.6.10",
|
"nuxt-icon": "^0.6.10",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.75.0",
|
"sass": "^1.75.0",
|
||||||
"sass-loader": "^13.3.3",
|
"sass-loader": "^13.3.3",
|
||||||
"tsc-watch": "^6.2.0",
|
"tsc-watch": "^6.2.0",
|
||||||
|
@ -20,13 +20,11 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(isLoggedInCR && service === 'crunchyroll') || (isLoggedInADN && service === 'adn')" class="relative flex flex-col">
|
<div v-if="(isLoggedInCR && service === 'crunchyroll') || (isLoggedInADN && service === 'adn')" class="relative flex flex-col">
|
||||||
<input
|
<input v-model="search" @input="handleInputChange" placeholder="SEARCH" class="bg-[#5c5b5b] focus:outline-none px-3 py-3 rounded-xl text-sm text-center" />
|
||||||
v-model="search"
|
<div
|
||||||
@input="handleInputChange"
|
class="absolute top-full left-0 h-28 w-full bg-[#868585] rounded-xl z-10 flex items-center justify-center transition-all duration-300"
|
||||||
placeholder="SEARCH"
|
:class="isFetchingResults ? 'opacity-100' : 'opacity-0 pointer-events-none'"
|
||||||
class="bg-[#5c5b5b] focus:outline-none px-3 py-3 rounded-xl text-sm text-center"
|
>
|
||||||
/>
|
|
||||||
<div class="absolute top-full left-0 h-28 w-full bg-[#868585] rounded-xl z-10 flex items-center justify-center transition-all duration-300" :class="isFetchingResults ? 'opacity-100' : 'opacity-0 pointer-events-none'">
|
|
||||||
<Icon name="mdi:loading" class="h-8 w-8 animate-spin" />
|
<Icon name="mdi:loading" class="h-8 w-8 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@ -258,7 +256,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row gap-3">
|
<div class="flex flex-row gap-3">
|
||||||
<div v-if="service === 'crunchyroll'" class="relative flex flex-col w-full">
|
<div v-if="service === 'crunchyroll'" class="relative flex flex-col w-full">
|
||||||
<select v-model="hardsub" name="episode" class="bg-[#5c5b5b] focus:outline-none px-3 py-2 rounded-xl text-sm text-center cursor-pointer" :disabled="isHardsubDisabled">
|
<select
|
||||||
|
v-model="hardsub"
|
||||||
|
name="episode"
|
||||||
|
class="bg-[#5c5b5b] focus:outline-none px-3 py-2 rounded-xl text-sm text-center cursor-pointer"
|
||||||
|
:disabled="isHardsubDisabled"
|
||||||
|
>
|
||||||
<option :value="false" class="text-sm text-slate-200">Hardsub: false</option>
|
<option :value="false" class="text-sm text-slate-200">Hardsub: false</option>
|
||||||
<option :value="true" class="text-sm text-slate-200">Hardsub: true</option>
|
<option :value="true" class="text-sm text-slate-200">Hardsub: true</option>
|
||||||
</select>
|
</select>
|
||||||
@ -788,23 +791,24 @@ const addToPlaylistADN = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.font-dm {
|
.font-dm {
|
||||||
font-family: "DM Sans", sans-serif;
|
font-family: 'DM Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-protest {
|
.font-protest {
|
||||||
font-family: "Protest Riot", sans-serif;
|
font-family: 'Protest Riot', sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-dm-big {
|
.font-dm-big {
|
||||||
font-family: "DM Sans", sans-serif;
|
font-family: 'DM Sans', sans-serif;
|
||||||
font-weight: 1000;
|
font-weight: 1000;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
background: url("data:image/svg+xml,<svg height='10px' width='10px' viewBox='0 0 16 16' fill='%23000000' xmlns='http://www.w3.org/2000/svg'><path d='M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/></svg>") no-repeat;
|
background: url("data:image/svg+xml,<svg height='10px' width='10px' viewBox='0 0 16 16' fill='%23000000' xmlns='http://www.w3.org/2000/svg'><path d='M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/></svg>")
|
||||||
|
no-repeat;
|
||||||
background-position: calc(100% - 0.75rem) center !important;
|
background-position: calc(100% - 0.75rem) center !important;
|
||||||
background-color: #5c5b5b;
|
background-color: #5c5b5b;
|
||||||
-moz-appearance: none !important;
|
-moz-appearance: none !important;
|
||||||
|
@ -58,17 +58,17 @@ const login = async () => {
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.font-dm {
|
.font-dm {
|
||||||
font-family: "DM Sans", sans-serif;
|
font-family: 'DM Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-protest {
|
.font-protest {
|
||||||
font-family: "Protest Riot", sans-serif;
|
font-family: 'Protest Riot', sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-dm-big {
|
.font-dm-big {
|
||||||
font-family: "DM Sans", sans-serif;
|
font-family: 'DM Sans', sans-serif;
|
||||||
font-weight: 1000;
|
font-weight: 1000;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
@ -58,17 +58,17 @@ const login = async () => {
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.font-dm {
|
.font-dm {
|
||||||
font-family: "DM Sans", sans-serif;
|
font-family: 'DM Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-protest {
|
.font-protest {
|
||||||
font-family: "Protest Riot", sans-serif;
|
font-family: 'Protest Riot', sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-dm-big {
|
.font-dm-big {
|
||||||
font-family: "DM Sans", sans-serif;
|
font-family: 'DM Sans', sans-serif;
|
||||||
font-weight: 1000;
|
font-weight: 1000;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@
|
|||||||
Delete Playlist
|
Delete Playlist
|
||||||
</button> -->
|
</button> -->
|
||||||
<div v-for="p in playlist" class="relative flex flex-row gap-4 min-h-36 bg-[#63636383] rounded-xl font-dm overflow-hidden">
|
<div v-for="p in playlist" class="relative flex flex-row gap-4 min-h-36 bg-[#63636383] rounded-xl font-dm overflow-hidden">
|
||||||
<div class="absolute top-0 left-0 w-full h-full bg-[#a1a1a141] transition-all duration-300" :style="`width: calc((${p.partsdownloaded} / ${p.partsleft}) * 100%);`"></div>
|
<div
|
||||||
|
class="absolute top-0 left-0 w-full h-full bg-[#a1a1a141] transition-all duration-300"
|
||||||
|
:style="`width: calc((${p.partsdownloaded} / ${p.partsleft}) * 100%);`"
|
||||||
|
></div>
|
||||||
<div class="absolute h-full w-full flex flex-row gap-3 p-3.5">
|
<div class="absolute h-full w-full flex flex-row gap-3 p-3.5">
|
||||||
<div v-if="p.service === 'CR'" class="flex w-48 min-w-48">
|
<div v-if="p.service === 'CR'" class="flex w-48 min-w-48">
|
||||||
<img :src="(p.media as CrunchyEpisode).images.thumbnail[0].find((p) => p.height === 1080)?.source" alt="Image" class="object-cover rounded-lg" />
|
<img :src="(p.media as CrunchyEpisode).images.thumbnail[0].find((p) => p.height === 1080)?.source" alt="Image" class="object-cover rounded-lg" />
|
||||||
@ -44,7 +47,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="p.service === 'CR'" class="text-base capitalize h-full flex items-center">
|
<div v-if="p.service === 'CR'" class="text-base capitalize h-full flex items-center">
|
||||||
{{ (p.media as CrunchyEpisode).series_title }} Season {{ (p.media as CrunchyEpisode).season_number }} Episode {{ (p.media as CrunchyEpisode).episode_number }}
|
{{ (p.media as CrunchyEpisode).series_title }} Season {{ (p.media as CrunchyEpisode).season_number }} Episode
|
||||||
|
{{ (p.media as CrunchyEpisode).episode_number }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="p.service === 'ADN'" class="text-base capitalize h-full">
|
<div v-if="p.service === 'ADN'" class="text-base capitalize h-full">
|
||||||
{{ (p.media as ADNEpisode).show.title }} Season {{ (p.media as ADNEpisode).season ? (p.media as ADNEpisode).season : 1 }} Episode
|
{{ (p.media as ADNEpisode).show.title }} Season {{ (p.media as ADNEpisode).season ? (p.media as ADNEpisode).season : 1 }} Episode
|
||||||
|
1760
pnpm-lock.yaml
1760
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
|||||||
@echo off
|
|
||||||
wait-on http://localhost:3000 && electron ./.output/src/electron/background.js
|
|
@ -1,46 +1,45 @@
|
|||||||
import fastify from "fastify";
|
import fastify from 'fastify'
|
||||||
import cors from "@fastify/cors";
|
import cors from '@fastify/cors'
|
||||||
import NodeCache from "node-cache";
|
import NodeCache from 'node-cache'
|
||||||
import crunchyrollRoutes from "./routes/crunchyroll/crunchyroll.route";
|
import crunchyrollRoutes from './routes/crunchyroll/crunchyroll.route'
|
||||||
import { sequelize } from "./db/database";
|
import { sequelize } from './db/database'
|
||||||
import serviceRoutes from "./routes/service/service.route";
|
import serviceRoutes from './routes/service/service.route'
|
||||||
|
;(async () => {
|
||||||
(async () => {
|
|
||||||
try {
|
try {
|
||||||
await sequelize.authenticate();
|
await sequelize.authenticate()
|
||||||
console.log("Connection has been established successfully.");
|
console.log('Connection has been established successfully.')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Unable to connect to the database:", error);
|
console.error('Unable to connect to the database:', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sequelize.sync();
|
await sequelize.sync()
|
||||||
console.log("All models were synchronized successfully.");
|
console.log('All models were synchronized successfully.')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Failed to synchronize Models");
|
console.log('Failed to synchronize Models')
|
||||||
}
|
}
|
||||||
})();
|
})()
|
||||||
|
|
||||||
const CacheController = new NodeCache({ stdTTL: 100, checkperiod: 120 });
|
const CacheController = new NodeCache({ stdTTL: 100, checkperiod: 120 })
|
||||||
|
|
||||||
export const server = fastify();
|
export const server = fastify()
|
||||||
|
|
||||||
// Cors registration
|
// Cors registration
|
||||||
server.register(cors, {
|
server.register(cors, {
|
||||||
origin: "*",
|
origin: '*',
|
||||||
methods: ["GET", "POST", "PUT", "DELETE"],
|
methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
||||||
allowedHeaders: ["Content-Type", "Authorization"],
|
allowedHeaders: ['Content-Type', 'Authorization']
|
||||||
});
|
})
|
||||||
|
|
||||||
// Cache Controller Type
|
// Cache Controller Type
|
||||||
declare module "fastify" {
|
declare module 'fastify' {
|
||||||
interface FastifyInstance {
|
interface FastifyInstance {
|
||||||
CacheController: NodeCache;
|
CacheController: NodeCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache Controller
|
// Cache Controller
|
||||||
server.decorate("CacheController", CacheController);
|
server.decorate('CacheController', CacheController)
|
||||||
|
|
||||||
// Routes
|
// Routes
|
||||||
server.register(crunchyrollRoutes, { prefix: 'api/crunchyroll' })
|
server.register(crunchyrollRoutes, { prefix: 'api/crunchyroll' })
|
||||||
@ -49,11 +48,11 @@ server.register(serviceRoutes, { prefix: 'api/service' })
|
|||||||
function startAPI() {
|
function startAPI() {
|
||||||
server.listen({ port: 8080 }, (err, address) => {
|
server.listen({ port: 8080 }, (err, address) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
console.log(`Server is listening on ${address}`);
|
console.log(`Server is listening on ${address}`)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default startAPI;
|
export default startAPI
|
||||||
|
@ -36,8 +36,8 @@ interface PlaylistAttributes {
|
|||||||
hardsub: boolean
|
hardsub: boolean
|
||||||
quality: 1080 | 720 | 480 | 360 | 240
|
quality: 1080 | 720 | 480 | 360 | 240
|
||||||
dir: string
|
dir: string
|
||||||
failedreason: string,
|
failedreason: string
|
||||||
service: 'CR' | 'ADN',
|
service: 'CR' | 'ADN'
|
||||||
format: 'mp4' | 'mkv'
|
format: 'mp4' | 'mkv'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,8 +48,8 @@ interface PlaylistCreateAttributes {
|
|||||||
dir: string
|
dir: string
|
||||||
quality: 1080 | 720 | 480 | 360 | 240
|
quality: 1080 | 720 | 480 | 360 | 240
|
||||||
hardsub: boolean
|
hardsub: boolean
|
||||||
status: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'completed' | 'failed',
|
status: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'completed' | 'failed'
|
||||||
service: 'CR' | 'ADN',
|
service: 'CR' | 'ADN'
|
||||||
format: 'mp4' | 'mkv'
|
format: 'mp4' | 'mkv'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,6 @@ export async function getEpisodeADN(q: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getPlayerConfigADN(id: number, geo: 'de' | 'fr') {
|
export async function getPlayerConfigADN(id: number, geo: 'de' | 'fr') {
|
||||||
|
|
||||||
const account = await loggedInCheck('ADN')
|
const account = await loggedInCheck('ADN')
|
||||||
|
|
||||||
if (!account) return
|
if (!account) return
|
||||||
@ -216,7 +215,7 @@ export async function adnGetPlaylist(animeid: number, geo: 'de' | 'fr') {
|
|||||||
const data: ADNLink = await JSON.parse(await response.text())
|
const data: ADNLink = await JSON.parse(await response.text())
|
||||||
return { data: data, secret: token.random }
|
return { data: data, secret: token.random }
|
||||||
} else {
|
} else {
|
||||||
const data: { message: string, code: string, statusCode: string} = JSON.parse(await response.text())
|
const data: { message: string; code: string; statusCode: string } = JSON.parse(await response.text())
|
||||||
|
|
||||||
messageBox('error', ['Cancel'], 2, 'Failed to fetch Playlist', 'Failed to fetch ADN Playlist', `${data.message} - ${data.code}`)
|
messageBox('error', ['Cancel'], 2, 'Failed to fetch Playlist', 'Failed to fetch ADN Playlist', `${data.message} - ${data.code}`)
|
||||||
|
|
||||||
@ -230,14 +229,14 @@ export async function adnGetPlaylist(animeid: number, geo: 'de' | 'fr') {
|
|||||||
export async function adnGetM3U8Playlist(url: string) {
|
export async function adnGetM3U8Playlist(url: string) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET'
|
||||||
})
|
})
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data: { location: string } = await JSON.parse(await response.text())
|
const data: { location: string } = await JSON.parse(await response.text())
|
||||||
|
|
||||||
const mu8 = await fetch(data.location, {
|
const mu8 = await fetch(data.location, {
|
||||||
method: 'GET',
|
method: 'GET'
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = await mu8.text()
|
const playlist = await mu8.text()
|
||||||
@ -245,12 +244,12 @@ export async function adnGetM3U8Playlist(url: string) {
|
|||||||
const url = await extractURLFromPlaylist(playlist)
|
const url = await extractURLFromPlaylist(playlist)
|
||||||
|
|
||||||
const partsraw = await fetch(url, {
|
const partsraw = await fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET'
|
||||||
})
|
})
|
||||||
|
|
||||||
const parts = await partsraw.text()
|
const parts = await partsraw.text()
|
||||||
|
|
||||||
const baseurl = await extractBaseURL(url);
|
const baseurl = await extractBaseURL(url)
|
||||||
|
|
||||||
const partsArray = await extractSequenceURLs(parts, baseurl)
|
const partsArray = await extractSequenceURLs(parts, baseurl)
|
||||||
|
|
||||||
@ -262,26 +261,26 @@ export async function adnGetM3U8Playlist(url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function extractURLFromPlaylist(playlist: string) {
|
async function extractURLFromPlaylist(playlist: string) {
|
||||||
var startIndex = playlist.indexOf("http");
|
var startIndex = playlist.indexOf('http')
|
||||||
var endIndex = playlist.indexOf(" ", startIndex);
|
var endIndex = playlist.indexOf(' ', startIndex)
|
||||||
var extractedURL = playlist.slice(startIndex, endIndex);
|
var extractedURL = playlist.slice(startIndex, endIndex)
|
||||||
return extractedURL;
|
return extractedURL
|
||||||
}
|
}
|
||||||
|
|
||||||
async function extractBaseURL(playlistURL: string) {
|
async function extractBaseURL(playlistURL: string) {
|
||||||
var baseURL = playlistURL.substring(0, playlistURL.lastIndexOf("/") + 1);
|
var baseURL = playlistURL.substring(0, playlistURL.lastIndexOf('/') + 1)
|
||||||
return baseURL;
|
return baseURL
|
||||||
}
|
}
|
||||||
|
|
||||||
async function extractSequenceURLs(playlistText: string, baseURL: string) {
|
async function extractSequenceURLs(playlistText: string, baseURL: string) {
|
||||||
var sequenceURLs: Array<{ filename: string, url: string }> = [];
|
var sequenceURLs: Array<{ filename: string; url: string }> = []
|
||||||
var matches = playlistText.match(/sequence_\d+\.ts/g);
|
var matches = playlistText.match(/sequence_\d+\.ts/g)
|
||||||
if (matches) {
|
if (matches) {
|
||||||
matches.forEach(function (match) {
|
matches.forEach(function (match) {
|
||||||
sequenceURLs.push({ filename: match, url: baseURL + match });
|
sequenceURLs.push({ filename: match, url: baseURL + match })
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
return sequenceURLs;
|
return sequenceURLs
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseSubs(url: string, secret: string) {
|
export async function parseSubs(url: string, secret: string) {
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
import { FastifyReply, FastifyRequest } from "fastify"
|
import { FastifyReply, FastifyRequest } from 'fastify'
|
||||||
import { crunchyLogin } from "../crunchyroll/crunchyroll.service"
|
import { crunchyLogin } from '../crunchyroll/crunchyroll.service'
|
||||||
import { addEpisodeToPlaylist, getDownloading, getPlaylist, loggedInCheck, safeLoginData } from "./service.service"
|
import { addEpisodeToPlaylist, getDownloading, getPlaylist, loggedInCheck, safeLoginData } from './service.service'
|
||||||
import { CrunchyEpisodes } from "../../types/crunchyroll"
|
import { CrunchyEpisodes } from '../../types/crunchyroll'
|
||||||
import { adnLogin } from "../adn/adn.service"
|
import { adnLogin } from '../adn/adn.service'
|
||||||
|
|
||||||
export async function checkLoginController(request: FastifyRequest<{
|
export async function checkLoginController(
|
||||||
|
request: FastifyRequest<{
|
||||||
Params: {
|
Params: {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
}>, reply: FastifyReply) {
|
}>,
|
||||||
|
reply: FastifyReply
|
||||||
|
) {
|
||||||
const account = await loggedInCheck(request.params.id)
|
const account = await loggedInCheck(request.params.id)
|
||||||
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
@ -23,7 +26,7 @@ export async function loginController(
|
|||||||
Body: {
|
Body: {
|
||||||
user: string
|
user: string
|
||||||
password: string
|
password: string
|
||||||
},
|
}
|
||||||
Params: {
|
Params: {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
@ -44,14 +47,12 @@ export async function loginController(
|
|||||||
|
|
||||||
if (params.id === 'CR') {
|
if (params.id === 'CR') {
|
||||||
const { data, error } = await crunchyLogin(body.user, body.password)
|
const { data, error } = await crunchyLogin(body.user, body.password)
|
||||||
responseError = error,
|
;(responseError = error), (responseData = data)
|
||||||
responseData = data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.id === 'ADN') {
|
if (params.id === 'ADN') {
|
||||||
const { data, error } = await adnLogin(body.user, body.password)
|
const { data, error } = await adnLogin(body.user, body.password)
|
||||||
responseError = error,
|
;(responseError = error), (responseData = data)
|
||||||
responseData = data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseError || !responseData) {
|
if (responseError || !responseData) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FastifyInstance } from "fastify"
|
import { FastifyInstance } from 'fastify'
|
||||||
import { addPlaylistController, checkLoginController, getPlaylistController, loginController } from "./service.controller"
|
import { addPlaylistController, checkLoginController, getPlaylistController, loginController } from './service.controller'
|
||||||
|
|
||||||
async function serviceRoutes(server: FastifyInstance) {
|
async function serviceRoutes(server: FastifyInstance) {
|
||||||
server.post(
|
server.post(
|
||||||
|
@ -290,14 +290,7 @@ export async function downloadADNPlaylist(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await mergeVideoFile(
|
await mergeVideoFile(file as string, [], subss, seasonFolder, `${name.replace(/[/\\?%*:|"<>]/g, '')} Season ${season} Episode ${episode}`, format)
|
||||||
file as string,
|
|
||||||
[],
|
|
||||||
subss,
|
|
||||||
seasonFolder,
|
|
||||||
`${name.replace(/[/\\?%*:|"<>]/g, '')} Season ${season} Episode ${episode}`,
|
|
||||||
format
|
|
||||||
)
|
|
||||||
|
|
||||||
await updatePlaylistByID(downloadID, 'completed')
|
await updatePlaylistByID(downloadID, 'completed')
|
||||||
|
|
||||||
|
@ -54,20 +54,20 @@ export async function deleteFolder(folderPath: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteTemporaryFolders() {
|
export async function deleteTemporaryFolders() {
|
||||||
const documentsPath = app.getPath('documents');
|
const documentsPath = app.getPath('documents')
|
||||||
const folderPrefix = 'crd-tmp-';
|
const folderPrefix = 'crd-tmp-'
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const files = await fs.promises.readdir(documentsPath);
|
const files = await fs.promises.readdir(documentsPath)
|
||||||
const tempFolders = files.filter(file => file.startsWith(folderPrefix));
|
const tempFolders = files.filter((file) => file.startsWith(folderPrefix))
|
||||||
|
|
||||||
for (const folder of tempFolders) {
|
for (const folder of tempFolders) {
|
||||||
const folderPath = path.join(documentsPath, folder);
|
const folderPath = path.join(documentsPath, folder)
|
||||||
await deleteFolder(folderPath);
|
await deleteFolder(folderPath)
|
||||||
console.log(`Temporary folder ${folder} deleted.`);
|
console.log(`Temporary folder ${folder} deleted.`)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting temporary folders:', error);
|
console.error('Error deleting temporary folders:', error)
|
||||||
throw error;
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,69 +76,69 @@ export interface ADNLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ADNEpisode {
|
export interface ADNEpisode {
|
||||||
id: number,
|
id: number
|
||||||
title: string,
|
title: string
|
||||||
name: string,
|
name: string
|
||||||
number: string,
|
number: string
|
||||||
shortNumber: string,
|
shortNumber: string
|
||||||
season: string,
|
season: string
|
||||||
reference: string,
|
reference: string
|
||||||
type: string,
|
type: string
|
||||||
order: number,
|
order: number
|
||||||
image: string,
|
image: string
|
||||||
image2x: string,
|
image2x: string
|
||||||
summary: string,
|
summary: string
|
||||||
releaseDate: string,
|
releaseDate: string
|
||||||
duration: number,
|
duration: number
|
||||||
url: string,
|
url: string
|
||||||
urlPath: string,
|
urlPath: string
|
||||||
embeddedUrl: string,
|
embeddedUrl: string
|
||||||
languages: Array<string>,
|
languages: Array<string>
|
||||||
qualities: Array<string>,
|
qualities: Array<string>
|
||||||
rating: number,
|
rating: number
|
||||||
ratingsCount: number,
|
ratingsCount: number
|
||||||
commentsCount: number,
|
commentsCount: number
|
||||||
available: boolean,
|
available: boolean
|
||||||
download: boolean,
|
download: boolean
|
||||||
free: boolean,
|
free: boolean
|
||||||
freeWithAds: boolean,
|
freeWithAds: boolean
|
||||||
show: {
|
show: {
|
||||||
id: number,
|
id: number
|
||||||
title: string,
|
title: string
|
||||||
type: string,
|
type: string
|
||||||
originalTitle: string,
|
originalTitle: string
|
||||||
shortTitle: string,
|
shortTitle: string
|
||||||
reference: string,
|
reference: string
|
||||||
age: string,
|
age: string
|
||||||
languages: Array<string>,
|
languages: Array<string>
|
||||||
summary: string,
|
summary: string
|
||||||
image: string,
|
image: string
|
||||||
image2x: string,
|
image2x: string
|
||||||
imageHorizontal: string,
|
imageHorizontal: string
|
||||||
imageHorizontal2x: string,
|
imageHorizontal2x: string
|
||||||
url: string,
|
url: string
|
||||||
urlPath: string,
|
urlPath: string
|
||||||
episodeCount: number,
|
episodeCount: number
|
||||||
genres: Array<string>,
|
genres: Array<string>
|
||||||
copyright: string,
|
copyright: string
|
||||||
rating: number,
|
rating: number
|
||||||
ratingsCount: number,
|
ratingsCount: number
|
||||||
commentsCount: number,
|
commentsCount: number
|
||||||
qualities: Array<string>,
|
qualities: Array<string>
|
||||||
simulcast: boolean,
|
simulcast: boolean
|
||||||
free: boolean,
|
free: boolean
|
||||||
available: boolean,
|
available: boolean
|
||||||
download: boolean,
|
download: boolean
|
||||||
basedOn: string,
|
basedOn: string
|
||||||
tagline: Array<string>,
|
tagline: Array<string>
|
||||||
firstReleaseYear: string,
|
firstReleaseYear: string
|
||||||
productionStudio: string,
|
productionStudio: string
|
||||||
countryOfOrigin: string,
|
countryOfOrigin: string
|
||||||
productionTeam: Array<{
|
productionTeam: Array<{
|
||||||
role: string,
|
role: string
|
||||||
name: string,
|
name: string
|
||||||
}>,
|
}>
|
||||||
nextVideoReleaseDate: string,
|
nextVideoReleaseDate: string
|
||||||
indexable: boolean
|
indexable: boolean
|
||||||
}
|
}
|
||||||
indexable: boolean
|
indexable: boolean
|
||||||
|
@ -2,7 +2,7 @@ import { BrowserWindow, ipcMain } from 'electron'
|
|||||||
import { autoUpdater } from 'electron-updater'
|
import { autoUpdater } from 'electron-updater'
|
||||||
import log from 'electron-log'
|
import log from 'electron-log'
|
||||||
|
|
||||||
var status: { status: string, info: any } = { status: "", info: null }
|
var status: { status: string; info: any } = { status: '', info: null }
|
||||||
|
|
||||||
autoUpdater.logger = log
|
autoUpdater.logger = log
|
||||||
;(autoUpdater.logger as typeof log).transports.file.level = 'info'
|
;(autoUpdater.logger as typeof log).transports.file.level = 'info'
|
||||||
@ -56,9 +56,12 @@ export default (mainWindow: BrowserWindow) => {
|
|||||||
|
|
||||||
autoUpdater.checkForUpdates()
|
autoUpdater.checkForUpdates()
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(
|
||||||
|
() => {
|
||||||
autoUpdater.checkForUpdates()
|
autoUpdater.checkForUpdates()
|
||||||
}, 1000 * 60 * 60 * 2)
|
},
|
||||||
|
1000 * 60 * 60 * 2
|
||||||
|
)
|
||||||
|
|
||||||
console.log('[-] MODULE::updater Initialized')
|
console.log('[-] MODULE::updater Initialized')
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,8 @@ import {contextBridge, ipcRenderer} from 'electron'
|
|||||||
contextBridge.exposeInMainWorld('myAPI', {
|
contextBridge.exposeInMainWorld('myAPI', {
|
||||||
selectFolder: () => ipcRenderer.invoke('dialog:openDirectory'),
|
selectFolder: () => ipcRenderer.invoke('dialog:openDirectory'),
|
||||||
getFolder: () => ipcRenderer.invoke('dialog:defaultDirectory'),
|
getFolder: () => ipcRenderer.invoke('dialog:defaultDirectory'),
|
||||||
openWindow: (opt: {
|
openWindow: (opt: { title: string; url: string; width: number; height: number; backgroundColor: string }) => ipcRenderer.invoke('window:openNewWindow', opt),
|
||||||
title: string,
|
|
||||||
url: string,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
backgroundColor: string
|
|
||||||
}) => ipcRenderer.invoke('window:openNewWindow', opt),
|
|
||||||
getUpdateStatus: () => ipcRenderer.invoke('updater:getUpdateStatus'),
|
getUpdateStatus: () => ipcRenderer.invoke('updater:getUpdateStatus'),
|
||||||
startUpdateDownload: () => ipcRenderer.invoke('updater:download'),
|
startUpdateDownload: () => ipcRenderer.invoke('updater:download'),
|
||||||
startUpdateInstall: () => ipcRenderer.invoke('updater:quitAndInstall'),
|
startUpdateInstall: () => ipcRenderer.invoke('updater:quitAndInstall')
|
||||||
})
|
})
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||||
|
|
||||||
/* Emit */
|
/* Emit */
|
||||||
"declaration": false, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
"declaration": false /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
|
||||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
{
|
{
|
||||||
// https://nuxt.com/docs/guide/concepts/typescript
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
"extends": "./.nuxt/tsconfig.json",
|
"extends": "./.nuxt/tsconfig.json",
|
||||||
"compilerOptions": {
|
|
||||||
"types": [
|
|
||||||
"@nuxtjs/i18n",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user