Browse Source

Provide torrent download locations. Utilize assigned volumes. Added movie post-processing

master
David Ludwig 4 years ago
parent
commit
ec5f59948e
18 changed files with 864 additions and 418 deletions
  1. +11
    -3
      Dockerfile
  2. +2
    -0
      package.json
  3. +1
    -1
      src/Application.ts
  4. +8
    -0
      src/database/entities/MovieTicket.ts
  5. +3
    -0
      src/database/entities/MovieTorrent.ts
  6. +23
    -23
      src/services/IpcInterface.ts
  7. +57
    -1
      src/services/MovieSearch.ts
  8. +142
    -0
      src/services/PostProcessor/PostProcessor.ts
  9. +3
    -0
      src/services/PostProcessor/index.ts
  10. +47
    -38
      src/services/Supervisor.ts
  11. +37
    -17
      src/services/TorrentManager/TorrentClientIpc.ts
  12. +162
    -0
      src/services/TorrentManager/TorrentManager.ts
  13. +3
    -0
      src/services/TorrentManager/index.ts
  14. +4
    -2
      src/services/index.ts
  15. +1
    -1
      src/torrents/ranking.ts
  16. +324
    -332
      src/typings/node-ipc/index.d.ts
  17. +11
    -0
      src/utils.ts
  18. +25
    -0
      yarn.lock

+ 11
- 3
Dockerfile View File

@ -2,8 +2,12 @@ FROM node:14-alpine AS base
WORKDIR /app WORKDIR /app
RUN mkdir /var/autoplex && chown node:node -R /var/autoplex RUN mkdir /var/autoplex && chown node:node -R /var/autoplex
# Install packages for compiling certain Node libraries
FROM base AS base-dev
RUN apk add build-base python3
# An image containing necessary components for building # An image containing necessary components for building
FROM base AS builder
FROM base-dev AS builder
COPY package.json yarn.lock tsconfig.json ./ COPY package.json yarn.lock tsconfig.json ./
RUN rm -rf node_modules && yarn install --frozen-lockfile RUN rm -rf node_modules && yarn install --frozen-lockfile
COPY src src COPY src src
@ -12,9 +16,13 @@ COPY src src
FROM builder AS build FROM builder AS build
RUN yarn run build RUN yarn run build
# Install production dependencies
FROM build AS build-prod
RUN rm -rf node_modules && yarn install --production --frozen-lockfile
# An image containing the built app and production dependencies # An image containing the built app and production dependencies
FROM base AS prod FROM base AS prod
COPY --from=build /app/build ./build
COPY --from=build-prod /app/build ./build
COPY --from=build-prod /app/node_modules ./node_modules
COPY package.json yarn.lock ./ COPY package.json yarn.lock ./
RUN rm -rf node_modules && yarn install --production --frozen-lockfile
CMD [ "yarn", "run", "start" ] CMD [ "yarn", "run", "start" ]

+ 2
- 0
package.json View File

@ -13,6 +13,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^14.14.41", "@types/node": "^14.14.41",
"@types/node-ipc": "^9.1.3",
"@types/xml2js": "^0.4.8", "@types/xml2js": "^0.4.8",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
@ -21,6 +22,7 @@
}, },
"dependencies": { "dependencies": {
"cheerio": "^1.0.0-rc.6", "cheerio": "^1.0.0-rc.6",
"diskusage": "^1.1.3",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"node-ipc": "^9.1.4", "node-ipc": "^9.1.4",
"typeorm": "^0.2.32", "typeorm": "^0.2.32",


+ 1
- 1
src/Application.ts View File

@ -98,7 +98,7 @@ export default class Application
* Get an application service instance * Get an application service instance
*/ */
public service<T extends Service>(serviceName: string) { public service<T extends Service>(serviceName: string) {
assert(serviceName in this.services);
assert(serviceName in this.services, `Could not find service: ${serviceName}`);
return <T>this.services[serviceName]; return <T>this.services[serviceName];
} }
} }

+ 8
- 0
src/database/entities/MovieTicket.ts View File

@ -42,4 +42,12 @@ export class MovieTicket extends BaseEntity
@OneToOne(() => MovieInfo, { nullable: true }) @OneToOne(() => MovieInfo, { nullable: true })
@JoinColumn() @JoinColumn()
info!: MovieInfo | null; info!: MovieInfo | null;
/**
* Fulfill the current ticket instance
*/
async fulfill() {
this.isFulfilled = true;
return await this.save();
}
} }

+ 3
- 0
src/database/entities/MovieTorrent.ts View File

@ -10,6 +10,9 @@ export class MovieTorrent extends BaseEntity
@Column() @Column()
infoHash!: string; infoHash!: string;
@Column()
diskName!: string;
@ManyToOne(() => MovieTicket, ticket => ticket.torrents) @ManyToOne(() => MovieTicket, ticket => ticket.torrents)
movieTicket!: MovieTicket; movieTicket!: MovieTicket;
} }

+ 23
- 23
src/services/IpcInterface.ts View File

@ -1,6 +1,7 @@
import ipc from "node-ipc";
import type { Server } from "node-ipc";
import { IPC } from "node-ipc";
import { Socket } from "net"; import { Socket } from "net";
import { mkdir } from "fs/promises";
import { dirname } from "path";
import Service from "./Service"; import Service from "./Service";
import Application from "../Application"; import Application from "../Application";
import MovieSearch from "./MovieSearch"; import MovieSearch from "./MovieSearch";
@ -10,59 +11,58 @@ import { MovieTicket } from "../database/entities";
export default class IpcInterface extends Service export default class IpcInterface extends Service
{ {
/** /**
* Quick reference to the IPC server
* The IPC instance
*/ */
protected server!: Server;
private __ipc: InstanceType<typeof IPC>;
/** /**
* Create a new IPC interface * Create a new IPC interface
*/ */
public constructor(app: Application) { public constructor(app: Application) {
super("IPC", app); super("IPC", app);
ipc.config.id = "seeker";
ipc.config.retry = 1500;
ipc.config.silent = true;
this.__ipc = new IPC();
this.__ipc.config.id = "seeker";
this.__ipc.config.retry = 1500;
this.__ipc.config.silent = true;
} }
/** /**
* Boot the IPC interface * Boot the IPC interface
*/ */
public boot() { public boot() {
return new Promise<void>((resolve, reject) => {
return new Promise<void>(async (resolve, reject) => {
console.log("Serving:", process.env["IPC_SOCKET_PATH"]); console.log("Serving:", process.env["IPC_SOCKET_PATH"]);
ipc.serve(<string>process.env["IPC_SOCKET_PATH"], () => {
this.server = ipc.server;
this.installEventHandlers(this.server);
await mkdir(dirname(<string>process.env["IPC_SOCKET_PATH"]), { recursive: true });
this.__ipc.serve(<string>process.env["IPC_SOCKET_PATH"], () => {
this.installEventHandlers();
resolve(); resolve();
}); });
ipc.server.start();
this.__ipc.server.start();
}); });
} }
public async shutdown() { public async shutdown() {
if (this.server) {
this.server.stop();
}
this.__ipc.server.stop();
} }
/** /**
* Install the the event handlers * Install the the event handlers
*/ */
protected installEventHandlers(server: Server) {
this.addEventHandler(server, "search_movie", this.searchMovie);
protected installEventHandlers() {
this.addEventHandler("movie_ticket_added", this.onMovieTicketAdded);
} }
/** /**
* Handle a specific event * Handle a specific event
*/ */
protected addEventHandler(server: Server, method: string, handle: (...args: any[]) => Promise<any>) {
server.on(method, async (message: any, socket: Socket) => {
protected addEventHandler(method: string, handle: (...args: any[]) => Promise<any>) {
this.__ipc.server.on(method, async (message: any, socket: Socket) => {
try { try {
let response = await handle.apply(this, [message]); let response = await handle.apply(this, [message]);
this.server.emit(socket, method, { response });
this.__ipc.server.emit(socket, method, { response });
} catch (error) { } catch (error) {
console.log("Error:", method, error); console.log("Error:", method, error);
this.server.emit(socket, method, {
this.__ipc.server.emit(socket, method, {
response: undefined, response: undefined,
error error
}); });
@ -75,11 +75,11 @@ export default class IpcInterface extends Service
/** /**
* Invoked when a new Movie ticket has been created * Invoked when a new Movie ticket has been created
*/ */
protected async searchMovie(ticketId: number) {
protected async onMovieTicketAdded(ticketId: number) {
let movie = await MovieTicket.findOne(ticketId); let movie = await MovieTicket.findOne(ticketId);
if (movie === undefined) { if (movie === undefined) {
return null; return null;
} }
this.app.service<Supervisor>("Supervisor").searchMovie(movie);
this.app.service<Supervisor>("Supervisor").onMovieTicketNeedsTorrent(movie);
} }
} }

+ 57
- 1
src/services/MovieSearch.ts View File

@ -5,19 +5,37 @@ import Provider, { MediaType } from "../torrents/providers/Provider";
import Torrent from "../torrents/Torrent"; import Torrent from "../torrents/Torrent";
import { rankTorrents } from "../torrents/ranking"; import { rankTorrents } from "../torrents/ranking";
import Service from "./Service"; import Service from "./Service";
import Supervisor from "./Supervisor";
export default class MovieSearch extends Service export default class MovieSearch extends Service
{ {
/**
* The queue of current movie tickts requiring torrents
*/
protected movieQueue!: MovieTicket[];
/** /**
* Available providers that support movies * Available providers that support movies
*/ */
protected providers!: Provider[]; protected providers!: Provider[];
/**
* Indicate if the service is currently searching for movies in the queue
*/
protected isSearchingForMovies: boolean;
/**
* Store a reference to the supervisor service
*/
protected supervisor!: Supervisor;
/** /**
* Create a new instance of the movie search service * Create a new instance of the movie search service
*/ */
public constructor(app: Application) { public constructor(app: Application) {
super("Movie Search", app); super("Movie Search", app);
this.movieQueue = [];
this.isSearchingForMovies = false;
} }
/** /**
@ -29,6 +47,13 @@ export default class MovieSearch extends Service
.map(ProviderClass => new ProviderClass()); .map(ProviderClass => new ProviderClass());
} }
/**
* Connect to the supervisor instance when everything is booted
*/
public start() {
this.supervisor = this.app.service<Supervisor>("Supervisor");
}
/** /**
* Shutdown the service * Shutdown the service
*/ */
@ -36,10 +61,41 @@ export default class MovieSearch extends Service
} }
// Interface Methods ---------------------------------------------------------------------------
/**
* Enqueue a movie to the search queue
*/
public enqueueMovie(movie: MovieTicket) {
this.movieQueue.push(movie);
this.searchMovies();
}
// Movie Searching -----------------------------------------------------------------------------
/**
* Search for movies currently in the queue
*/
protected async searchMovies() {
if (this.isSearchingForMovies) {
return;
}
this.isSearchingForMovies = true;
while (this.movieQueue.length > 0) {
let movie = this.movieQueue.splice(0, 1)[0];
let link = await this.searchMovie(movie);
if (link === null) {
continue;
}
this.supervisor.onMovieTorrentFound(movie, link);
}
this.isSearchingForMovies = false;
}
/** /**
* Search for a movie * Search for a movie
*/ */
public async searchMovie(movie: MovieTicket) {
protected async searchMovie(movie: MovieTicket) {
// Search by IMDb // Search by IMDb
let torrents = await this.searchImdb(movie); let torrents = await this.searchImdb(movie);
if (torrents.length == 0) { if (torrents.length == 0) {


+ 142
- 0
src/services/PostProcessor/PostProcessor.ts View File

@ -0,0 +1,142 @@
import { link, mkdir } from "fs/promises";
import { dirname, extname } from "path";
import Application from "../../Application";
import { MovieTicket, MovieTorrent } from "../../database/entities";
import Service from "../Service";
import { ISerializedTorrent } from "../TorrentManager/TorrentClientIpc";
import { safeTitleFileName } from "../../utils";
import Supervisor from "../Supervisor";
/**
* Common video file extensions
*/
const VIDEO_FILE_EXTENSIONS = new Set(
".mp4,.mkv,.avi,.wmv,.mov".split(",")
);
/**
* A wrapper for a pending movie torrent
*/
interface IPendingMovieTorrent {
details: ISerializedTorrent,
diskName : string,
ticket : MovieTicket
}
export default class PostProcessor extends Service
{
/**
* The queue of movies to process
*/
protected pendingMovies: IPendingMovieTorrent[];
/**
* Indicate if movies are currently being processed
*/
protected isProcessingMovies: boolean;
/**
* Create a new instance of the post processor
*/
public constructor(app: Application) {
super("Post Processor", app);
this.pendingMovies = [];
this.isProcessingMovies = false;
}
/**
* Boot the post-processor service
*/
public async boot() {
}
/**
* Shutdown the post-processor service
*/
public async shutdown() {
}
// Methods -------------------------------------------------------------------------------------
/**
* Enqueue a completed movie for post-processing
*/
public enqueueMovie(torrent: MovieTorrent, details: ISerializedTorrent) {
this.pendingMovies.push({ticket: torrent.movieTicket, diskName: torrent.diskName, details});
this.processMovies();
}
/**
* Process the enqueued movies
*/
public async processMovies() {
if (this.isProcessingMovies) {
return;
}
this.isProcessingMovies = true;
while (this.pendingMovies.length > 0) {
let movie = this.pendingMovies.splice(0, 1)[0];
this.processMovie(movie);
}
this.isProcessingMovies = false;
}
/**
* Process an enqueue movie
*/
protected async processMovie(pendingMovie: IPendingMovieTorrent) {
let movieFile = this.findMovieFile(pendingMovie.details);
if (!movieFile) {
this.log("Unable to find a completed movie file in the torrent:", pendingMovie.details.name);
return;
}
// Generate the movie file's name
let movieName = safeTitleFileName(pendingMovie.ticket.title);
if (pendingMovie.ticket.year !== null) {
movieName += ` (${pendingMovie.ticket.year})`;
}
let basePath = `/mnt/movies/${pendingMovie.diskName}`;
let from = `${basePath}/Downloads/${movieFile.path}`;
let to = `${basePath}/Media/${movieName}/${movieName}${extname(movieFile.path)}`;
await this.hardlinkFile(from, to);
// Notify the supervisor that the movie has been processed
this.app.service<Supervisor>("Supervisor").onMovieTorrentProcessed(pendingMovie.ticket);
}
/**
* Locate the movie file in a torrent
*/
protected findMovieFile(details: ISerializedTorrent) {
// Find video files in the torrent
let movieFiles = details.files.filter(
file => file.selected && file.downloaded == file.size
&& VIDEO_FILE_EXTENSIONS.has(extname(file.path).toLowerCase())
);
// Find the video file with the largest size
let maxIndex = 0;
for (let i = 0; i < movieFiles.length; i++) {
if (movieFiles[i].size > movieFiles[maxIndex].size) {
maxIndex = i;
}
}
// Return the result
if (movieFiles[maxIndex] === undefined) {
return null;
}
return movieFiles[maxIndex];
}
/**
* Hardlink a file to another directory
*/
protected async hardlinkFile(from: string, to: string) {
this.log("Creating hardlink:", from, "->", to);
await mkdir(dirname(to), { recursive: true });
await link(from, to);
}
}

+ 3
- 0
src/services/PostProcessor/index.ts View File

@ -0,0 +1,3 @@
import PostProcessor from "./PostProcessor";
export default PostProcessor;

+ 47
- 38
src/services/Supervisor.ts View File

@ -1,15 +1,13 @@
import Application from "../Application"; import Application from "../Application";
import { MovieTicket, MovieTorrent } from "../database/entities"; import { MovieTicket, MovieTorrent } from "../database/entities";
import MovieSearch from "./MovieSearch"; import MovieSearch from "./MovieSearch";
import PostProcessor from "./PostProcessor";
import Service from "./Service"; import Service from "./Service";
import TorrentClientIpc, { TorrentClientConnectionError } from "./TorrentClientIpc";
import TorrentManager from "./TorrentManager";
import { ISerializedTorrent } from "./TorrentManager/TorrentClientIpc";
export default class Supervisor extends Service export default class Supervisor extends Service
{ {
/**
* Keep a list of pending torrent links to add
*/
protected pendingTorrentsToAdd: string[];
/** /**
* The movie search service instance * The movie search service instance
@ -19,14 +17,18 @@ export default class Supervisor extends Service
/** /**
* The torrent client IPC service instance * The torrent client IPC service instance
*/ */
protected torrentClient!: TorrentClientIpc;
protected torrentManager!: TorrentManager;
/**
* The post-processor service instance
*/
protected postProcessor!: PostProcessor;
/** /**
* Create a new supervisor service instance * Create a new supervisor service instance
*/ */
public constructor(app: Application) { public constructor(app: Application) {
super("Supervisor", app); super("Supervisor", app);
this.pendingTorrentsToAdd = [];
} }
/** /**
@ -39,7 +41,8 @@ export default class Supervisor extends Service
*/ */
public start() { public start() {
this.movieSearch = this.app.service<MovieSearch>("Movie Search"); this.movieSearch = this.app.service<MovieSearch>("Movie Search");
this.torrentClient = this.app.service<TorrentClientIpc>("Torrent Client IPC");
this.torrentManager = this.app.service<TorrentManager>("Torrent Manager");
this.postProcessor = this.app.service<PostProcessor>("Post Processor");
this.searchMovies(); this.searchMovies();
} }
@ -48,6 +51,41 @@ export default class Supervisor extends Service
*/ */
public async shutdown() {} public async shutdown() {}
// Request Flow --------------------------------------------------------------------------------
/**
* 1. A movie ticket has been added/torrent has gone stale, so
* dispatch a search task for a torrent
*/
public onMovieTicketNeedsTorrent(ticket: MovieTicket) {
this.log("A movie needs a torrent:", ticket.title);
this.movieSearch.enqueueMovie(ticket);
}
/**
* 2. A movie torrent has been found, so add it to the client
*/
public onMovieTorrentFound(ticket: MovieTicket, link: string) {
this.log("A torrent was found for movie:", ticket.title);
this.torrentManager.enqueueMovie(ticket, link);
}
/**
* 3. A torrent has finished downloading, so send it for post-processing
*/
public onMovieTorrentFinished(torrent: MovieTorrent, details: ISerializedTorrent) {
this.log("A torrent has finished for movie:", torrent.movieTicket.title);
this.postProcessor.enqueueMovie(torrent, details);
}
/**
* 4. A ticket's torrent has finished post-processing, so fulfill the ticket
*/
public onMovieTorrentProcessed(ticket: MovieTicket) {
this.log("A movie torrent has been successfully processed:", ticket.title);
ticket.fulfill();
}
// Tasks --------------------------------------------------------------------------------------- // Tasks ---------------------------------------------------------------------------------------
/** /**
@ -62,36 +100,7 @@ export default class Supervisor extends Service
this.log("Skipping already satisfied ticket") this.log("Skipping already satisfied ticket")
continue; continue;
} }
await this.searchMovie(movie);
}
}
/**
* Search for a movie and add it to the torrent client
*/
public async searchMovie(movie: MovieTicket) {
// Search for a movie torrent
let link = await this.movieSearch.searchMovie(movie);
if (link === null) {
return false;
}
this.log("Found a torrent for:", movie.title, link);
// Send the link to the client
let infoHash: string;
try {
infoHash = await this.torrentClient.add(link);
} catch(e) {
if (e instanceof TorrentClientConnectionError) {
this.log("Failed to add torrent to client... Added to pending");
this.pendingTorrentsToAdd.push(link);
}
return false;
this.onMovieTicketNeedsTorrent(movie);
} }
// Store a reference to this torrent in the database
let torrent = new MovieTorrent();
torrent.infoHash = infoHash;
torrent.movieTicket = movie;
await torrent.save();
return true;
} }
} }

src/services/TorrentClientIpc.ts → src/services/TorrentManager/TorrentClientIpc.ts View File


+ 162
- 0
src/services/TorrentManager/TorrentManager.ts View File

@ -0,0 +1,162 @@
import diskusage from "diskusage";
import { readdir } from "fs/promises";
import Application from "../../Application"
import { MovieTicket, MovieTorrent } from "../../database/entities";
import Supervisor from "../Supervisor";
import TorrentClientIpc, { TorrentClientConnectionError } from "./TorrentClientIpc"
interface IPendingMovieTorrent {
link: string,
movie: MovieTicket
}
/**
* A mapping of available disks
*/
interface IDiskMap {
movies: string[],
// tvshows: string[]
}
export default class TorrentManager extends TorrentClientIpc
{
/**
* The queue of movies to add to the client
*/
protected pendingMovies: IPendingMovieTorrent[];
/**
* Indicate if the service is currently adding movies to the torrent client
*/
protected isAddingMovies: boolean;
/**
* Available movie disk names
*/
protected disks!: IDiskMap;
/**
* Create a new torrent manager instance
*/
public constructor(app: Application) {
super("Torrent Manager", app);
this.pendingMovies = [];
this.isAddingMovies = false;
}
/**
* Boot the Torrent Manager service
*/
public async boot() {
this.log("Booting the torrent manager");
await super.boot();
await this.loadDisks();
}
// Interface methods ---------------------------------------------------------------------------
/**
* Add a movie to the queue
*/
public enqueueMovie(movie: MovieTicket, link: string) {
this.pendingMovies.push({movie, link});
this.addMovies();
}
// Volume Management ---------------------------------------------------------------------------
/**
* Load available storage disks
*/
public async loadDisks() {
this.disks = {
movies: await readdir("/mnt/movies"),
// tvshows: await readdir("/mnt/tvshows")
}
}
/**
* Get the disk with the most space available
*/
public async findMostEmptyDisk(diskType: "movies") {
let diskSizes = await Promise.all(this.disks[diskType].map(
async diskName => (await diskusage.check(`/mnt/${diskType}/${diskName}`)).available
));
let minIndex = 0;
for (let i = 1; i < diskSizes.length; i++) {
if (diskSizes[i] < diskSizes[minIndex]) {
minIndex = i;
}
}
return this.disks[diskType][minIndex];
}
// Movie Management ----------------------------------------------------------------------------
/**
* Add the movies in the queue to the torrent client
*/
protected async addMovies() {
if (this.isAddingMovies || !this.isConnected || this.pendingMovies.length == 0) {
return;
}
this.isAddingMovies = true;
let diskName = await this.findMostEmptyDisk("movies");
while (this.pendingMovies.length > 0) {
let {movie, link} = this.pendingMovies.splice(0, 1)[0];
try {
await this.addMovie(movie, link, diskName);
} catch(e) {
this.log("Failed to add torrent to client... Added to pending");
this.pendingMovies.push({movie, link});
break;
}
}
this.isAddingMovies = false;
}
/**
* Add a movie to the torrent client
*/
public async addMovie(movie: MovieTicket, link: string, diskName: string) {
try {
let infoHash = await this.add(link, `/mnt/movies/${diskName}/Downloads`);
let torrent = new MovieTorrent();
torrent.infoHash = infoHash;
torrent.diskName = diskName;
torrent.movieTicket = movie;
await torrent.save();
} catch(e) {
if (e instanceof TorrentClientConnectionError) {
throw e;
}
console.log("Failed download the torrent");
return false;
}
return true;
}
// Event Handling ------------------------------------------------------------------------------
/**
* Invoked when the connection to the torrent client is established/re-established
*/
protected onConnect() {
super.onConnect();
this.addMovies();
}
/**
* Invoked when a torrent
*/
protected async onTorrentFinished(infoHash: string) {
let torrent = await MovieTorrent.findOne({
where: { infoHash }, relations: ["movieTicket"]
});
if (torrent !== undefined) {
let details = (await this.details(infoHash))[0];
this.app.service<Supervisor>("Supervisor").onMovieTorrentFinished(torrent, details);
}
// this.app.service<Supervisor>();
}
}

+ 3
- 0
src/services/TorrentManager/index.ts View File

@ -0,0 +1,3 @@
import TorrentManager from "./TorrentManager";
export default TorrentManager;

+ 4
- 2
src/services/index.ts View File

@ -1,13 +1,15 @@
import Database from "./Database"; import Database from "./Database";
import IpcInterface from "./IpcInterface"; import IpcInterface from "./IpcInterface";
import MovieSearch from "./MovieSearch"; import MovieSearch from "./MovieSearch";
import PostProcessor from "./PostProcessor";
import Supervisor from "./Supervisor"; import Supervisor from "./Supervisor";
import TorrentClientIpc from "./TorrentClientIpc";
import TorrentManager from "./TorrentManager";
export default { export default {
Database, Database,
IpcInterface, IpcInterface,
MovieSearch, MovieSearch,
PostProcessor,
Supervisor, Supervisor,
TorrentClientIpc,
TorrentManager,
} }

+ 1
- 1
src/torrents/ranking.ts View File

@ -18,7 +18,7 @@ function selectPreferredTorrents(torrent: Torrent) {
return false; return false;
} }
if (torrent.metadata.resolution == Resolution.HD4k) { if (torrent.metadata.resolution == Resolution.HD4k) {
return torrent.size != null && torrent.size < 15*1024*1024*1024; // 15GB
return torrent.size != null && torrent.size < 10*1024*1024*1024; // 10GB
} }
return true; return true;
} }


+ 324
- 332
src/typings/node-ipc/index.d.ts View File

@ -1,350 +1,342 @@
/// <reference types="node"/>
declare module "node-ipc" {
import { Socket } from "net";
declare const NodeIPC: NodeIPC.NodeIPC;
declare namespace NodeIPC {
interface NodeIPC extends IPC
{}
interface IPC {
/**
* Set these variables in the ipc.config scope to overwrite or set default values
*/
config: Config;
/**
* https://www.npmjs.com/package/node-ipc#log
*/
log(...args: any[]): void;
/**
* https://www.npmjs.com/package/node-ipc#connectto
* Used for connecting as a client to local Unix Sockets and Windows Sockets.
* This is the fastest way for processes on the same machine to communicate
* because it bypasses the network card which TCP and UDP must both use.
* @param id is the string id of the socket being connected to.
* The socket with this id is added to the ipc.of object when created.
* @param path is the path of the Unix Domain Socket File, if the System is Windows,
* this will automatically be converted to an appropriate pipe with the same information as the Unix Domain Socket File.
* If not set this will default to ipc.config.socketRoot+ipc.config.appspace+id
* @param callback this is the function to execute when the socket has been created
*/
connectTo(id: string, path?: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connectto
* Used for connecting as a client to local Unix Sockets and Windows Sockets.
* This is the fastest way for processes on the same machine to communicate
* because it bypasses the network card which TCP and UDP must both use.
* @param id is the string id of the socket being connected to.
* The socket with this id is added to the ipc.of object when created.
* @param callback this is the function to execute when the socket has been created
*/
connectTo(id: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connecttonet
* Used to connect as a client to a TCP or TLS socket via the network card.
* This can be local or remote, if local, it is recommended that you use the Unix
* and Windows Socket Implementaion of connectTo instead as it is much faster since it avoids the network card altogether.
* For TLS and SSL Sockets see the node-ipc TLS and SSL docs.
* They have a few additional requirements, and things to know about and so have their own doc.
* @param id is the string id of the socket being connected to. For TCP & TLS sockets,
* this id is added to the ipc.of object when the socket is created with a reference to the socket
* @param host is the host on which the TCP or TLS socket resides.
* This will default to ipc.config.networkHost if not specified
* @param port the port on which the TCP or TLS socket resides
* @param callback this is the function to execute when the socket has been created
*/
connectToNet(id: string, host?: string, port?: number, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connecttonet
* Used to connect as a client to a TCP or TLS socket via the network card.
* This can be local or remote, if local, it is recommended that you use the Unix
* and Windows Socket Implementaion of connectTo instead as it is much faster since it avoids the network card altogether.
* For TLS and SSL Sockets see the node-ipc TLS and SSL docs.
* They have a few additional requirements, and things to know about and so have their own doc.
* @param id is the string id of the socket being connected to. For TCP & TLS sockets,
* this id is added to the ipc.of object when the socket is created with a reference to the socket
* @param callback this is the function to execute when the socket has been created
*/
connectToNet(id: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connecttonet
* Used to connect as a client to a TCP or TLS socket via the network card.
* This can be local or remote, if local, it is recommended that you use the Unix
* and Windows Socket Implementaion of connectTo instead as it is much faster since it avoids the network card altogether.
* For TLS and SSL Sockets see the node-ipc TLS and SSL docs.
* They have a few additional requirements, and things to know about and so have their own doc.
* @param id is the string id of the socket being connected to.
* For TCP & TLS sockets, this id is added to the ipc.of object when the socket is created with a reference to the socket
* @param host is the host on which the TCP or TLS socket resides. This will default to ipc.config.networkHost if not specified
* @param port the port on which the TCP or TLS socket resides
* @param callback this is the function to execute when the socket has been created
*/
connectToNet(id: string, hostOrPort: number | string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#disconnect
* Used to disconnect a client from a Unix, Windows, TCP or TLS socket.
* The socket and its refrence will be removed from memory and the ipc.of scope.
* This can be local or remote. UDP clients do not maintain connections and so there are no Clients and this method has no value to them
* @param id is the string id of the socket from which to disconnect
*/
disconnect(id: string): void;
/**
* https://www.npmjs.com/package/node-ipc#serve
* Used to create local Unix Socket Server or Windows Socket Server to which Clients can bind.
* The server can emit events to specific Client Sockets, or broadcast events to all known Client Sockets
* @param path This is the path of the Unix Domain Socket File, if the System is Windows,
* this will automatically be converted to an appropriate pipe with the same information as the Unix Domain Socket File.
* If not set this will default to ipc.config.socketRoot+ipc.config.appspace+id
* @param callback This is a function to be called after the Server has started.
* This can also be done by binding an event to the start event like ipc.server.on('start',function(){});
*/
serve(path: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#serve
* Used to create local Unix Socket Server or Windows Socket Server to which Clients can bind.
* The server can emit events to specific Client Sockets, or broadcast events to all known Client Sockets
* @param callback This is a function to be called after the Server has started.
* This can also be done by binding an event to the start event like ipc.server.on('start',function(){});
*/
serve(callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#serve
* Used to create local Unix Socket Server or Windows Socket Server to which Clients can bind.
* The server can emit events to specific Client Sockets, or broadcast events to all known Client Sockets
*/
serve(callback: null): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param host If not specified this defaults to the first address in os.networkInterfaces().
* For TCP, TLS & UDP servers this is most likely going to be 127.0.0.1 or ::1
* @param port The port on which the TCP, UDP, or TLS Socket server will be bound, this defaults to 8000 if not specified
* @param UDPType If set this will create the server as a UDP socket. 'udp4' or 'udp6' are valid values.
* This defaults to not being set. When using udp6 make sure to specify a valid IPv6 host, like ::1
* @param callback Function to be called when the server is created
*/
serveNet(host?: string, port?: number, UDPType?: "udp4" | "udp6", callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param UDPType If set this will create the server as a UDP socket. 'udp4' or 'udp6' are valid values.
* This defaults to not being set. When using udp6 make sure to specify a valid IPv6 host, like ::1
* @param callback Function to be called when the server is created
*/
serveNet(UDPType: "udp4" | "udp6", callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param callback Function to be called when the server is created
* @param port The port on which the TCP, UDP, or TLS Socket server will be bound, this defaults to 8000 if not specified
*/
serveNet(callbackOrPort: EmptyCallback | number): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param host If not specified this defaults to the first address in os.networkInterfaces().
* For TCP, TLS & UDP servers this is most likely going to be 127.0.0.1 or ::1
* @param port The port on which the TCP, UDP, or TLS Socket server will be bound, this defaults to 8000 if not specified
* @param callback Function to be called when the server is created
*/
serveNet(host: string, port: number, callback?: () => void): void;
/**
* This is where socket connection refrences will be stored when connecting to them as a client via the ipc.connectTo
* or iupc.connectToNet. They will be stored based on the ID used to create them, eg : ipc.of.mySocket
*/
of: any;
/**
* This is a refrence to the server created by ipc.serve or ipc.serveNet
*/
server: Server;
}
type EmptyCallback = () => void;
interface Client {
/**
* triggered when a JSON message is received. The event name will be the type string from your message
* and the param will be the data object from your message eg : { type:'myEvent',data:{a:1}}
*/
on(event: string, callback: (message: any, socket: Socket) => void): Client;
/**
* triggered when an error has occured
*/
on(event: "error", callback: (err: any) => void): Client;
/**
* connect - triggered when socket connected
* disconnect - triggered by client when socket has disconnected from server
* destroy - triggered when socket has been totally destroyed, no further auto retries will happen and all references are gone
*/
on(event: "connect" | "disconnect" | "destroy", callback: () => void): Client;
/**
* triggered by server when a client socket has disconnected
*/
on(event: "socket.disconnected", callback: (socket: Socket, destroyedSocketID: string) => void): Client;
/**
* triggered when ipc.config.rawBuffer is true and a message is received
*/
on(event: "data", callback: (buffer: Buffer) => void): Client;
emit(event: string, value?: any): Client;
/**
* Unbind subscribed events
*/
off(event: string, handler: any): Client;
}
interface Server extends Client {
/**
* start serving need top call serve or serveNet first to set up the server
*/
start(): void;
/**
* close the server and stop serving
*/
stop(): void;
emit(value: any): Client;
emit(event: string, value: any): Client;
emit(socket: Socket | SocketConfig, event: string, value?: any): Server;
emit(socketConfig: Socket | SocketConfig, value?: any): Server;
}
interface SocketConfig {
address?: string;
port?: number;
}
interface Config {
/**
* Default: 'app.'
* Used for Unix Socket (Unix Domain Socket) namespacing.
* If not set specifically, the Unix Domain Socket will combine the socketRoot, appspace,
* and id to form the Unix Socket Path for creation or binding.
* This is available incase you have many apps running on your system, you may have several sockets with the same id,
* but if you change the appspace, you will still have app specic unique sockets
*/
appspace: string;
/**
* Default: '/tmp/'
* The directory in which to create or bind to a Unix Socket
*/
socketRoot: string;
/**
* Default: os.hostname()
* The id of this socket or service
*/
id: string;
/**
* Default: 'localhost'
* The local or remote host on which TCP, TLS or UDP Sockets should connect
* Should resolve to 127.0.0.1 or ::1 see the table below related to this
*/
networkHost: string;
/**
* Default: 8000
* The default port on which TCP, TLS, or UDP sockets should connect
*/
networkPort: number;
/**
* Default: 'utf8'
* the default encoding for data sent on sockets. Mostly used if rawBuffer is set to true.
* Valid values are : ascii utf8 utf16le ucs2 base64 hex
*/
encoding: "ascii" | "utf8" | "utf16le" | "ucs2" | "base64" | "hex";
// Type definitions for node-ipc 9.1
// Project: http://riaevangelist.github.io/node-ipc/
// Definitions by: Arvitaly <https://github.com/arvitaly>, gjurgens <https://github.com/gjurgens>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/// <reference types="node" />
import { Socket } from "net";
declare namespace NodeIPC {
export class IPC {
/**
* Set these variables in the ipc.config scope to overwrite or set default values
*/
config: Config;
/**
* https://www.npmjs.com/package/node-ipc#log
*/
log(...args: any[]): void;
/**
* https://www.npmjs.com/package/node-ipc#connectto
* Used for connecting as a client to local Unix Sockets and Windows Sockets.
* This is the fastest way for processes on the same machine to communicate
* because it bypasses the network card which TCP and UDP must both use.
* @param id is the string id of the socket being connected to.
* The socket with this id is added to the ipc.of object when created.
* @param path is the path of the Unix Domain Socket File, if the System is Windows,
* this will automatically be converted to an appropriate pipe with the same information as the Unix Domain Socket File.
* If not set this will default to ipc.config.socketRoot+ipc.config.appspace+id
* @param callback this is the function to execute when the socket has been created
*/
connectTo(id: string, path?: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connectto
* Used for connecting as a client to local Unix Sockets and Windows Sockets.
* This is the fastest way for processes on the same machine to communicate
* because it bypasses the network card which TCP and UDP must both use.
* @param id is the string id of the socket being connected to.
* The socket with this id is added to the ipc.of object when created.
* @param callback this is the function to execute when the socket has been created
*/
connectTo(id: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connecttonet
* Used to connect as a client to a TCP or TLS socket via the network card.
* This can be local or remote, if local, it is recommended that you use the Unix
* and Windows Socket Implementaion of connectTo instead as it is much faster since it avoids the network card altogether.
* For TLS and SSL Sockets see the node-ipc TLS and SSL docs.
* They have a few additional requirements, and things to know about and so have their own doc.
* @param id is the string id of the socket being connected to. For TCP & TLS sockets,
* this id is added to the ipc.of object when the socket is created with a reference to the socket
* @param host is the host on which the TCP or TLS socket resides.
* This will default to ipc.config.networkHost if not specified
* @param port the port on which the TCP or TLS socket resides
* @param callback this is the function to execute when the socket has been created
*/
connectToNet(id: string, host?: string, port?: number, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connecttonet
* Used to connect as a client to a TCP or TLS socket via the network card.
* This can be local or remote, if local, it is recommended that you use the Unix
* and Windows Socket Implementaion of connectTo instead as it is much faster since it avoids the network card altogether.
* For TLS and SSL Sockets see the node-ipc TLS and SSL docs.
* They have a few additional requirements, and things to know about and so have their own doc.
* @param id is the string id of the socket being connected to. For TCP & TLS sockets,
* this id is added to the ipc.of object when the socket is created with a reference to the socket
* @param callback this is the function to execute when the socket has been created
*/
connectToNet(id: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#connecttonet
* Used to connect as a client to a TCP or TLS socket via the network card.
* This can be local or remote, if local, it is recommended that you use the Unix
* and Windows Socket Implementaion of connectTo instead as it is much faster since it avoids the network card altogether.
* For TLS and SSL Sockets see the node-ipc TLS and SSL docs.
* They have a few additional requirements, and things to know about and so have their own doc.
* @param id is the string id of the socket being connected to.
* For TCP & TLS sockets, this id is added to the ipc.of object when the socket is created with a reference to the socket
* @param host is the host on which the TCP or TLS socket resides. This will default to ipc.config.networkHost if not specified
* @param port the port on which the TCP or TLS socket resides
* @param callback this is the function to execute when the socket has been created
*/
connectToNet(id: string, hostOrPort: number | string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#disconnect
* Used to disconnect a client from a Unix, Windows, TCP or TLS socket.
* The socket and its refrence will be removed from memory and the ipc.of scope.
* This can be local or remote. UDP clients do not maintain connections and so there are no Clients and this method has no value to them
* @param id is the string id of the socket from which to disconnect
*/
disconnect(id: string): void;
/**
* https://www.npmjs.com/package/node-ipc#serve
* Used to create local Unix Socket Server or Windows Socket Server to which Clients can bind.
* The server can emit events to specific Client Sockets, or broadcast events to all known Client Sockets
* @param path This is the path of the Unix Domain Socket File, if the System is Windows,
* this will automatically be converted to an appropriate pipe with the same information as the Unix Domain Socket File.
* If not set this will default to ipc.config.socketRoot+ipc.config.appspace+id
* @param callback This is a function to be called after the Server has started.
* This can also be done by binding an event to the start event like ipc.server.on('start',function(){});
*/
serve(path: string, callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#serve
* Used to create local Unix Socket Server or Windows Socket Server to which Clients can bind.
* The server can emit events to specific Client Sockets, or broadcast events to all known Client Sockets
* @param callback This is a function to be called after the Server has started.
* This can also be done by binding an event to the start event like ipc.server.on('start',function(){});
*/
serve(callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#serve
* Used to create local Unix Socket Server or Windows Socket Server to which Clients can bind.
* The server can emit events to specific Client Sockets, or broadcast events to all known Client Sockets
*/
serve(callback: null): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param host If not specified this defaults to the first address in os.networkInterfaces().
* For TCP, TLS & UDP servers this is most likely going to be 127.0.0.1 or ::1
* @param port The port on which the TCP, UDP, or TLS Socket server will be bound, this defaults to 8000 if not specified
* @param UDPType If set this will create the server as a UDP socket. 'udp4' or 'udp6' are valid values.
* This defaults to not being set. When using udp6 make sure to specify a valid IPv6 host, like ::1
* @param callback Function to be called when the server is created
*/
serveNet(host?: string, port?: number, UDPType?: "udp4" | "udp6", callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param UDPType If set this will create the server as a UDP socket. 'udp4' or 'udp6' are valid values.
* This defaults to not being set. When using udp6 make sure to specify a valid IPv6 host, like ::1
* @param callback Function to be called when the server is created
*/
serveNet(UDPType: "udp4" | "udp6", callback?: () => void): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param callback Function to be called when the server is created
* @param port The port on which the TCP, UDP, or TLS Socket server will be bound, this defaults to 8000 if not specified
*/
serveNet(callbackOrPort: EmptyCallback | number): void;
/**
* https://www.npmjs.com/package/node-ipc#servenet
* @param host If not specified this defaults to the first address in os.networkInterfaces().
* For TCP, TLS & UDP servers this is most likely going to be 127.0.0.1 or ::1
* @param port The port on which the TCP, UDP, or TLS Socket server will be bound, this defaults to 8000 if not specified
* @param callback Function to be called when the server is created
*/
serveNet(host: string, port: number, callback?: () => void): void;
/**
* This is where socket connection refrences will be stored when connecting to them as a client via the ipc.connectTo
* or iupc.connectToNet. They will be stored based on the ID used to create them, eg : ipc.of.mySocket
*/
of: any;
/**
* This is a refrence to the server created by ipc.serve or ipc.serveNet
*/
server: Server;
}
type EmptyCallback = () => void;
export interface Client {
/**
* triggered when a JSON message is received. The event name will be the type string from your message
* and the param will be the data object from your message eg : { type:'myEvent',data:{a:1}}
*/
on(event: string, callback: (...args: any[]) => void): Client;
/**
* triggered when an error has occured
*/
on(event: "error", callback: (err: any) => void): Client;
/**
* connect - triggered when socket connected
* disconnect - triggered by client when socket has disconnected from server
* destroy - triggered when socket has been totally destroyed, no further auto retries will happen and all references are gone
*/
on(event: "connect" | "disconnect" | "destroy", callback: () => void): Client;
/**
* triggered by server when a client socket has disconnected
*/
on(event: "socket.disconnected", callback: (socket: Socket, destroyedSocketID: string) => void): Client;
/**
* triggered when ipc.config.rawBuffer is true and a message is received
*/
on(event: "data", callback: (buffer: Buffer) => void): Client;
emit(event: string, value?: any): Client;
/**
* Unbind subscribed events
*/
off(event: string, handler: any): Client;
}
export interface Server extends Client {
/**
* start serving need top call serve or serveNet first to set up the server
*/
start(): void;
/**
* close the server and stop serving
*/
stop(): void;
emit(value: any): Client;
emit(event: string, value: any): Client;
emit(socket: Socket | SocketConfig, event: string, value?: any): Server;
emit(socketConfig: Socket | SocketConfig, value?: any): Server;
}
interface SocketConfig {
address?: string;
port?: number;
}
interface Config {
/**
* Default: 'app.'
* Used for Unix Socket (Unix Domain Socket) namespacing.
* If not set specifically, the Unix Domain Socket will combine the socketRoot, appspace,
* and id to form the Unix Socket Path for creation or binding.
* This is available incase you have many apps running on your system, you may have several sockets with the same id,
* but if you change the appspace, you will still have app specic unique sockets
*/
appspace: string;
/**
* Default: '/tmp/'
* The directory in which to create or bind to a Unix Socket
*/
socketRoot: string;
/**
* Default: os.hostname()
* The id of this socket or service
*/
id: string;
/**
* Default: 'localhost'
* The local or remote host on which TCP, TLS or UDP Sockets should connect
* Should resolve to 127.0.0.1 or ::1 see the table below related to this
*/
networkHost: string;
/**
* Default: 8000
* The default port on which TCP, TLS, or UDP sockets should connect
*/
networkPort: number;
/**
* Default: 'utf8'
* the default encoding for data sent on sockets. Mostly used if rawBuffer is set to true.
* Valid values are : ascii utf8 utf16le ucs2 base64 hex
*/
encoding: "ascii" | "utf8" | "utf16le" | "ucs2" | "base64" | "hex";
/**
* Default: false
* If true, data will be sent and received as a raw node Buffer NOT an Object as JSON.
* This is great for Binary or hex IPC, and communicating with other processes in languages like C and C++
*/
rawBuffer: boolean;
/**
* Default: false
* Synchronous requests. Clients will not send new requests until the server answers
*/
sync: boolean;
/**
* Default: false
* Turn on/off logging default is false which means logging is on
*/
silent: boolean;
/**
* Default: true
* Turn on/off util.inspect colors for ipc.log
*/
logInColor: boolean;
/**
* Default: 5
* Set the depth for util.inspect during ipc.log
*/
logDepth: number;
/**
* Default: console.log
* The function which receives the output from ipc.log; should take a single string argument
*/
logger(msg: string): void;
/**
* Default: 100
* This is the max number of connections allowed to a socket. It is currently only being set on Unix Sockets.
* Other Socket types are using the system defaults
*/
maxConnections: number;
/**
* Default: 500
* This is the time in milliseconds a client will wait before trying to reconnect to a server if the connection is lost.
* This does not effect UDP sockets since they do not have a client server relationship like Unix Sockets and TCP Sockets
*/
retry: number;
/* */
/**
* Default: false
* if set, it represents the maximum number of retries after each disconnect before giving up
* and completely killing a specific connection
*/
maxRetries: boolean | number;
/**
* Default: false
* Defaults to false meaning clients will continue to retry to connect to servers indefinitely at the retry interval.
* If set to any number the client will stop retrying when that number is exceeded after each disconnect.
* If set to true in real time it will immediately stop trying to connect regardless of maxRetries.
* If set to 0, the client will NOT try to reconnect
*/
stopRetrying: boolean;
/**
* Default: true
* Defaults to true meaning that the module will take care of deleting the IPC socket prior to startup.
* If you use node-ipc in a clustered environment where there will be multiple listeners on the same socket,
* you must set this to false and then take care of deleting the socket in your own code.
*/
unlink: boolean;
/**
* Primarily used when specifying which interface a client should connect through.
* see the socket.connect documentation in the node.js api https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener
*/
interfaces: {
/** /**
* Default: false * Default: false
* If true, data will be sent and received as a raw node Buffer NOT an Object as JSON.
* This is great for Binary or hex IPC, and communicating with other processes in languages like C and C++
*/ */
rawBuffer: boolean;
localAddress?: boolean;
/** /**
* Default: false * Default: false
* Synchronous requests. Clients will not send new requests until the server answers
*/ */
sync: boolean;
localPort?: boolean;
/** /**
* Default: false * Default: false
* Turn on/off logging default is false which means logging is on
*/
silent: boolean;
/**
* Default: true
* Turn on/off util.inspect colors for ipc.log
*/
logInColor: boolean;
/**
* Default: 5
* Set the depth for util.inspect during ipc.log
*/
logDepth: number;
/**
* Default: console.log
* The function which receives the output from ipc.log; should take a single string argument
*/ */
logger(msg: string): void;
/**
* Default: 100
* This is the max number of connections allowed to a socket. It is currently only being set on Unix Sockets.
* Other Socket types are using the system defaults
*/
maxConnections: number;
/**
* Default: 500
* This is the time in milliseconds a client will wait before trying to reconnect to a server if the connection is lost.
* This does not effect UDP sockets since they do not have a client server relationship like Unix Sockets and TCP Sockets
*/
retry: number;
/* */
family?: boolean;
/** /**
* Default: false * Default: false
* if set, it represents the maximum number of retries after each disconnect before giving up
* and completely killing a specific connection
*/ */
maxRetries: boolean | number;
hints?: boolean;
/** /**
* Default: false * Default: false
* Defaults to false meaning clients will continue to retry to connect to servers indefinitely at the retry interval.
* If set to any number the client will stop retrying when that number is exceeded after each disconnect.
* If set to true in real time it will immediately stop trying to connect regardless of maxRetries.
* If set to 0, the client will NOT try to reconnect
*/
stopRetrying: boolean;
/**
* Default: true
* Defaults to true meaning that the module will take care of deleting the IPC socket prior to startup.
* If you use node-ipc in a clustered environment where there will be multiple listeners on the same socket,
* you must set this to false and then take care of deleting the socket in your own code.
*/ */
unlink: boolean;
/**
* Primarily used when specifying which interface a client should connect through.
* see the socket.connect documentation in the node.js api https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener
*/
interfaces: {
/**
* Default: false
*/
localAddress?: boolean;
/**
* Default: false
*/
localPort?: boolean;
/**
* Default: false
*/
family?: boolean;
/**
* Default: false
*/
hints?: boolean;
/**
* Default: false
*/
lookup?: boolean;
};
tls: {
rejectUnauthorized?: boolean;
public?: string;
private?: string;
};
}
lookup?: boolean;
};
tls: {
rejectUnauthorized?: boolean;
public?: string;
private?: string;
};
} }
export = NodeIPC
// declare const RootIPC: NodeIPC.IPC & { IPC: new () => NodeIPC.IPC };
// export = RootIPC;
} }
declare const RootIPC: NodeIPC.IPC & { IPC: new () => NodeIPC.IPC };
export = RootIPC;

+ 11
- 0
src/utils.ts View File

@ -0,0 +1,11 @@
/**
* Add better assurance that a generated file name will be safe
*/
export function safeTitleFileName(title: string) {
title = title.replace(/(?<=\S):\s/g, " - ");
title = title.replace(/[\<\>\|\:\/\\]/g, " ");
title = title.replace(/\s\&\s/g, " and ");
title = title.trim();
return title[0].toUpperCase() + title.slice(1);
}

+ 25
- 0
yarn.lock View File

@ -19,6 +19,13 @@
dependencies: dependencies:
defer-to-connect "^1.0.1" defer-to-connect "^1.0.1"
"@types/node-ipc@^9.1.3":
version "9.1.3"
resolved "https://registry.yarnpkg.com/@types/node-ipc/-/node-ipc-9.1.3.tgz#5381fbc910071083b28dd43225727877c108b361"
integrity sha512-ka7CPX9Dk2lwe4PxoZMLOwcQrtdcYe/7OKmH75fQbmt0jdKltWVkdGA81D5l55d0wNhkweHa3XmzFbt5C0ieOQ==
dependencies:
"@types/node" "*"
"@types/node@*", "@types/node@^14.14.41": "@types/node@*", "@types/node@^14.14.41":
version "14.14.41" version "14.14.41"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615"
@ -394,6 +401,14 @@ diff@^4.0.1:
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
diskusage@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/diskusage/-/diskusage-1.1.3.tgz#680d7dbf1b679168a195c9240eb3552cbd2c067b"
integrity sha512-EAyaxl8hy4Ph07kzlzGTfpbZMNAAAHXSZtNEMwdlnSd1noHzvA6HsgKt4fEMSvaEXQYLSphe5rPMxN4WOj0hcQ==
dependencies:
es6-promise "^4.2.5"
nan "^2.14.0"
dom-serializer@^1.0.1, dom-serializer@^1.3.1: dom-serializer@^1.0.1, dom-serializer@^1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.1.tgz#d845a1565d7c041a95e5dab62184ab41e3a519be" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.1.tgz#d845a1565d7c041a95e5dab62184ab41e3a519be"
@ -468,6 +483,11 @@ entities@^2.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
es6-promise@^4.2.5:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
@ -857,6 +877,11 @@ mz@^2.4.0:
object-assign "^4.0.1" object-assign "^4.0.1"
thenify-all "^1.0.0" thenify-all "^1.0.0"
nan@^2.14.0:
version "2.14.2"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
node-ipc@^9.1.4: node-ipc@^9.1.4:
version "9.1.4" version "9.1.4"
resolved "https://registry.yarnpkg.com/node-ipc/-/node-ipc-9.1.4.tgz#2acf962681afdac2602876d98fe6434d54d9bd3c" resolved "https://registry.yarnpkg.com/node-ipc/-/node-ipc-9.1.4.tgz#2acf962681afdac2602876d98fe6434d54d9bd3c"


Loading…
Cancel
Save