animepaste
Version:
Paste your favourite anime online
520 lines (497 loc) • 13.4 kB
TypeScript
import { VideoInfo as VideoInfo$2, VideoSource as VideoSource$1, VideoStore, EpisodeStore, MagnetStore, Episode } from '@animepaste/database';
export { VideoSource } from '@animepaste/database';
import Progress from 'cli-progress';
import * as mediainfo_js_dist_types from 'mediainfo.js/dist/types';
export { getBgmDmhy, getBgmId, getBgmLink, getBgmTitle } from '@animepaste/bangumi/utils';
type VideoStorePlatform = 'ali';
type VideoInfo$1 = VideoInfo$2<VideoStorePlatform>;
declare function b64encode(text: string): string;
declare function b64decode(text: string): string;
declare function hashFile(filepath: string): Promise<string>;
declare function createSingleProgress(): Progress.SingleBar;
interface ProgressBarOption<T> {
suffix?: (value: number, total: number, payload: T) => string;
}
declare function createProgressBar<T extends object>(option?: ProgressBarOption<T>): {
finish(): void;
println(text: string): void;
create(name: string, length: number): {
update(value: number, payload?: T): void;
increment(value: number, payload?: T): void;
};
};
interface DownloadPayload {
filepath: string;
url: string;
}
declare function download(...payloads: DownloadPayload[]): Promise<void>;
interface VideoInfo<T extends string = string> {
/**
* Storage type, only supports Ali OSS
*
* @default 'ali'
*/
platform: T;
/**
* Video ID
*/
videoId: string;
/**
* Video title
*/
title: string;
/**
* Creation time
*/
createdAt: string;
/**
* Cover image
*/
cover?: string;
/**
* Play urls
*/
playUrl: string[];
/**
* Video source
*/
source: VideoSource;
}
interface VideoSource {
magnetId?: string;
directory?: string;
hash?: string;
}
type CreateStore = () => Promise<Store>;
declare abstract class Store {
readonly platform: string;
constructor(platform: string);
init(): Promise<void>;
protected abstract doFetchVideoInfo(videoId: string, option?: StoreOption): Promise<VideoInfo$1 | undefined>;
protected abstract doUpload(filePath: string, option?: StoreOption): Promise<string | undefined>;
protected abstract doDelete(videoId: string): Promise<boolean>;
fetchVideoInfo(videoId: string): Promise<VideoInfo$1 | undefined>;
searchLocalVideo(filename: string): Promise<VideoInfo$1[]>;
listLocalVideos(): Promise<VideoInfo<"ali">[]>;
deleteVideo(videoId: string): Promise<void>;
upload(filepath: string, option?: StoreOption): Promise<VideoInfo$1 | undefined>;
}
interface StoreOption {
/**
* MagnetId
*/
magnetId?: string;
/**
* Max retry number
*/
retry?: number;
}
declare class AliStore extends Store {
private readonly accessKeyId;
private readonly accessKeySecret;
private readonly regionId;
private readonly vodClient;
constructor(config: AliStoreConfig);
private createUplodaVideo;
doUpload(filepath: string, option?: StoreOption): Promise<string | undefined>;
doDelete(videoId: string): Promise<boolean>;
doFetchVideoInfo(videoId: string): Promise<VideoInfo$1 | undefined>;
}
declare const createAliStore: CreateStore;
interface AliStoreConfig {
accessKeyId: string;
accessKeySecret: string;
regionId: string;
}
interface UploadResponse {
VideoId: string;
RequestId: string;
UploadAddress: {
Endpoint: string;
Bucket: string;
FileName: string;
};
UploadAuth: {
SecurityToken: string;
AccessKeyId: string;
AccessKeySecret: string;
Region: string;
Expiration: string;
ExpireUTCTime: string;
};
}
interface Checkpoint {
file: string;
name: string;
fileSize: number;
partSize: number;
uploadId: string;
doneParts: Array<{
number: number;
etag: string;
}>;
}
declare function useStore(type: 'ali'): CreateStore;
interface DownloadTask {
magnetURI: string;
filename?: string;
}
declare class TorrentClient {
private readonly client;
private readonly folder;
constructor(folder: string);
download(downloadTasks: DownloadTask[]): Promise<void>;
destroy(): Promise<void>;
}
declare function closeMediaInfo(): Promise<void>;
declare function getVideoInfo(filepath: string): Promise<{
general: mediainfo_js_dist_types.Track;
video: mediainfo_js_dist_types.Track;
audio: mediainfo_js_dist_types.Track;
}>;
declare function checkVideo(filepath: string): Promise<boolean>;
type AnimeType = 'tv' | 'web' | 'movie' | 'ova';
interface CliOption {
force: boolean;
}
interface RawPlan {
/**
* Plan name
*/
name: string;
/**
* Plan date
*/
date: Date;
/**
* Plan is onair or finish
*
* @default 'onair'
*/
state: 'onair' | 'finish';
/**
* Store platform
*
* @default 'ali'
*/
store: VideoStorePlatform;
/**
* Template string for names
*
* @default '[{fansub}] {title} - S{season}E{ep}.mp4'
*/
format?: string;
/**
* Enable upload bangumis to OSS
*
* @default true
*/
sync: boolean;
/**
* Onair list
*/
onair: OnairPlan[];
}
interface OnairPlan {
/**
* Anime name
*/
title: string;
/**
* Anime season
*
* This value may be inferred from the title or be set with the default value 1
*/
season: number;
/**
* Bangumi ID
*/
bgmId: string;
/**
* Plan is onair or finish
*
* @default 'onair'
*/
state: 'onair' | 'finish';
/**
* Fansub order
*/
fansub?: string[];
/**
* Specify play link
*
* Type string for other platform
*
* Type record for play urls
*/
link?: string | EpisodesInputList;
/**
* Specify the magnet id of some episode
*/
magnet?: EpisodesInputList;
/**
* Specify OSS source of some episode
*/
source?: EpisodesInputList;
/**
* Template string for names
*
* @default '[{fansub}] {title} - S{season}E{ep}.mp4'
*/
format: string;
/**
* Enable upload bangumis to OSS
*
* @default true
*/
sync: boolean;
/**
* Keywords for searching resources
*/
keywords?: string[];
}
type EpisodesInputList = Record<number, string> | string[];
interface SearchOption {
type: AnimeType;
raw?: boolean;
plan?: boolean;
year?: string;
month?: string;
title?: string;
fansub?: string[];
log?: boolean;
beginDate?: Date;
}
declare function userSearch(anime: string | undefined, option: SearchOption): Promise<void>;
declare function daemonSearch(bgmId: string, optionKeywords?: string[], option?: SearchOption): Promise<void>;
declare function search(bgm: {
bgmId: string;
titleCN: string;
}, keywords: string[], option?: SearchOption): Promise<void>;
declare function bangumiLink(bgmId: string): string;
interface OnairAnime {
title: string;
bgmId: string;
episodes: (OnairEpisode | OnlineEpisode)[];
link?: string;
}
interface OnlineEpisode {
/**
* 条目内的集数, 从 1 开始
*/
ep: number;
/**
* Play url
*/
playURL: string;
}
interface OnairEpisode {
/**
* 条目内的集数, 从 1 开始
*/
ep: number;
/**
* Video qulity
*/
quality: 1080 | 720;
/**
* Airdate
*/
creationTime: string;
/**
* Play url
*/
playURL: string;
/**
* Global storage config
*/
storage: {
type: string;
videoId: string;
source: VideoSource$1;
};
}
interface UserOption {
token: string;
baseURL: string;
onairIds?: Set<string>;
}
declare abstract class SyncClient {
/**
* Current onair bangumis
*/
readonly onair: OnairAnime[];
/**
* Onair bangumis to be uploaded
*/
readonly newOnair: OnairAnime[];
abstract fetchOnair(): Promise<OnairAnime[]>;
abstract syncOnair(): Promise<OnairAnime[]>;
abstract removeOnair(bgmId: string): void;
abstract updateOnair(onair: OnairAnime): void;
}
declare class LocalSyncClient extends SyncClient {
static init(): Promise<LocalSyncClient>;
fetchOnair(): Promise<OnairAnime[]>;
syncOnair(): Promise<OnairAnime[]>;
removeOnair(bgmId: string): void;
updateOnair(onair: OnairAnime): void;
}
declare class RemoteSyncClient extends SyncClient {
private static MAX_RETRY;
private readonly token;
private readonly api;
/**
* Mark whether onair anime is changed
*/
private dirty;
/**
* Filter all the ids of onair bangumis
*/
readonly onairIds: Set<string> | undefined;
constructor(option: UserOption);
static create(onairIds?: Set<string>): Promise<RemoteSyncClient>;
static init(): Promise<RemoteSyncClient>;
fetchOnair(): Promise<OnairAnime[]>;
syncOnair(): Promise<OnairAnime[]>;
removeOnair(bgmId: string): void;
updateOnair(onair: OnairAnime): void;
createToken(payload: TokenPayload): Promise<Required<TokenPayload> | undefined>;
listToken(): Promise<Required<TokenPayload & {
access: Access[];
}>[]>;
removeToken(token: string): Promise<boolean>;
removeVisitors(): Promise<string[] | undefined>;
}
interface TokenPayload {
token?: string;
type?: 'user' | 'admin' | 'visitor';
comment?: string;
}
interface Access {
ip: string;
count: number;
timestamp: number;
}
declare function initClient(): Promise<LocalSyncClient | RemoteSyncClient>;
interface GlobalConfig {
plans: string | string[];
sync: {
local?: boolean;
remote?: {
baseURL: string;
token: string;
};
};
store: {};
}
declare class GlobalContex {
static SpaceDirectory: string;
static ConfigFilename: string;
static DatabaseFilename: string;
cliOption: CliOption;
isDaemon: boolean;
readonly root: string;
readonly config: string;
readonly databaseFilepath: string;
readonly videoStore: VideoStore<VideoStorePlatform>;
readonly episodeStore: EpisodeStore;
readonly magnetStore: MagnetStore;
private _cacheRoot;
private _localRoot;
private configCache;
constructor();
get localRoot(): string;
get cacheRoot(): string;
init(option: CliOption): Promise<void>;
makeLocalAnimeRoot(title: string): Promise<string>;
loadConfig<T = any>(): Promise<T>;
getPlans(): Promise<RawPlan[]>;
getSyncConfig(): Promise<GlobalConfig['sync']>;
getRemoteConfig(): Promise<GlobalConfig['sync']['remote']>;
getStoreConfig<T = any>(key: string): Promise<T>;
/**
* Copy file from "src" to cache root
*
* @param src
*/
copyToCache(src: string): Promise<string>;
formatOnlineURL(baseURL: string, bgmId: string): string;
encodePath(src: string): string;
decodePath(src: string, filename?: string): string;
}
declare const context: GlobalContex;
interface DaemonStepOption {
/**
* Filter onair plan
*/
filter?: (onair: OnairPlan) => boolean;
/**
* Enable log
*/
log?: boolean;
}
declare class Daemon {
private plan;
private store;
private client;
/**
* Enable index
*
* @default 'true'
*/
private readonly enableIndex;
/**
* Enable upload
*
* @default 'true'
*/
private readonly enableUpload;
/**
* Enable sync onair list
*
* @default 'true'
*/
private readonly enableSync;
constructor(option: {
index: boolean;
upload: boolean;
sync: boolean;
});
init(): Promise<void>;
update(): Promise<void>;
initPlan({ log }?: DaemonStepOption): Promise<void>;
initClient(): Promise<void>;
private refreshDatabase;
/**
* Refresh episode magnet list
*
* Prerequisite: this.initPlan(), this.initClient()
*/
refreshEpisode({ log, filter }?: DaemonStepOption): Promise<void>;
private refreshStore;
private refreshAnime;
private syncPlaylist;
}
declare class Plan {
private readonly baseURL;
private readonly plans;
constructor(option: {
baseURL: string;
plans: RawPlan[];
});
static create(): Promise<Plan>;
[Symbol.iterator](): IterableIterator<RawPlan>;
onairs(): OnairPlan[];
printOnair(): void;
genEpisodes(allEpisodes: Episode[], fansubOrder: string[]): Episode[];
}
declare function startDaemon(option: {
once: boolean;
interval: number;
index: boolean;
upload: boolean;
sync: boolean;
}): Promise<void>;
declare function createDaemon(index?: boolean): Daemon;
export { AliStore, AliStoreConfig, Checkpoint, CreateStore, DownloadPayload, GlobalConfig, GlobalContex, OnairAnime, OnairEpisode, OnlineEpisode, Plan, ProgressBarOption, RemoteSyncClient, Store, StoreOption, SyncClient, TorrentClient, UploadResponse, UserOption, VideoInfo$1 as VideoInfo, VideoStorePlatform, b64decode, b64encode, bangumiLink, checkVideo, closeMediaInfo, context, createAliStore, createDaemon, createProgressBar, createSingleProgress, daemonSearch, download, getVideoInfo, hashFile, initClient, search, startDaemon, useStore, userSearch };