diff --git a/package.json b/package.json
index 0d7a518..9184e7b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ui",
- "version": "6.4.150",
+ "version": "6.4.151",
"license": "BUSL-1.1",
"private": true,
"packageManager": "pnpm@9.15.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0e21ccf..a5067b3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -185,7 +185,7 @@ importers:
version: 1.8.13(@gql.tada/svelte-support@1.0.1(svelte@4.2.19)(typescript@5.9.2))(graphql@16.10.0)(typescript@5.9.2)
hayase-extensions:
specifier: github:hayase-app/extensions
- version: https://codeload.github.com/hayase-app/extensions/tar.gz/0fad214a4a0aacd826c0801255ced65bd1d49a13
+ version: https://codeload.github.com/hayase-app/extensions/tar.gz/2c43ec0bf157733901be1ad9188b64933aac2e15
jassub:
specifier: ^1.8.6
version: 1.8.6
@@ -197,7 +197,7 @@ importers:
version: 2.1.3
native:
specifier: github:hayase-app/native
- version: https://codeload.github.com/hayase-app/native/tar.gz/b77747898ca7e4991fac752559ea159c8c0f5083
+ version: https://codeload.github.com/hayase-app/native/tar.gz/e8045ec8878086117a9c3b52dcff069f4b9b48e8
rollup-plugin-license:
specifier: ^3.6.0
version: 3.6.0(picomatch@4.0.3)(rollup@4.40.2)
@@ -1711,8 +1711,8 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
- hayase-extensions@https://codeload.github.com/hayase-app/extensions/tar.gz/0fad214a4a0aacd826c0801255ced65bd1d49a13:
- resolution: {tarball: https://codeload.github.com/hayase-app/extensions/tar.gz/0fad214a4a0aacd826c0801255ced65bd1d49a13}
+ hayase-extensions@https://codeload.github.com/hayase-app/extensions/tar.gz/2c43ec0bf157733901be1ad9188b64933aac2e15:
+ resolution: {tarball: https://codeload.github.com/hayase-app/extensions/tar.gz/2c43ec0bf157733901be1ad9188b64933aac2e15}
version: 1.0.6
idb-keyval@6.2.2:
@@ -2051,8 +2051,8 @@ packages:
engines: {node: ^18 || >=20}
hasBin: true
- native@https://codeload.github.com/hayase-app/native/tar.gz/b77747898ca7e4991fac752559ea159c8c0f5083:
- resolution: {tarball: https://codeload.github.com/hayase-app/native/tar.gz/b77747898ca7e4991fac752559ea159c8c0f5083}
+ native@https://codeload.github.com/hayase-app/native/tar.gz/e8045ec8878086117a9c3b52dcff069f4b9b48e8:
+ resolution: {tarball: https://codeload.github.com/hayase-app/native/tar.gz/e8045ec8878086117a9c3b52dcff069f4b9b48e8}
version: 1.0.0
natural-compare@1.4.0:
@@ -4560,7 +4560,7 @@ snapshots:
dependencies:
function-bind: 1.1.2
- hayase-extensions@https://codeload.github.com/hayase-app/extensions/tar.gz/0fad214a4a0aacd826c0801255ced65bd1d49a13: {}
+ hayase-extensions@https://codeload.github.com/hayase-app/extensions/tar.gz/2c43ec0bf157733901be1ad9188b64933aac2e15: {}
idb-keyval@6.2.2: {}
@@ -4865,7 +4865,7 @@ snapshots:
nanoid@5.1.5: {}
- native@https://codeload.github.com/hayase-app/native/tar.gz/b77747898ca7e4991fac752559ea159c8c0f5083: {}
+ native@https://codeload.github.com/hayase-app/native/tar.gz/e8045ec8878086117a9c3b52dcff069f4b9b48e8: {}
natural-compare@1.4.0: {}
diff --git a/src/app.html b/src/app.html
index 1533c15..89ff183 100644
--- a/src/app.html
+++ b/src/app.html
@@ -4,6 +4,8 @@
Hayase
+
+
%sveltekit.head%
diff --git a/src/lib/components/ui/torrentclient/peers/cells/country.svelte b/src/lib/components/ui/torrentclient/peers/cells/country.svelte
index bb48633..04f7784 100644
--- a/src/lib/components/ui/torrentclient/peers/cells/country.svelte
+++ b/src/lib/components/ui/torrentclient/peers/cells/country.svelte
@@ -13,5 +13,6 @@
{location.country}
+ {:catch}
{/await}
diff --git a/src/lib/modules/extensions/extensions.ts b/src/lib/modules/extensions/extensions.ts
index 2126c8d..8d1e8de 100644
--- a/src/lib/modules/extensions/extensions.ts
+++ b/src/lib/modules/extensions/extensions.ts
@@ -1,6 +1,7 @@
import anitomyscript, { type AnitomyResult } from 'anitomyscript'
import Debug from 'debug'
import { get } from 'svelte/store'
+import { toast } from 'svelte-sonner'
import { dedupeAiring, episodes, isMovie, type Media, getParentForSpecial, isSingleEpisode } from '../anilist'
import { episodes as _episodes } from '../anizip'
@@ -203,13 +204,14 @@ export const extensions = new class Extensions {
debug(`Checking ${Object.keys(workers).length} extensions for ${media.id}:${media.title?.userPreferred} ${episode} ${resolution} ${checkMovie ? 'movie' : ''} ${checkBatch ? 'batch' : ''}`)
for (const [id, worker] of Object.entries(workers)) {
- if (!extopts[id]!.enabled) continue
+ const thisExtOpts = extopts[id]!
+ if (!thisExtOpts.enabled) continue
if (configs[id]!.type !== 'torrent') continue
try {
const promises: Array> = []
- promises.push(worker.single(options))
- if (checkMovie) promises.push(worker.movie(options))
- if (checkBatch) promises.push(worker.batch(options))
+ promises.push(worker.single(options, thisExtOpts.options))
+ if (checkMovie) promises.push(worker.movie(options, thisExtOpts.options))
+ if (checkBatch) promises.push(worker.batch(options, thisExtOpts.options))
for (const result of await Promise.allSettled(promises)) {
if (result.status === 'fulfilled') {
@@ -246,6 +248,37 @@ export const extensions = new class Extensions {
return { results: navigator.onLine ? await this.updatePeerCounts(deduped) : deduped, errors }
}
+ async getNZBResultsFromExtensions (hash: string) {
+ await storage.modules
+ const workers = storage.workers
+ const results: Array<{ nzb: string, options: Record }> = []
+ const errors: Array<{ error: Error, extension: string }> = []
+
+ const extopts = get(extensionOptions)
+ const configs = get(saved)
+
+ for (const [id, worker] of Object.entries(workers)) {
+ const thisExtOpts = extopts[id]!
+ if (!thisExtOpts.enabled) continue
+ if (configs[id]!.type !== 'nzb') continue
+ try {
+ const nzb = await worker.query(hash, thisExtOpts.options)
+ if (!nzb) continue
+ results.push({ nzb, options: thisExtOpts.options })
+ } catch (error) {
+ errors.push({ error: error as Error, extension: id })
+ }
+ }
+
+ if (errors.length) {
+ for (const { error, extension } of errors) {
+ toast.error(`Error fetching NZB from ${configs[extension]?.name ?? extension}`, { description: error.message })
+ }
+ }
+
+ return results
+ }
+
async updatePeerCounts (entries: T): Promise {
debug(`Updating peer counts for ${entries.length} entries`)
diff --git a/src/lib/modules/extensions/worker.ts b/src/lib/modules/extensions/worker.ts
index 6fbaa19..c261f5a 100644
--- a/src/lib/modules/extensions/worker.ts
+++ b/src/lib/modules/extensions/worker.ts
@@ -1,15 +1,15 @@
import { finalizer } from 'abslink'
import { expose } from 'abslink/w3c'
-import type { SearchFunction, TorrentSource } from 'hayase-extensions'
+import type { SearchFunction, TorrentSource, NZBorURLSource } from 'hayase-extensions'
export default expose({
- mod: null as unknown as Promise,
+ mod: null as unknown as Promise,
construct (code: string) {
this.mod = this.load(code)
},
- async load (code: string): Promise {
+ async load (code: string): Promise {
// WARN: unsafe eval
const url = URL.createObjectURL(new Blob([code], { type: 'application/javascript' }))
const module = await import(/* @vite-ignore */url)
@@ -22,15 +22,19 @@ export default expose({
},
async single (...args: Parameters): ReturnType {
- return await ((await this.mod)).single(...args)
+ return await ((await this.mod) as TorrentSource).single(...args)
},
async batch (...args: Parameters): ReturnType {
- return await ((await this.mod)).batch(...args)
+ return await ((await this.mod) as TorrentSource).batch(...args)
},
async movie (...args: Parameters): ReturnType {
- return await ((await this.mod)).movie(...args)
+ return await ((await this.mod) as TorrentSource).movie(...args)
+ },
+
+ async query (...args: Parameters) {
+ return await ((await this.mod) as NZBorURLSource).query(...args)
},
async test () {
diff --git a/src/lib/modules/native.ts b/src/lib/modules/native.ts
index b691237..aebc9e6 100644
--- a/src/lib/modules/native.ts
+++ b/src/lib/modules/native.ts
@@ -138,6 +138,7 @@ export default Object.assign>({
navigate: async () => undefined,
downloadProgress: async () => undefined,
updateProgress: async () => undefined,
+ createNZB: async () => undefined,
torrentInfo: async (): Promise => ({
name: '',
progress: 0,
diff --git a/src/lib/modules/torrent/client.ts b/src/lib/modules/torrent/client.ts
index 2e9d3d9..7f19fb0 100644
--- a/src/lib/modules/torrent/client.ts
+++ b/src/lib/modules/torrent/client.ts
@@ -2,8 +2,10 @@ import Debug from 'debug'
import { writable } from 'simple-store-svelte'
import { get } from 'svelte/store'
import { persisted } from 'svelte-persisted-store'
+import { toast } from 'svelte-sonner'
import client from '../auth/client'
+import { extensions } from '../extensions'
import native from '../native'
import { SUPPORTS } from '../settings'
import { w2globby } from '../w2g/lobby'
@@ -97,8 +99,21 @@ export const server = new class ServerClient {
const result = { id, media, episode, files: await native.playTorrent(id, media.id, episode) }
debug('torrent play result', result)
this.downloaded.value = this.cachedSet()
+ this._addNZBs(result.files[0]!.hash)
return result
}
+
+ async _addNZBs (hash: string) {
+ const nzbs = await extensions.getNZBResultsFromExtensions(hash)
+
+ for (const { nzb, options } of nzbs) {
+ try {
+ await native.createNZB(hash, nzb, options.domain!, Number(options.port!), options.username!, options.password!, Number(options.poolSize!))
+ } catch (e) {
+ toast.error('Failed to add NZB', { description: (e as Error).message })
+ }
+ }
+ }
}()
requestIdleCallback(() => {