Skip to content

Commit

Permalink
feat(node): fix add torrent and add read magnet helper
Browse files Browse the repository at this point in the history
  • Loading branch information
yjl9903 committed Oct 11, 2024
1 parent 7935211 commit 66e69cb
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ await torrent.watchTorrent(
await client.shutdown()
```

You can find detailed examples using Node.js here: [examples/torrent.mjs](https://github.com/yjl9903/naria2/blob/main/examples/torrent.mjs), [examples/http.mjs](https://github.com/yjl9903/naria2/blob/main/examples/http.mjs).
You can find detailed examples using Node.js here: [examples/magnet.mjs](https://github.com/yjl9903/naria2/blob/main/examples/magnet.mjs), [examples/torrent.mjs](https://github.com/yjl9903/naria2/blob/main/examples/torrent.mjs), [examples/http.mjs](https://github.com/yjl9903/naria2/blob/main/examples/http.mjs).

> Due to the implementation of [aria2](https://aria2.github.io/manual/en/html/index.html), the downloading progress of a magnet uri includes **two steps**:
>
Expand Down
Binary file not shown.
37 changes: 37 additions & 0 deletions examples/magnet.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Commands to run this example (ensure you have built this package):
// $ pnpm i && pnpm build
// $ node ./examples/magnet.mjs

import { SingleBar } from 'cli-progress';
import { createClient } from 'naria2';
import { attachWebUI } from '@naria2/node/ui';
import { createChildProcess } from '@naria2/node';

const magnet = `magnet:?xt=urn:btih:DWZF43GLQCL4ZNOGR4PRIJCBTANP76CG&dn=&tr=http%3A%2F%2F104.143.10.186%3A8000%2Fannounce&tr=udp%3A%2F%2F104.143.10.186%3A8000%2Fannounce&tr=http%3A%2F%2Ftracker.openbittorrent.com%3A80%2Fannounce&tr=http%3A%2F%2Ftracker3.itzmx.com%3A6961%2Fannounce&tr=http%3A%2F%2Ftracker4.itzmx.com%3A2710%2Fannounce&tr=http%3A%2F%2Ftracker.publicbt.com%3A80%2Fannounce&tr=http%3A%2F%2Ftracker.prq.to%2Fannounce&tr=http%3A%2F%2Fopen.acgtracker.com%3A1096%2Fannounce&tr=https%3A%2F%2Ft-115.rhcloud.com%2Fonly_for_ylbud&tr=http%3A%2F%2Ftracker1.itzmx.com%3A8080%2Fannounce&tr=http%3A%2F%2Ftracker2.itzmx.com%3A6961%2Fannounce&tr=udp%3A%2F%2Ftracker1.itzmx.com%3A8080%2Fannounce&tr=udp%3A%2F%2Ftracker2.itzmx.com%3A6961%2Fannounce&tr=udp%3A%2F%2Ftracker3.itzmx.com%3A6961%2Fannounce&tr=udp%3A%2F%2Ftracker4.itzmx.com%3A2710%2Fannounce&tr=http%3A%2F%2Ftr.bangumi.moe%3A6969%2Fannounce&tr=http%3A%2F%2Ft.nyaatracker.com%2Fannounce&tr=http%3A%2F%2Fopen.nyaatorrents.info%3A6544%2Fannounce&tr=http%3A%2F%2Ft2.popgo.org%3A7456%2Fannonce&tr=http%3A%2F%2Fshare.camoe.cn%3A8080%2Fannounce&tr=http%3A%2F%2Fopentracker.acgnx.se%2Fannounce&tr=http%3A%2F%2Ftracker.acgnx.se%2Fannounce&tr=http%3A%2F%2Fnyaa.tracker.wf%3A7777%2Fannounce&tr=http%3A%2F%2Ftracker.kamigami.org%3A2710%2Fannounce&tr=http%3A%2F%2Fanidex.moe%3A6969%2Fannounce&tr=http%3A%2F%2Ft.acg.rip%3A6699%2Fannounce&tr=https%3A%2F%2Ftr.bangumi.moe%3A9696%2Fannounce&tr=https%3A%2F%2Fopentracker.i2p.rocks%3A443%2Fannounce&tr=https%3A%2F%2Ftracker.nanoha.org%3A443%2Fannounce&tr=https%3A%2F%2Ftracker.lilithraws.org%3A443%2Fannounce&tr=https%3A%2F%2Ftr.burnabyhighstar.com%3A443%2Fannounce`;

// Create a aria2 child process and initialize a client
const childprocess = createChildProcess({ rpc: {}, environment: 'ignore' });
const client = await createClient(childprocess);
const { url } = await attachWebUI(childprocess);

console.log(`Web UI: ${url}`);

// Start downloading a magnet
const torrent = await client.downloadUri(magnet);

// Watch its progress, and await for its completion
const bar = new SingleBar({});
bar.start(100, 0);
await torrent.watchTorrent(
() => {},
(task) => {
bar.update(task.progress);
},
'bt-complete'
);
bar.stop();

console.log(`Download OK:`, torrent.followedBy?.bittorrent?.name);

// Close client
await client.shutdown();
16 changes: 8 additions & 8 deletions examples/torrent.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// Commands to run this example (ensure you have built this package):
// $ pnpm i && pnpm build
// $ node ./scripts/download.mjs
// $ node ./examples/torrent.mjs

import { SingleBar } from 'cli-progress';
import { createClient } from 'naria2';
import { attachWebUI } from '@naria2/node/ui';
import { createChildProcess } from '@naria2/node';

const magnet = `magnet:?xt=urn:btih:DWZF43GLQCL4ZNOGR4PRIJCBTANP76CG&dn=&tr=http%3A%2F%2F104.143.10.186%3A8000%2Fannounce&tr=udp%3A%2F%2F104.143.10.186%3A8000%2Fannounce&tr=http%3A%2F%2Ftracker.openbittorrent.com%3A80%2Fannounce&tr=http%3A%2F%2Ftracker3.itzmx.com%3A6961%2Fannounce&tr=http%3A%2F%2Ftracker4.itzmx.com%3A2710%2Fannounce&tr=http%3A%2F%2Ftracker.publicbt.com%3A80%2Fannounce&tr=http%3A%2F%2Ftracker.prq.to%2Fannounce&tr=http%3A%2F%2Fopen.acgtracker.com%3A1096%2Fannounce&tr=https%3A%2F%2Ft-115.rhcloud.com%2Fonly_for_ylbud&tr=http%3A%2F%2Ftracker1.itzmx.com%3A8080%2Fannounce&tr=http%3A%2F%2Ftracker2.itzmx.com%3A6961%2Fannounce&tr=udp%3A%2F%2Ftracker1.itzmx.com%3A8080%2Fannounce&tr=udp%3A%2F%2Ftracker2.itzmx.com%3A6961%2Fannounce&tr=udp%3A%2F%2Ftracker3.itzmx.com%3A6961%2Fannounce&tr=udp%3A%2F%2Ftracker4.itzmx.com%3A2710%2Fannounce&tr=http%3A%2F%2Ftr.bangumi.moe%3A6969%2Fannounce&tr=http%3A%2F%2Ft.nyaatracker.com%2Fannounce&tr=http%3A%2F%2Fopen.nyaatorrents.info%3A6544%2Fannounce&tr=http%3A%2F%2Ft2.popgo.org%3A7456%2Fannonce&tr=http%3A%2F%2Fshare.camoe.cn%3A8080%2Fannounce&tr=http%3A%2F%2Fopentracker.acgnx.se%2Fannounce&tr=http%3A%2F%2Ftracker.acgnx.se%2Fannounce&tr=http%3A%2F%2Fnyaa.tracker.wf%3A7777%2Fannounce&tr=http%3A%2F%2Ftracker.kamigami.org%3A2710%2Fannounce&tr=http%3A%2F%2Fanidex.moe%3A6969%2Fannounce&tr=http%3A%2F%2Ft.acg.rip%3A6699%2Fannounce&tr=https%3A%2F%2Ftr.bangumi.moe%3A9696%2Fannounce&tr=https%3A%2F%2Fopentracker.i2p.rocks%3A443%2Fannounce&tr=https%3A%2F%2Ftracker.nanoha.org%3A443%2Fannounce&tr=https%3A%2F%2Ftracker.lilithraws.org%3A443%2Fannounce&tr=https%3A%2F%2Ftr.burnabyhighstar.com%3A443%2Fannounce`;
import { createChildProcess, readTorrentSync } from '@naria2/node';

// Create a aria2 child process and initialize a client
const childprocess = createChildProcess({ rpc: {}, environment: 'ignore' });
Expand All @@ -17,7 +15,9 @@ const { url } = await attachWebUI(childprocess);
console.log(`Web UI: ${url}`);

// Start downloading a magnet
const torrent = await client.downloadUri(magnet);
const torrent = await client.downloadTorrent(
readTorrentSync(`./assets/9d37cf4eb76b4318913341d487a0a76f36067cec.torrent`)
);

// Watch its progress, and await for its completion
const bar = new SingleBar({});
Expand All @@ -26,12 +26,12 @@ await torrent.watchTorrent(
() => {},
(task) => {
bar.update(task.progress);
},
'bt-complete'
}
);
bar.stop();

console.log(`Download OK:`, torrent.followedBy?.bittorrent?.name);
await torrent.updateStatus();
console.log(`Download OK:`, torrent.followedBy[0]);

// Close client
await client.shutdown();
2 changes: 1 addition & 1 deletion packages/naria2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ await torrent.watchTorrent(
await client.shutdown()
```

You can find detailed examples using Node.js here: [examples/torrent.mjs](https://github.com/yjl9903/naria2/blob/main/examples/torrent.mjs), [examples/http.mjs](https://github.com/yjl9903/naria2/blob/main/examples/http.mjs).
You can find detailed examples using Node.js here: [examples/magnet.mjs](https://github.com/yjl9903/naria2/blob/main/examples/magnet.mjs), [examples/torrent.mjs](https://github.com/yjl9903/naria2/blob/main/examples/torrent.mjs), [examples/http.mjs](https://github.com/yjl9903/naria2/blob/main/examples/http.mjs).

> Due to the implementation of [aria2](https://aria2.github.io/manual/en/html/index.html), the downloading progress of a magnet uri includes **two steps**:
>
Expand Down
16 changes: 11 additions & 5 deletions packages/naria2/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { type Aria2InputOptions, resolveInputOptions } from '@naria2/options';

import { Naria2Error } from '../error';

import type { MaybePromise } from './utils';
import type { ClientOptions, DownloadOptions } from './types';

import { sleep } from './utils';
Expand Down Expand Up @@ -92,13 +93,17 @@ export class Aria2Client {
}

public async downloadTorrent(
torrent: string,
torrent: MaybePromise<string>,
options: PartialDeep<Aria2InputOptions> & DownloadOptions = {}
) {
const inputOptions = resolveInputOptions(options);
const uris = options.uris ?? [];
const position = options.position ? [options.position] : [];
delete options.uris;
delete options.position;

const inputOptions = resolveInputOptions(options);
const gid = await aria2
.addTorrent(this.conn, torrent, undefined, { ...inputOptions }, ...position)
.addTorrent(this.conn, await torrent, uris, { ...inputOptions }, ...position)
.catch((error) => {
return { error: new Naria2Error(error?.message, error) };
});
Expand All @@ -108,10 +113,11 @@ export class Aria2Client {
}

public async downloadUri(
uri: string | string[],
uri: MaybePromise<string | string[]>,
options: PartialDeep<Aria2InputOptions> & DownloadOptions = {}
) {
const uris = Array.isArray(uri) ? uri : [uri];
const _uri = await uri;
const uris = Array.isArray(_uri) ? _uri : [_uri];
const inputOptions = resolveInputOptions(options);
const position = options.position ? [options.position] : [];
const gid = await aria2
Expand Down
3 changes: 1 addition & 2 deletions packages/naria2/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type Socket, type PreconfiguredSocket, open } from 'maria2';

import type { MaybePromise } from './utils';
import type { ClientOptions } from './types';

import { Aria2Client } from './client';
Expand All @@ -10,8 +11,6 @@ export * from './torrent';

export * from './types';

type MaybePromise<T> = T | Promise<T>;

export async function createClient(
_socket: MaybePromise<Socket | PreconfiguredSocket>,
options: ClientOptions = {}
Expand Down
10 changes: 8 additions & 2 deletions packages/naria2/src/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@ export interface ClientOptions {
}

export interface DownloadOptions {
/**
* uris is an array of URIs (string). uris is used for Web-seeding. For single file torrents, the URI can be a complete URI pointing to the resource; if URI ends with /, name in torrent file is added. For multi-file torrents, name and path in torrent are added to form a URI for each file. options is a struct and its members are pairs of option name and value.
*/
uris?: string[];

/**
* If position is given, it must be an integer starting from 0. The new download will be inserted at position in the waiting queue. If position is omitted or position is larger than the current size of the queue, the new download is appended to the end of the queue.
*/
position?: number;
}

export interface TorrentFile {}

export interface TorrentPiece {
readonly length: number;

Expand Down
2 changes: 2 additions & 0 deletions packages/naria2/src/client/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export type MaybePromise<T> = T | Promise<T>;

export function sleep(time: number): Promise<void> {
return new Promise((res) => {
setTimeout(() => res(), time);
Expand Down
2 changes: 2 additions & 0 deletions packages/node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export * from './error';
export * from './child_process';

export * from './transport';

export * from './utils';
18 changes: 18 additions & 0 deletions packages/node/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { readFile } from 'fs/promises';
import { readFileSync } from 'fs';

export async function readTorrent(file: string) {
const buffer = await readFile(file);
return buffer.toString('base64');
}

export function readTorrentSync(file: string) {
const buffer = readFileSync(file);
return buffer.toString('base64');
}

export async function fetchTorrent(...args: Parameters<typeof fetch>) {
const resp = await fetch(...args);
const buffer = await resp.arrayBuffer();
return Buffer.from(buffer).toString('base64');
}

0 comments on commit 66e69cb

Please sign in to comment.