├── example
├── .babelrc
├── README.md
├── index.html
├── package.json
├── webpack.config.js
└── src
│ └── index.js
├── .babelrc
├── proto
├── magnet2torrent
│ ├── magnet2torrent.proto
│ ├── magnet2torrent_pb_service.js
│ ├── magnet2torrent_pb.d.ts
│ ├── magnet2torrent_pb_service.d.ts
│ └── magnet2torrent_pb.js
├── download-progress
│ ├── download-progress.proto
│ ├── download-progress_pb.d.ts
│ ├── download-progress_pb_service.d.ts
│ ├── download-progress_pb_service.js
│ └── download-progress_pb.js
├── url-store
│ ├── url-store.proto
│ ├── url-store_pb_service.js
│ ├── url-store_pb_service.d.ts
│ ├── url-store_pb.d.ts
│ └── url-store_pb.js
├── abuse-store
│ ├── abuse-store.proto
│ ├── abuse-store_pb_service.js
│ ├── abuse-store_pb_service.d.ts
│ ├── abuse-store_pb.d.ts
│ └── abuse-store_pb.js
├── torrent-store
│ ├── torrent-store.proto
│ ├── torrent-store_pb_service.js
│ ├── torrent-store_pb_service.d.ts
│ └── torrent-store_pb.d.ts
└── torrent-web-seeder
│ ├── torrent-web-seeder.proto
│ ├── torrent-web-seeder_pb_service.d.ts
│ ├── torrent-web-seeder_pb_service.js
│ └── torrent-web-seeder_pb.d.ts
├── webpack.config.js
├── src
├── sdk
│ ├── tracker.js
│ ├── process.js
│ ├── abuse.js
│ ├── magnet.js
│ ├── ext.js
│ ├── seeder
│ │ ├── downloadProgress.js
│ │ └── stats.js
│ ├── loader
│ │ └── torrent
│ │ │ └── resource.js
│ ├── torrent.js
│ ├── loader.js
│ ├── seeder.js
│ └── util.js
└── index.js
├── .github
└── FUNDING.yml
├── .eslintrc.js
├── LICENSE
├── .gitignore
├── package.json
└── README.md
/example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"]
3 | }
4 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"],
3 | "plugins": [
4 | "@babel/plugin-proposal-class-properties",
5 | "@babel/transform-runtime"
6 | // "transform-decorators-legacy"
7 | ],
8 | "env": {
9 | "production": {
10 | // "presets": ["minify"]
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Example usage
2 |
3 | 1. Install dependencies
4 |
5 | ```bash
6 | npm install
7 | ```
8 |
9 | 2. Change `apiUrl` at `src/index.js` to yours
10 | 3. Rebuild `dist/index.js` with:
11 |
12 | ```bash
13 | npm run build
14 | ```
15 |
16 | 4. Open `index.html` in your browser.
17 |
--------------------------------------------------------------------------------
/proto/magnet2torrent/magnet2torrent.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | service Magnet2Torrent {
4 | // Converts magnet uri to torrent file
5 | rpc Magnet2Torrent (Magnet2TorrentRequest) returns (Magnet2TorrentReply) {}
6 | }
7 |
8 | // The request message containing the magnet url
9 | message Magnet2TorrentRequest {
10 | string magnet = 1;
11 | }
12 |
13 | // The response message containing the torrent
14 | message Magnet2TorrentReply {
15 | bytes torrent = 1;
16 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | mode: 'production',
5 | entry: './src/index.js',
6 | output: {
7 | path: path.resolve('dist'),
8 | filename: 'index.js',
9 | libraryTarget: 'commonjs2',
10 | },
11 | module: {
12 | rules: [
13 | {
14 | test: /\.js?$/,
15 | exclude: /(node_modules)/,
16 | use: 'babel-loader',
17 | },
18 | ],
19 | },
20 | node: {
21 | fs: 'empty',
22 | },
23 | resolve: {
24 | extensions: ['.js'],
25 | },
26 | };
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Webtor Platform SDK Example
5 |
6 |
7 | Sintel.mp4
8 | The Fanimatrix.avi
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/sdk/tracker.js:
--------------------------------------------------------------------------------
1 | const Url = require('url-parse');
2 |
3 | export default function(params, sdk) {
4 | const self = {params, sdk};
5 | return {
6 | async url(metadata = {}, params = {}) {
7 | params = Object.assign(self.params, params);
8 | const url = new Url(params.apiUrl);
9 | const pathname = '/tracker/';
10 | url.set('pathname', pathname);
11 | url.set('protocol', 'wss:');
12 | const query = await self.sdk.util.makeQuery(metadata, params);
13 | url.set('query', query);
14 | return url;
15 | },
16 | };
17 | };
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: pavel_tatarskiy
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/proto/download-progress/download-progress.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option go_package = "github.com/webtor-io/download-progress;download_progress";
4 |
5 | service DownloadProgress {
6 | // Get download stat
7 | rpc Stat (StatRequest) returns (StatReply) {}
8 | // Get download stat stream
9 | rpc StatStream (StatRequest) returns (stream StatReply) {}
10 | }
11 |
12 | // Stat request message
13 | message StatRequest {
14 | }
15 |
16 | // Stat response message
17 | message StatReply {
18 | enum Status {
19 | NOT_STARTED = 0;
20 | PENDING = 1;
21 | ACTIVE = 2;
22 | DONE = 3;
23 | FAILED = 4;
24 | }
25 | Status status = 1;
26 | int64 downloaded = 2;
27 | int64 rate = 3;
28 | int64 length = 4;
29 | }
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "webpack",
9 | "watch": "webpack --watch"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "MIT",
14 | "devDependencies": {
15 | "css-loader": "^5.2.0",
16 | "style-loader": "^2.0.0",
17 | "webpack": "^4.46.0",
18 | "webpack-cli": "^3.3.12"
19 | },
20 | "dependencies": {
21 | "@babel/core": "^7.13.14",
22 | "@babel/preset-env": "^7.13.12",
23 | "@webtor/platform-sdk-js": "^0.2.14",
24 | "babel-loader": "^8.2.2",
25 | "video.js": "^7.11.4",
26 | "videojs-contrib-hls": "^5.15.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/proto/url-store/url-store.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package webtor.url_store;
4 | option go_package = "github.com/webtor-io/url-store;url_store";
5 |
6 | service UrlStore {
7 | // Pushes url to the store
8 | rpc Push (PushRequest) returns (PushReply) {}
9 |
10 | // Check url existence in the store
11 | rpc Check (CheckRequest) returns (CheckReply) {}
12 | }
13 |
14 | // The push response message
15 | message PushReply {
16 | string hash = 1;
17 | }
18 |
19 | // The push request message
20 | message PushRequest {
21 | string url = 1;
22 | }
23 |
24 | // The check request message containing the infoHash
25 | message CheckRequest {
26 | string hash = 1;
27 | }
28 |
29 | // The check response message containing existance flag
30 | message CheckReply {
31 | bool exists = 1;
32 | }
33 |
--------------------------------------------------------------------------------
/example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | entry: './src/index.js',
5 | output: {
6 | filename: 'index.js',
7 | path: path.resolve(__dirname, 'dist'),
8 | },
9 | mode: 'production',
10 | node: {
11 | fs: 'empty'
12 | },
13 | module: {
14 | rules: [
15 | {
16 | test: /\.js?$/,
17 | exclude: /(node_modules)/,
18 | use: 'babel-loader',
19 | },
20 | {
21 | test: /\.css$/i,
22 | use: ['style-loader', 'css-loader'],
23 | },
24 | ],
25 | },
26 | // node: {
27 | // fs: 'empty',
28 | // },
29 | // resolve: {
30 | // extensions: ['.js'],
31 | // },
32 | };
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // "extends": ["google", "plugin:vue/recommended"],
3 | "extends": ["google"],
4 | "parser": "babel-eslint",
5 | "parserOptions": {
6 | "sourceType": "module",
7 | "ecmaVersion": 8,
8 | "ecmaFeatures": {
9 | "experimentalObjectRestSpread": true
10 | }
11 | },
12 | "rules": {
13 | "max-len": [2, 80, 4, {"ignoreUrls": true, "ignoreStrings": true,
14 | "ignoreComments": true, "ignoreTemplateLiterals": true}],
15 | "require-jsdoc": "off",
16 | "no-invalid-this": "off",
17 | "chai-expect/missing-assertion": 2,
18 | "chai-expect/terminating-properties": 1,
19 | "mocha/no-exclusive-tests": 2
20 | },
21 | "plugins": [
22 | "eslint-plugin-html",
23 | "mocha",
24 | "chai-expect",
25 | "vue"
26 | ]
27 | };
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 webtor.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/proto/abuse-store/abuse-store.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | service AbuseStore {
4 | // Pushes abuse to the store
5 | rpc Push (PushRequest) returns (PushReply) {}
6 |
7 | // Check abuse in the store for existence
8 | rpc Check (CheckRequest) returns (CheckReply) {}
9 | }
10 |
11 | // The push response message containing
12 | message PushReply {
13 | }
14 |
15 | // The push request message
16 | message PushRequest {
17 | string notice_id = 1;
18 | string infohash = 2;
19 | string filename = 3;
20 | string work = 4;
21 | int64 started_at = 5;
22 | string email = 6;
23 | string description = 7;
24 | string subject = 8;
25 | enum Cause {
26 | ILLEGAL_CONTENT = 0;
27 | MALWARE = 1;
28 | APP_ERROR = 2;
29 | QUESTION = 3;
30 | }
31 | Cause cause = 9;
32 | enum Source {
33 | MAIL = 0;
34 | FORM = 1;
35 | }
36 | Source source = 10;
37 | }
38 |
39 | // The check request message containing the infoHash
40 | message CheckRequest {
41 | string infohash = 1;
42 | }
43 |
44 | // The check response message containing existance flag
45 | message CheckReply {
46 | bool exists = 1;
47 | }
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | .yalc
61 |
62 | .DS_Store
63 |
64 | example/node_modules/
--------------------------------------------------------------------------------
/proto/torrent-store/torrent-store.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | service TorrentStore {
4 | // Pushes torrent to the store
5 | rpc Push (PushRequest) returns (PushReply) {}
6 |
7 | // Pulls torrent from the store
8 | rpc Pull (PullRequest) returns (PullReply) {}
9 |
10 | // Touch torrent in the store
11 | rpc Touch (TouchRequest) returns (TouchReply) {}
12 | }
13 |
14 | // The push response message containing info hash of the pushed torrent file
15 | message PushReply {
16 | string infoHash = 1;
17 | }
18 |
19 | // The push request message containing the torrent and expire duration is seconds
20 | message PushRequest {
21 | bytes torrent = 1;
22 | int32 expire = 2 [deprecated=true];
23 | }
24 |
25 | // The pull request message containing the infoHash
26 | message PullRequest {
27 | string infoHash = 1;
28 | }
29 |
30 | // The pull response message containing the torrent
31 | message PullReply {
32 | bytes torrent = 1;
33 | }
34 |
35 | // The check request message containing the infoHash
36 | message CheckRequest {
37 | string infoHash = 1;
38 | }
39 |
40 | // The check response message containing existance flag
41 | message CheckReply {
42 | bool exists = 1;
43 | }
44 |
45 | // The touch response message
46 | message TouchReply {
47 | }
48 |
49 | // The touch request message containing the torrent and expire duration is seconds
50 | message TouchRequest {
51 | string infoHash = 1;
52 | int32 expire = 2 [deprecated=true];
53 | }
--------------------------------------------------------------------------------
/proto/torrent-web-seeder/torrent-web-seeder.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | service TorrentWebSeeder {
4 | // Get file stat
5 | rpc Stat (StatRequest) returns (StatReply) {}
6 | // Get file stat stream
7 | rpc StatStream (StatRequest) returns (stream StatReply) {}
8 | // Get file list
9 | rpc Files (FilesRequest) returns (FilesReply) {}
10 | }
11 |
12 | // Stat request message
13 | message StatRequest {
14 | string path = 1;
15 | }
16 |
17 | // Stat response message
18 | message StatReply {
19 | int64 total = 1;
20 | int64 completed = 2;
21 | int32 peers = 3;
22 | enum Status {
23 | INITIALIZATION = 0;
24 | SEEDING = 1;
25 | IDLE = 2;
26 | TERMINATED = 3;
27 | WAITING_FOR_PEERS = 4;
28 | RESTORING = 5;
29 | BACKINGUP = 6;
30 | }
31 | Status status = 4;
32 | repeated Piece pieces = 5;
33 | int32 seeders = 6;
34 | int32 leechers = 7;
35 | }
36 |
37 | message Piece {
38 | int64 position = 1;
39 | bool complete = 2;
40 | enum Priority {
41 | NONE = 0;
42 | NORMAL = 1;
43 | HIGH = 2;
44 | READAHEAD = 3;
45 | NEXT = 4;
46 | NOW = 5;
47 | }
48 | Priority priority = 3;
49 | }
50 |
51 | // Files requst message
52 | message FilesRequest {
53 | }
54 |
55 | message File {
56 | string path = 1;
57 | }
58 |
59 | // Files reply message
60 | message FilesReply {
61 | repeated File files = 1;
62 | }
63 |
--------------------------------------------------------------------------------
/src/sdk/process.js:
--------------------------------------------------------------------------------
1 | import {grpc} from '@improbable-eng/grpc-web';
2 |
3 | const debug = require('debug')('webtor:sdk');
4 |
5 | export default async function(client, request, onMessage, onEnd, metadata = {}, params = {}) {
6 | metadata['token'] = await params.getToken();
7 | metadata['api-key'] = params.apiKey;
8 | let retryCount = 0;
9 | return new Promise(function(resolve, reject) {
10 | function process() {
11 | const c = client();
12 | if (onMessage) {
13 | c.onMessage((message) => {
14 | debug('got message=%o', message.toObject());
15 | onMessage(message.toObject(), resolve, reject);
16 | });
17 | }
18 | if (onEnd) {
19 | c.onEnd(async (res) => {
20 | if ((res == grpc.Code.Unknown || res == grpc.Code.Unavailable) && params.retryInterval && params.retryLimit > 0 && retryCount < params.retryLimit) {
21 | debug('failed to get process request error=%o retry count=%o', res, retryCount);
22 | await (new Promise(resolve => setTimeout(resolve, params.retryInterval)));
23 | retryCount++;
24 | process();
25 | } else {
26 | onEnd(res, resolve, reject);
27 | }
28 | });
29 | }
30 | c.start(new grpc.Metadata(metadata));
31 | c.send(request);
32 | c.finishSend();
33 | }
34 | process();
35 | });
36 | }
37 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@webtor/platform-sdk-js",
3 | "version": "0.2.18",
4 | "description": "SDK for online torrent streaming",
5 | "main": "src/index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/webtor-io/platform-sdk-js"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1",
12 | "build": "webpack --mode production",
13 | "watch": "webpack --watch",
14 | "protoc": "ls proto/ | xargs -I{} protoc --plugin='protoc-gen-ts=./node_modules/.bin/protoc-gen-ts' --js_out='import_style=commonjs_strict,binary:.' --ts_out='service=grpc-web:.' ./proto/{}/{}.proto"
15 | },
16 | "keywords": [
17 | "webtor",
18 | "torrent",
19 | "streaming",
20 | "sdk"
21 | ],
22 | "homepage": "https://webtor.io",
23 | "author": "Pavel Tatarskiy",
24 | "license": "MIT",
25 | "devDependencies": {
26 | "@babel/core": "^7.7.7",
27 | "@babel/plugin-proposal-class-properties": "^7.7.4",
28 | "@babel/plugin-transform-runtime": "^7.7.6",
29 | "@babel/preset-env": "^7.7.7",
30 | "babel-loader": "^8.0.6",
31 | "webpack": "^4.41.5",
32 | "webpack-cli": "^3.3.10"
33 | },
34 | "dependencies": {
35 | "@babel/runtime": "^7.7.7",
36 | "@improbable-eng/grpc-web": "^0.12.0",
37 | "debug": "^4.3.3",
38 | "fetch-retry": "^3.1.0",
39 | "google-protobuf": "^3.11.2",
40 | "iso-639-1": "^2.1.0",
41 | "lodash": "^4.17.15",
42 | "md5": "^2.3.0",
43 | "mime": "^2.4.4",
44 | "parse-torrent": "^7.0.1",
45 | "path-parse": "^1.0.6",
46 | "url-parse": "^1.4.7"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/sdk/abuse.js:
--------------------------------------------------------------------------------
1 | import {AbuseStore} from '../../proto/abuse-store/abuse-store_pb_service';
2 | import {PushRequest} from '../../proto/abuse-store/abuse-store_pb';
3 | import {grpc} from '@improbable-eng/grpc-web';
4 | import process from './process';
5 | const debug = require('debug')('webtor:sdk:abuse');
6 |
7 | export default function(params = {}) {
8 | const self = {params};
9 | return {
10 | push(abuse, metadata = {}, params = {}) {
11 | params = Object.assign(self.params, params);
12 | const url = params.apiUrl + '/abuse';
13 | debug('push abuse url=%s metadata=%o', url, metadata);
14 | const request = new PushRequest();
15 | request.setSubject(abuse.subject);
16 | request.setDescription(abuse.description);
17 | request.setInfohash(abuse.infohash);
18 | request.setFilename(abuse.filename);
19 | request.setEmail(abuse.email);
20 | request.setWork(abuse.work);
21 | request.setCause(abuse.cause);
22 | request.setSource(PushRequest.Source.FORM);
23 | const client = () => grpc.client(AbuseStore.Push, {
24 | host: url,
25 | // transport: grpc.WebsocketTransport(),
26 | debug: params.grpcDebug,
27 | });
28 | const onEnd = (res, resolve, reject) => {
29 | if (res === grpc.Code.OK) {
30 | debug('abuse stored');
31 | resolve();
32 | } else {
33 | reject('failed to push abuse code=' + res);
34 | }
35 | }
36 | return process(client, request, null, onEnd, metadata, params);
37 | },
38 | };
39 | };
--------------------------------------------------------------------------------
/src/sdk/magnet.js:
--------------------------------------------------------------------------------
1 | import {Magnet2Torrent} from '../../proto/magnet2torrent/magnet2torrent_pb_service';
2 | import {Magnet2TorrentRequest} from '../../proto/magnet2torrent/magnet2torrent_pb';
3 | import {grpc} from '@improbable-eng/grpc-web';
4 | import process from './process';
5 | import parseTorrent from 'parse-torrent';
6 | const debug = require('debug')('webtor:sdk:magnet');
7 |
8 | export default function(params = {}) {
9 | const self = {params};
10 | return {
11 | fetchTorrent(magnet, metadata = {}, params = {}) {
12 | params = Object.assign(self.params, params);
13 | const url = params.apiUrl + '/magnet2torrent';
14 | debug('fetch torrent magnet=%s url=%s metadata=%o', magnet, url, metadata);
15 | const request = new Magnet2TorrentRequest();
16 | request.setMagnet(magnet);
17 | const client = () => grpc.client(Magnet2Torrent.Magnet2Torrent, {
18 | host: url,
19 | transport: grpc.WebsocketTransport(),
20 | debug: params.grpcDebug,
21 | });
22 | const onMessage = (message, resolve, reject) => {
23 | if (message.torrent == '') {
24 | return reject('no torrent');
25 | }
26 | let torrent = Buffer.from(message.torrent, 'base64');
27 | torrent = parseTorrent(torrent);
28 | debug('and finally torrent=%o', torrent);
29 | resolve(torrent);
30 | }
31 | const onEnd = (res, resolve, reject) => {
32 | if (res !== grpc.Code.OK) {
33 | reject('failed to fetch torrent code=' + res);
34 | }
35 | }
36 | return process(client, request, onMessage, onEnd, metadata, params);
37 | },
38 | };
39 | };
--------------------------------------------------------------------------------
/src/sdk/ext.js:
--------------------------------------------------------------------------------
1 | const pathParse = require('path-parse');
2 | const Url = require('url-parse');
3 |
4 | export default function(params, sdk) {
5 | const self = {params, sdk};
6 | return {
7 | async url(extUrl, metadata = {}, params = {}) {
8 | params = Object.assign(self.params, params);
9 | const url = new Url(params.apiUrl);
10 | let fileName = "";
11 | if (params.fileName) {
12 | fileName = params.fileName;
13 | } else {
14 | fileName = pathParse(extUrl).base;
15 | }
16 | const encodedUrl = encodeURIComponent(btoa(extUrl));
17 | const pathname = '/ext/' + encodedUrl + '/' + fileName;
18 | url.set('pathname', pathname);
19 | const query = await self.sdk.util.makeQuery(metadata, params);
20 | url.set('query', query);
21 | return url;
22 | },
23 | async streamSubtitleUrl(extUrl, metadata = {}, params = {}) {
24 | const url = await this.url(extUrl, metadata, params);
25 | return self.sdk.util.streamSubtitleUrl(url);
26 | },
27 | async streamUrl(extUrl, metadata = {}, params = {}) {
28 | params = Object.assign({}, this.params, params);
29 | let url = await this.url(extUrl, metadata, params);
30 | return self.sdk.util.streamUrl(url, metadata, params);
31 | },
32 | async mediaInfo(extUrl, metadata = {}, params = {}) {
33 | const url = await this.url(extUrl, metadata, params);
34 | return await self.sdk.util.mediaInfo(url);
35 | },
36 | async openSubtitles(extUrl, metadata = {}, params = {}) {
37 | const url = await this.url(extUrl, metadata, params);
38 | return await self.sdk.util.openSubtitles(url);
39 | },
40 | };
41 | };
--------------------------------------------------------------------------------
/proto/magnet2torrent/magnet2torrent_pb_service.js:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/magnet2torrent/magnet2torrent.proto
3 |
4 | var proto_magnet2torrent_magnet2torrent_pb = require("../../proto/magnet2torrent/magnet2torrent_pb");
5 | var grpc = require("@improbable-eng/grpc-web").grpc;
6 |
7 | var Magnet2Torrent = (function () {
8 | function Magnet2Torrent() {}
9 | Magnet2Torrent.serviceName = "Magnet2Torrent";
10 | return Magnet2Torrent;
11 | }());
12 |
13 | Magnet2Torrent.Magnet2Torrent = {
14 | methodName: "Magnet2Torrent",
15 | service: Magnet2Torrent,
16 | requestStream: false,
17 | responseStream: false,
18 | requestType: proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentRequest,
19 | responseType: proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentReply
20 | };
21 |
22 | exports.Magnet2Torrent = Magnet2Torrent;
23 |
24 | function Magnet2TorrentClient(serviceHost, options) {
25 | this.serviceHost = serviceHost;
26 | this.options = options || {};
27 | }
28 |
29 | Magnet2TorrentClient.prototype.magnet2Torrent = function magnet2Torrent(requestMessage, metadata, callback) {
30 | if (arguments.length === 2) {
31 | callback = arguments[1];
32 | }
33 | var client = grpc.unary(Magnet2Torrent.Magnet2Torrent, {
34 | request: requestMessage,
35 | host: this.serviceHost,
36 | metadata: metadata,
37 | transport: this.options.transport,
38 | debug: this.options.debug,
39 | onEnd: function (response) {
40 | if (callback) {
41 | if (response.status !== grpc.Code.OK) {
42 | var err = new Error(response.statusMessage);
43 | err.code = response.status;
44 | err.metadata = response.trailers;
45 | callback(err, null);
46 | } else {
47 | callback(null, response.message);
48 | }
49 | }
50 | }
51 | });
52 | return {
53 | cancel: function () {
54 | callback = null;
55 | client.close();
56 | }
57 | };
58 | };
59 |
60 | exports.Magnet2TorrentClient = Magnet2TorrentClient;
61 |
62 |
--------------------------------------------------------------------------------
/proto/magnet2torrent/magnet2torrent_pb.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/magnet2torrent/magnet2torrent.proto
3 |
4 | import * as jspb from "google-protobuf";
5 |
6 | export class Magnet2TorrentRequest extends jspb.Message {
7 | getMagnet(): string;
8 | setMagnet(value: string): void;
9 |
10 | serializeBinary(): Uint8Array;
11 | toObject(includeInstance?: boolean): Magnet2TorrentRequest.AsObject;
12 | static toObject(includeInstance: boolean, msg: Magnet2TorrentRequest): Magnet2TorrentRequest.AsObject;
13 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
14 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
15 | static serializeBinaryToWriter(message: Magnet2TorrentRequest, writer: jspb.BinaryWriter): void;
16 | static deserializeBinary(bytes: Uint8Array): Magnet2TorrentRequest;
17 | static deserializeBinaryFromReader(message: Magnet2TorrentRequest, reader: jspb.BinaryReader): Magnet2TorrentRequest;
18 | }
19 |
20 | export namespace Magnet2TorrentRequest {
21 | export type AsObject = {
22 | magnet: string,
23 | }
24 | }
25 |
26 | export class Magnet2TorrentReply extends jspb.Message {
27 | getTorrent(): Uint8Array | string;
28 | getTorrent_asU8(): Uint8Array;
29 | getTorrent_asB64(): string;
30 | setTorrent(value: Uint8Array | string): void;
31 |
32 | serializeBinary(): Uint8Array;
33 | toObject(includeInstance?: boolean): Magnet2TorrentReply.AsObject;
34 | static toObject(includeInstance: boolean, msg: Magnet2TorrentReply): Magnet2TorrentReply.AsObject;
35 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
36 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
37 | static serializeBinaryToWriter(message: Magnet2TorrentReply, writer: jspb.BinaryWriter): void;
38 | static deserializeBinary(bytes: Uint8Array): Magnet2TorrentReply;
39 | static deserializeBinaryFromReader(message: Magnet2TorrentReply, reader: jspb.BinaryReader): Magnet2TorrentReply;
40 | }
41 |
42 | export namespace Magnet2TorrentReply {
43 | export type AsObject = {
44 | torrent: Uint8Array | string,
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import torrent from './sdk/torrent';
2 | import magnet from './sdk/magnet';
3 | import abuse from './sdk/abuse';
4 | import seeder from './sdk/seeder';
5 | import tracker from './sdk/tracker';
6 | import loader from './sdk/loader';
7 | import util from './sdk/util';
8 | import ext from './sdk/ext';
9 | import throttle from 'lodash/throttle';
10 |
11 | const defaultParams = {
12 | db: null,
13 | grpcDebug: false,
14 | retryInterval: 1000,
15 | retryLimit: 3,
16 | cache: false,
17 | multibitrate: false,
18 | vod: false,
19 | pools: {
20 | cache: [],
21 | seeder: [],
22 | transcoder: [],
23 | },
24 | subdomains: false,
25 | async getToken() {
26 | return null;
27 | },
28 | endpoints: {
29 | torrent: '/store'
30 | },
31 | tokenRenewInterval: 60000,
32 | }
33 |
34 | function sdk(params = {}) {
35 | params = Object.assign(defaultParams, params);
36 | if (params.tokenUrl) {
37 | params.getToken = async () => {
38 | const res = await fetch(params.tokenUrl);
39 | return res.text();
40 | }
41 | }
42 | if (params.tokenRenewInterval) {
43 | const t = params.getToken;
44 | params.getToken = throttle(t, params.tokenRenewInterval, {
45 | trailing: false,
46 | });
47 | }
48 |
49 | let sdk = {};
50 |
51 | sdk = Object.assign(sdk, {
52 | params,
53 | tracker: tracker(params, sdk),
54 | seeder: seeder(params, sdk),
55 | ext: ext(params, sdk),
56 | magnet: magnet(params, sdk),
57 | torrent: torrent(params, sdk),
58 | abuse: abuse(params, sdk),
59 | util: util(params, sdk),
60 | loader: loader(params, sdk),
61 | });
62 | sdk.load = (source, metadata = {}, params = {}) => {
63 | return sdk.loader.load(source, metadata, params);
64 | };
65 | sdk.loadById = (type, id, metadata = {}, params = {}) => {
66 | return sdk.loader.loadById(type, id, metadata, params);
67 | };
68 |
69 | return sdk;
70 |
71 | };
72 |
73 | export default function(params = {}) {
74 | return sdk(params);
75 | }
--------------------------------------------------------------------------------
/src/sdk/seeder/downloadProgress.js:
--------------------------------------------------------------------------------
1 | import {DownloadProgress} from '../../../proto/download-progress/download-progress_pb_service';
2 | import {StatRequest, StatReply} from '../../../proto/download-progress/download-progress_pb';
3 | import {grpc} from '@improbable-eng/grpc-web';
4 | import process from '../process';
5 | const debug = require('debug')('webtor:sdk:seeder:downloadProgress');
6 | import invert from 'lodash/invert';
7 |
8 | class Stats {
9 | constructor(url, path) {
10 | this.url = url;
11 | this.path = path;
12 | this.closed = false;
13 | this.client = null;
14 | }
15 | close() {
16 | if (this.closed) return;
17 | this.closed = true;
18 | debug('close download progress url=%o path=%o', this.url, this.path);
19 | if (this.client) this.client.close();
20 | }
21 | start(onMessage, onEnd, metadata, params) {
22 | const request = new StatRequest();
23 | const client = () => {
24 | const c = grpc.client(DownloadProgress.StatStream, {
25 | host: this.url,
26 | transport: grpc.WebsocketTransport(),
27 | debug: params.grpcDebug,
28 | });
29 | this.client = c;
30 | return c;
31 | };
32 | const statuses = invert(StatReply.Status);
33 | const onMessageWrapper = (message) => {
34 | message.statusName = statuses[message.status];
35 | onMessage(this.path, message);
36 | }
37 | const onEndWrapper = (res, resolve, reject) => {
38 | if (res !== grpc.Code.OK) {
39 | reject('failed to get download progress code=' + res);
40 | } else {
41 | debug('download progress finished url=%o path=%o', this.url, this.path);
42 | this.close();
43 | resolve();
44 | }
45 | onEnd(this.path, res);
46 | }
47 |
48 | return process(client, request, onMessageWrapper, onEndWrapper, metadata, params);
49 | }
50 | }
51 |
52 | export default function(url, path, onMessage, onEnd, metadata = {}, params = {}) {
53 | const st = new Stats(url, path);
54 | st.start(onMessage, onEnd, metadata, params);
55 | return st;
56 | }
--------------------------------------------------------------------------------
/example/src/index.js:
--------------------------------------------------------------------------------
1 | import webtor from '@webtor/platform-sdk-js';
2 | import 'video.js/dist/video-js.css';
3 | import videojs from 'video.js';
4 | // import hls from 'videojs-contrib-hls';
5 | const parseTorrent = require('parse-torrent');
6 |
7 | async function main() {
8 | const links = document.querySelectorAll('a[data-magnet]');
9 | for (const l of links) {
10 | l.addEventListener('click', function (e) {
11 | const m = e.target.getAttribute('data-magnet');
12 | run(m);
13 | e.preventDefault();
14 | return false;
15 | });
16 | }
17 | }
18 |
19 | async function run(magnetUri) {
20 | const link = document.querySelector('#download');
21 | link.setAttribute('target', '_blank');
22 | link.innerHTML = 'loading...';
23 | const status = document.querySelector('#status')
24 | status.innerHTML = '';
25 |
26 | const sdk = webtor({
27 | apiUrl: 'http://127.0.0.1:32476', // you should change this
28 | });
29 |
30 | let torrent = parseTorrent(magnetUri);
31 |
32 | try {
33 | torrent = await sdk.torrent.pull(torrent.infoHash);
34 | } catch (e) {
35 | console.log(e);
36 | torrent = null;
37 | }
38 |
39 | if (!torrent) {
40 | torrent = await sdk.magnet.fetchTorrent(magnetUri);
41 | }
42 |
43 | const expire = 60*60*24;
44 |
45 | await sdk.torrent.push(torrent, expire);
46 |
47 | const seeder = sdk.seeder.get(torrent.infoHash);
48 |
49 | let filePath = null;
50 |
51 | for (const f of torrent.files) {
52 | if (sdk.util.getMediaType(f.path) == 'video') {
53 | filePath = f.path;
54 | }
55 | }
56 |
57 | const url = await seeder.streamUrl(filePath);
58 |
59 | const v = videojs("webtor");
60 | v.src({
61 | src: url.toString(),
62 | });
63 |
64 | link.setAttribute('href', url.toString());
65 | link.innerHTML = filePath;
66 |
67 | // NOTE: stats will become available only after content url access
68 | seeder.stats(filePath, (path, data) => {
69 | console.log(data);
70 | status.innerHTML = 'total: ' + data.total;
71 | status.innerHTML += ' completed: ' + data.completed;
72 | status.innerHTML += ' peers: ' + data.peers;
73 | });
74 | }
75 |
76 | main();
--------------------------------------------------------------------------------
/proto/download-progress/download-progress_pb.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/download-progress/download-progress.proto
3 |
4 | import * as jspb from "google-protobuf";
5 |
6 | export class StatRequest extends jspb.Message {
7 | serializeBinary(): Uint8Array;
8 | toObject(includeInstance?: boolean): StatRequest.AsObject;
9 | static toObject(includeInstance: boolean, msg: StatRequest): StatRequest.AsObject;
10 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
11 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
12 | static serializeBinaryToWriter(message: StatRequest, writer: jspb.BinaryWriter): void;
13 | static deserializeBinary(bytes: Uint8Array): StatRequest;
14 | static deserializeBinaryFromReader(message: StatRequest, reader: jspb.BinaryReader): StatRequest;
15 | }
16 |
17 | export namespace StatRequest {
18 | export type AsObject = {
19 | }
20 | }
21 |
22 | export class StatReply extends jspb.Message {
23 | getStatus(): StatReply.StatusMap[keyof StatReply.StatusMap];
24 | setStatus(value: StatReply.StatusMap[keyof StatReply.StatusMap]): void;
25 |
26 | getDownloaded(): number;
27 | setDownloaded(value: number): void;
28 |
29 | getRate(): number;
30 | setRate(value: number): void;
31 |
32 | getLength(): number;
33 | setLength(value: number): void;
34 |
35 | serializeBinary(): Uint8Array;
36 | toObject(includeInstance?: boolean): StatReply.AsObject;
37 | static toObject(includeInstance: boolean, msg: StatReply): StatReply.AsObject;
38 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
39 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
40 | static serializeBinaryToWriter(message: StatReply, writer: jspb.BinaryWriter): void;
41 | static deserializeBinary(bytes: Uint8Array): StatReply;
42 | static deserializeBinaryFromReader(message: StatReply, reader: jspb.BinaryReader): StatReply;
43 | }
44 |
45 | export namespace StatReply {
46 | export type AsObject = {
47 | status: StatReply.StatusMap[keyof StatReply.StatusMap],
48 | downloaded: number,
49 | rate: number,
50 | length: number,
51 | }
52 |
53 | export interface StatusMap {
54 | NOT_STARTED: 0;
55 | PENDING: 1;
56 | ACTIVE: 2;
57 | DONE: 3;
58 | FAILED: 4;
59 | }
60 |
61 | export const Status: StatusMap;
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/src/sdk/seeder/stats.js:
--------------------------------------------------------------------------------
1 | import {TorrentWebSeeder} from '../../../proto/torrent-web-seeder/torrent-web-seeder_pb_service';
2 | import {StatRequest, StatReply} from '../../../proto/torrent-web-seeder/torrent-web-seeder_pb';
3 | import {grpc} from '@improbable-eng/grpc-web';
4 | import process from '../process';
5 | const debug = require('debug')('webtor:sdk:seeder:stats');
6 | import invert from 'lodash/invert';
7 |
8 | class Stats {
9 | constructor(url, path) {
10 | this.url = url;
11 | this.path = path;
12 | this.closed = false;
13 | this.client = null;
14 | }
15 | close() {
16 | if (this.closed) return;
17 | this.closed = true;
18 | debug('close stats url=%o path=%o', this.url, this.path);
19 | if (this.client) this.client.close();
20 | }
21 | start(onMessage, metadata, params) {
22 | const request = new StatRequest();
23 | request.setPath(this.path);
24 | const client = () => {
25 | const c = grpc.client(TorrentWebSeeder.StatStream, {
26 | host: this.url,
27 | transport: grpc.WebsocketTransport(),
28 | debug: params.grpcDebug,
29 | });
30 | this.client = c;
31 | return c;
32 | };
33 | const statuses = invert(StatReply.Status);
34 | let map = null;
35 | const onMessageWrapper = (message) => {
36 | message.statusName = statuses[message.status];
37 | if (!map && message.status != 0) {
38 | map = message.piecesList;
39 | } else {
40 | for (const p of message.piecesList) {
41 | for (const m of map) {
42 | if (m.position == p.position) {
43 | m.complete = p.complete;
44 | m.priority = p.priority;
45 | }
46 | }
47 | }
48 | message.piecesList = JSON.parse(JSON.stringify(map));
49 | }
50 | onMessage(this.path, message);
51 | }
52 | const onEnd = (res, resolve, reject) => {
53 | if (res !== grpc.Code.OK) {
54 | reject('failed to get stats torrent code=' + res);
55 | } else {
56 | debug('stats finished url=%o path=%o', this.url, this.path);
57 | this.close();
58 | resolve();
59 | }
60 | }
61 |
62 | return process(client, request, onMessageWrapper, onEnd, metadata, params);
63 | }
64 | }
65 |
66 | export default function(url, path, onMessage, metadata = {}, params = {}) {
67 | const stats = new Stats(url, path);
68 | stats.start(onMessage, metadata, params);
69 | return stats;
70 | }
--------------------------------------------------------------------------------
/proto/magnet2torrent/magnet2torrent_pb_service.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/magnet2torrent/magnet2torrent.proto
3 |
4 | import * as proto_magnet2torrent_magnet2torrent_pb from "../../proto/magnet2torrent/magnet2torrent_pb";
5 | import {grpc} from "@improbable-eng/grpc-web";
6 |
7 | type Magnet2TorrentMagnet2Torrent = {
8 | readonly methodName: string;
9 | readonly service: typeof Magnet2Torrent;
10 | readonly requestStream: false;
11 | readonly responseStream: false;
12 | readonly requestType: typeof proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentRequest;
13 | readonly responseType: typeof proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentReply;
14 | };
15 |
16 | export class Magnet2Torrent {
17 | static readonly serviceName: string;
18 | static readonly Magnet2Torrent: Magnet2TorrentMagnet2Torrent;
19 | }
20 |
21 | export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }
22 | export type Status = { details: string, code: number; metadata: grpc.Metadata }
23 |
24 | interface UnaryResponse {
25 | cancel(): void;
26 | }
27 | interface ResponseStream {
28 | cancel(): void;
29 | on(type: 'data', handler: (message: T) => void): ResponseStream;
30 | on(type: 'end', handler: (status?: Status) => void): ResponseStream;
31 | on(type: 'status', handler: (status: Status) => void): ResponseStream;
32 | }
33 | interface RequestStream {
34 | write(message: T): RequestStream;
35 | end(): void;
36 | cancel(): void;
37 | on(type: 'end', handler: (status?: Status) => void): RequestStream;
38 | on(type: 'status', handler: (status: Status) => void): RequestStream;
39 | }
40 | interface BidirectionalStream {
41 | write(message: ReqT): BidirectionalStream;
42 | end(): void;
43 | cancel(): void;
44 | on(type: 'data', handler: (message: ResT) => void): BidirectionalStream;
45 | on(type: 'end', handler: (status?: Status) => void): BidirectionalStream;
46 | on(type: 'status', handler: (status: Status) => void): BidirectionalStream;
47 | }
48 |
49 | export class Magnet2TorrentClient {
50 | readonly serviceHost: string;
51 |
52 | constructor(serviceHost: string, options?: grpc.RpcOptions);
53 | magnet2Torrent(
54 | requestMessage: proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentRequest,
55 | metadata: grpc.Metadata,
56 | callback: (error: ServiceError|null, responseMessage: proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentReply|null) => void
57 | ): UnaryResponse;
58 | magnet2Torrent(
59 | requestMessage: proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentRequest,
60 | callback: (error: ServiceError|null, responseMessage: proto_magnet2torrent_magnet2torrent_pb.Magnet2TorrentReply|null) => void
61 | ): UnaryResponse;
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/proto/url-store/url-store_pb_service.js:
--------------------------------------------------------------------------------
1 | // package: webtor.url_store
2 | // file: proto/url-store/url-store.proto
3 |
4 | var proto_url_store_url_store_pb = require("../../proto/url-store/url-store_pb");
5 | var grpc = require("@improbable-eng/grpc-web").grpc;
6 |
7 | var UrlStore = (function () {
8 | function UrlStore() {}
9 | UrlStore.serviceName = "webtor.url_store.UrlStore";
10 | return UrlStore;
11 | }());
12 |
13 | UrlStore.Push = {
14 | methodName: "Push",
15 | service: UrlStore,
16 | requestStream: false,
17 | responseStream: false,
18 | requestType: proto_url_store_url_store_pb.PushRequest,
19 | responseType: proto_url_store_url_store_pb.PushReply
20 | };
21 |
22 | UrlStore.Check = {
23 | methodName: "Check",
24 | service: UrlStore,
25 | requestStream: false,
26 | responseStream: false,
27 | requestType: proto_url_store_url_store_pb.CheckRequest,
28 | responseType: proto_url_store_url_store_pb.CheckReply
29 | };
30 |
31 | exports.UrlStore = UrlStore;
32 |
33 | function UrlStoreClient(serviceHost, options) {
34 | this.serviceHost = serviceHost;
35 | this.options = options || {};
36 | }
37 |
38 | UrlStoreClient.prototype.push = function push(requestMessage, metadata, callback) {
39 | if (arguments.length === 2) {
40 | callback = arguments[1];
41 | }
42 | var client = grpc.unary(UrlStore.Push, {
43 | request: requestMessage,
44 | host: this.serviceHost,
45 | metadata: metadata,
46 | transport: this.options.transport,
47 | debug: this.options.debug,
48 | onEnd: function (response) {
49 | if (callback) {
50 | if (response.status !== grpc.Code.OK) {
51 | var err = new Error(response.statusMessage);
52 | err.code = response.status;
53 | err.metadata = response.trailers;
54 | callback(err, null);
55 | } else {
56 | callback(null, response.message);
57 | }
58 | }
59 | }
60 | });
61 | return {
62 | cancel: function () {
63 | callback = null;
64 | client.close();
65 | }
66 | };
67 | };
68 |
69 | UrlStoreClient.prototype.check = function check(requestMessage, metadata, callback) {
70 | if (arguments.length === 2) {
71 | callback = arguments[1];
72 | }
73 | var client = grpc.unary(UrlStore.Check, {
74 | request: requestMessage,
75 | host: this.serviceHost,
76 | metadata: metadata,
77 | transport: this.options.transport,
78 | debug: this.options.debug,
79 | onEnd: function (response) {
80 | if (callback) {
81 | if (response.status !== grpc.Code.OK) {
82 | var err = new Error(response.statusMessage);
83 | err.code = response.status;
84 | err.metadata = response.trailers;
85 | callback(err, null);
86 | } else {
87 | callback(null, response.message);
88 | }
89 | }
90 | }
91 | });
92 | return {
93 | cancel: function () {
94 | callback = null;
95 | client.close();
96 | }
97 | };
98 | };
99 |
100 | exports.UrlStoreClient = UrlStoreClient;
101 |
102 |
--------------------------------------------------------------------------------
/proto/abuse-store/abuse-store_pb_service.js:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/abuse-store/abuse-store.proto
3 |
4 | var proto_abuse_store_abuse_store_pb = require("../../proto/abuse-store/abuse-store_pb");
5 | var grpc = require("@improbable-eng/grpc-web").grpc;
6 |
7 | var AbuseStore = (function () {
8 | function AbuseStore() {}
9 | AbuseStore.serviceName = "AbuseStore";
10 | return AbuseStore;
11 | }());
12 |
13 | AbuseStore.Push = {
14 | methodName: "Push",
15 | service: AbuseStore,
16 | requestStream: false,
17 | responseStream: false,
18 | requestType: proto_abuse_store_abuse_store_pb.PushRequest,
19 | responseType: proto_abuse_store_abuse_store_pb.PushReply
20 | };
21 |
22 | AbuseStore.Check = {
23 | methodName: "Check",
24 | service: AbuseStore,
25 | requestStream: false,
26 | responseStream: false,
27 | requestType: proto_abuse_store_abuse_store_pb.CheckRequest,
28 | responseType: proto_abuse_store_abuse_store_pb.CheckReply
29 | };
30 |
31 | exports.AbuseStore = AbuseStore;
32 |
33 | function AbuseStoreClient(serviceHost, options) {
34 | this.serviceHost = serviceHost;
35 | this.options = options || {};
36 | }
37 |
38 | AbuseStoreClient.prototype.push = function push(requestMessage, metadata, callback) {
39 | if (arguments.length === 2) {
40 | callback = arguments[1];
41 | }
42 | var client = grpc.unary(AbuseStore.Push, {
43 | request: requestMessage,
44 | host: this.serviceHost,
45 | metadata: metadata,
46 | transport: this.options.transport,
47 | debug: this.options.debug,
48 | onEnd: function (response) {
49 | if (callback) {
50 | if (response.status !== grpc.Code.OK) {
51 | var err = new Error(response.statusMessage);
52 | err.code = response.status;
53 | err.metadata = response.trailers;
54 | callback(err, null);
55 | } else {
56 | callback(null, response.message);
57 | }
58 | }
59 | }
60 | });
61 | return {
62 | cancel: function () {
63 | callback = null;
64 | client.close();
65 | }
66 | };
67 | };
68 |
69 | AbuseStoreClient.prototype.check = function check(requestMessage, metadata, callback) {
70 | if (arguments.length === 2) {
71 | callback = arguments[1];
72 | }
73 | var client = grpc.unary(AbuseStore.Check, {
74 | request: requestMessage,
75 | host: this.serviceHost,
76 | metadata: metadata,
77 | transport: this.options.transport,
78 | debug: this.options.debug,
79 | onEnd: function (response) {
80 | if (callback) {
81 | if (response.status !== grpc.Code.OK) {
82 | var err = new Error(response.statusMessage);
83 | err.code = response.status;
84 | err.metadata = response.trailers;
85 | callback(err, null);
86 | } else {
87 | callback(null, response.message);
88 | }
89 | }
90 | }
91 | });
92 | return {
93 | cancel: function () {
94 | callback = null;
95 | client.close();
96 | }
97 | };
98 | };
99 |
100 | exports.AbuseStoreClient = AbuseStoreClient;
101 |
102 |
--------------------------------------------------------------------------------
/proto/download-progress/download-progress_pb_service.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/download-progress/download-progress.proto
3 |
4 | import * as proto_download_progress_download_progress_pb from "../../proto/download-progress/download-progress_pb";
5 | import {grpc} from "@improbable-eng/grpc-web";
6 |
7 | type DownloadProgressStat = {
8 | readonly methodName: string;
9 | readonly service: typeof DownloadProgress;
10 | readonly requestStream: false;
11 | readonly responseStream: false;
12 | readonly requestType: typeof proto_download_progress_download_progress_pb.StatRequest;
13 | readonly responseType: typeof proto_download_progress_download_progress_pb.StatReply;
14 | };
15 |
16 | type DownloadProgressStatStream = {
17 | readonly methodName: string;
18 | readonly service: typeof DownloadProgress;
19 | readonly requestStream: false;
20 | readonly responseStream: true;
21 | readonly requestType: typeof proto_download_progress_download_progress_pb.StatRequest;
22 | readonly responseType: typeof proto_download_progress_download_progress_pb.StatReply;
23 | };
24 |
25 | export class DownloadProgress {
26 | static readonly serviceName: string;
27 | static readonly Stat: DownloadProgressStat;
28 | static readonly StatStream: DownloadProgressStatStream;
29 | }
30 |
31 | export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }
32 | export type Status = { details: string, code: number; metadata: grpc.Metadata }
33 |
34 | interface UnaryResponse {
35 | cancel(): void;
36 | }
37 | interface ResponseStream {
38 | cancel(): void;
39 | on(type: 'data', handler: (message: T) => void): ResponseStream;
40 | on(type: 'end', handler: (status?: Status) => void): ResponseStream;
41 | on(type: 'status', handler: (status: Status) => void): ResponseStream;
42 | }
43 | interface RequestStream {
44 | write(message: T): RequestStream;
45 | end(): void;
46 | cancel(): void;
47 | on(type: 'end', handler: (status?: Status) => void): RequestStream;
48 | on(type: 'status', handler: (status: Status) => void): RequestStream;
49 | }
50 | interface BidirectionalStream {
51 | write(message: ReqT): BidirectionalStream;
52 | end(): void;
53 | cancel(): void;
54 | on(type: 'data', handler: (message: ResT) => void): BidirectionalStream;
55 | on(type: 'end', handler: (status?: Status) => void): BidirectionalStream;
56 | on(type: 'status', handler: (status: Status) => void): BidirectionalStream;
57 | }
58 |
59 | export class DownloadProgressClient {
60 | readonly serviceHost: string;
61 |
62 | constructor(serviceHost: string, options?: grpc.RpcOptions);
63 | stat(
64 | requestMessage: proto_download_progress_download_progress_pb.StatRequest,
65 | metadata: grpc.Metadata,
66 | callback: (error: ServiceError|null, responseMessage: proto_download_progress_download_progress_pb.StatReply|null) => void
67 | ): UnaryResponse;
68 | stat(
69 | requestMessage: proto_download_progress_download_progress_pb.StatRequest,
70 | callback: (error: ServiceError|null, responseMessage: proto_download_progress_download_progress_pb.StatReply|null) => void
71 | ): UnaryResponse;
72 | statStream(requestMessage: proto_download_progress_download_progress_pb.StatRequest, metadata?: grpc.Metadata): ResponseStream;
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/proto/url-store/url-store_pb_service.d.ts:
--------------------------------------------------------------------------------
1 | // package: webtor.url_store
2 | // file: proto/url-store/url-store.proto
3 |
4 | import * as proto_url_store_url_store_pb from "../../proto/url-store/url-store_pb";
5 | import {grpc} from "@improbable-eng/grpc-web";
6 |
7 | type UrlStorePush = {
8 | readonly methodName: string;
9 | readonly service: typeof UrlStore;
10 | readonly requestStream: false;
11 | readonly responseStream: false;
12 | readonly requestType: typeof proto_url_store_url_store_pb.PushRequest;
13 | readonly responseType: typeof proto_url_store_url_store_pb.PushReply;
14 | };
15 |
16 | type UrlStoreCheck = {
17 | readonly methodName: string;
18 | readonly service: typeof UrlStore;
19 | readonly requestStream: false;
20 | readonly responseStream: false;
21 | readonly requestType: typeof proto_url_store_url_store_pb.CheckRequest;
22 | readonly responseType: typeof proto_url_store_url_store_pb.CheckReply;
23 | };
24 |
25 | export class UrlStore {
26 | static readonly serviceName: string;
27 | static readonly Push: UrlStorePush;
28 | static readonly Check: UrlStoreCheck;
29 | }
30 |
31 | export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }
32 | export type Status = { details: string, code: number; metadata: grpc.Metadata }
33 |
34 | interface UnaryResponse {
35 | cancel(): void;
36 | }
37 | interface ResponseStream {
38 | cancel(): void;
39 | on(type: 'data', handler: (message: T) => void): ResponseStream;
40 | on(type: 'end', handler: (status?: Status) => void): ResponseStream;
41 | on(type: 'status', handler: (status: Status) => void): ResponseStream;
42 | }
43 | interface RequestStream {
44 | write(message: T): RequestStream;
45 | end(): void;
46 | cancel(): void;
47 | on(type: 'end', handler: (status?: Status) => void): RequestStream;
48 | on(type: 'status', handler: (status: Status) => void): RequestStream;
49 | }
50 | interface BidirectionalStream {
51 | write(message: ReqT): BidirectionalStream;
52 | end(): void;
53 | cancel(): void;
54 | on(type: 'data', handler: (message: ResT) => void): BidirectionalStream;
55 | on(type: 'end', handler: (status?: Status) => void): BidirectionalStream;
56 | on(type: 'status', handler: (status: Status) => void): BidirectionalStream;
57 | }
58 |
59 | export class UrlStoreClient {
60 | readonly serviceHost: string;
61 |
62 | constructor(serviceHost: string, options?: grpc.RpcOptions);
63 | push(
64 | requestMessage: proto_url_store_url_store_pb.PushRequest,
65 | metadata: grpc.Metadata,
66 | callback: (error: ServiceError|null, responseMessage: proto_url_store_url_store_pb.PushReply|null) => void
67 | ): UnaryResponse;
68 | push(
69 | requestMessage: proto_url_store_url_store_pb.PushRequest,
70 | callback: (error: ServiceError|null, responseMessage: proto_url_store_url_store_pb.PushReply|null) => void
71 | ): UnaryResponse;
72 | check(
73 | requestMessage: proto_url_store_url_store_pb.CheckRequest,
74 | metadata: grpc.Metadata,
75 | callback: (error: ServiceError|null, responseMessage: proto_url_store_url_store_pb.CheckReply|null) => void
76 | ): UnaryResponse;
77 | check(
78 | requestMessage: proto_url_store_url_store_pb.CheckRequest,
79 | callback: (error: ServiceError|null, responseMessage: proto_url_store_url_store_pb.CheckReply|null) => void
80 | ): UnaryResponse;
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/proto/abuse-store/abuse-store_pb_service.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/abuse-store/abuse-store.proto
3 |
4 | import * as proto_abuse_store_abuse_store_pb from "../../proto/abuse-store/abuse-store_pb";
5 | import {grpc} from "@improbable-eng/grpc-web";
6 |
7 | type AbuseStorePush = {
8 | readonly methodName: string;
9 | readonly service: typeof AbuseStore;
10 | readonly requestStream: false;
11 | readonly responseStream: false;
12 | readonly requestType: typeof proto_abuse_store_abuse_store_pb.PushRequest;
13 | readonly responseType: typeof proto_abuse_store_abuse_store_pb.PushReply;
14 | };
15 |
16 | type AbuseStoreCheck = {
17 | readonly methodName: string;
18 | readonly service: typeof AbuseStore;
19 | readonly requestStream: false;
20 | readonly responseStream: false;
21 | readonly requestType: typeof proto_abuse_store_abuse_store_pb.CheckRequest;
22 | readonly responseType: typeof proto_abuse_store_abuse_store_pb.CheckReply;
23 | };
24 |
25 | export class AbuseStore {
26 | static readonly serviceName: string;
27 | static readonly Push: AbuseStorePush;
28 | static readonly Check: AbuseStoreCheck;
29 | }
30 |
31 | export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }
32 | export type Status = { details: string, code: number; metadata: grpc.Metadata }
33 |
34 | interface UnaryResponse {
35 | cancel(): void;
36 | }
37 | interface ResponseStream {
38 | cancel(): void;
39 | on(type: 'data', handler: (message: T) => void): ResponseStream;
40 | on(type: 'end', handler: (status?: Status) => void): ResponseStream;
41 | on(type: 'status', handler: (status: Status) => void): ResponseStream;
42 | }
43 | interface RequestStream {
44 | write(message: T): RequestStream;
45 | end(): void;
46 | cancel(): void;
47 | on(type: 'end', handler: (status?: Status) => void): RequestStream;
48 | on(type: 'status', handler: (status: Status) => void): RequestStream;
49 | }
50 | interface BidirectionalStream {
51 | write(message: ReqT): BidirectionalStream;
52 | end(): void;
53 | cancel(): void;
54 | on(type: 'data', handler: (message: ResT) => void): BidirectionalStream;
55 | on(type: 'end', handler: (status?: Status) => void): BidirectionalStream;
56 | on(type: 'status', handler: (status: Status) => void): BidirectionalStream;
57 | }
58 |
59 | export class AbuseStoreClient {
60 | readonly serviceHost: string;
61 |
62 | constructor(serviceHost: string, options?: grpc.RpcOptions);
63 | push(
64 | requestMessage: proto_abuse_store_abuse_store_pb.PushRequest,
65 | metadata: grpc.Metadata,
66 | callback: (error: ServiceError|null, responseMessage: proto_abuse_store_abuse_store_pb.PushReply|null) => void
67 | ): UnaryResponse;
68 | push(
69 | requestMessage: proto_abuse_store_abuse_store_pb.PushRequest,
70 | callback: (error: ServiceError|null, responseMessage: proto_abuse_store_abuse_store_pb.PushReply|null) => void
71 | ): UnaryResponse;
72 | check(
73 | requestMessage: proto_abuse_store_abuse_store_pb.CheckRequest,
74 | metadata: grpc.Metadata,
75 | callback: (error: ServiceError|null, responseMessage: proto_abuse_store_abuse_store_pb.CheckReply|null) => void
76 | ): UnaryResponse;
77 | check(
78 | requestMessage: proto_abuse_store_abuse_store_pb.CheckRequest,
79 | callback: (error: ServiceError|null, responseMessage: proto_abuse_store_abuse_store_pb.CheckReply|null) => void
80 | ): UnaryResponse;
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/proto/url-store/url-store_pb.d.ts:
--------------------------------------------------------------------------------
1 | // package: webtor.url_store
2 | // file: proto/url-store/url-store.proto
3 |
4 | import * as jspb from "google-protobuf";
5 |
6 | export class PushReply extends jspb.Message {
7 | getHash(): string;
8 | setHash(value: string): void;
9 |
10 | serializeBinary(): Uint8Array;
11 | toObject(includeInstance?: boolean): PushReply.AsObject;
12 | static toObject(includeInstance: boolean, msg: PushReply): PushReply.AsObject;
13 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
14 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
15 | static serializeBinaryToWriter(message: PushReply, writer: jspb.BinaryWriter): void;
16 | static deserializeBinary(bytes: Uint8Array): PushReply;
17 | static deserializeBinaryFromReader(message: PushReply, reader: jspb.BinaryReader): PushReply;
18 | }
19 |
20 | export namespace PushReply {
21 | export type AsObject = {
22 | hash: string,
23 | }
24 | }
25 |
26 | export class PushRequest extends jspb.Message {
27 | getUrl(): string;
28 | setUrl(value: string): void;
29 |
30 | serializeBinary(): Uint8Array;
31 | toObject(includeInstance?: boolean): PushRequest.AsObject;
32 | static toObject(includeInstance: boolean, msg: PushRequest): PushRequest.AsObject;
33 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
34 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
35 | static serializeBinaryToWriter(message: PushRequest, writer: jspb.BinaryWriter): void;
36 | static deserializeBinary(bytes: Uint8Array): PushRequest;
37 | static deserializeBinaryFromReader(message: PushRequest, reader: jspb.BinaryReader): PushRequest;
38 | }
39 |
40 | export namespace PushRequest {
41 | export type AsObject = {
42 | url: string,
43 | }
44 | }
45 |
46 | export class CheckRequest extends jspb.Message {
47 | getHash(): string;
48 | setHash(value: string): void;
49 |
50 | serializeBinary(): Uint8Array;
51 | toObject(includeInstance?: boolean): CheckRequest.AsObject;
52 | static toObject(includeInstance: boolean, msg: CheckRequest): CheckRequest.AsObject;
53 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
54 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
55 | static serializeBinaryToWriter(message: CheckRequest, writer: jspb.BinaryWriter): void;
56 | static deserializeBinary(bytes: Uint8Array): CheckRequest;
57 | static deserializeBinaryFromReader(message: CheckRequest, reader: jspb.BinaryReader): CheckRequest;
58 | }
59 |
60 | export namespace CheckRequest {
61 | export type AsObject = {
62 | hash: string,
63 | }
64 | }
65 |
66 | export class CheckReply extends jspb.Message {
67 | getExists(): boolean;
68 | setExists(value: boolean): void;
69 |
70 | serializeBinary(): Uint8Array;
71 | toObject(includeInstance?: boolean): CheckReply.AsObject;
72 | static toObject(includeInstance: boolean, msg: CheckReply): CheckReply.AsObject;
73 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
74 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
75 | static serializeBinaryToWriter(message: CheckReply, writer: jspb.BinaryWriter): void;
76 | static deserializeBinary(bytes: Uint8Array): CheckReply;
77 | static deserializeBinaryFromReader(message: CheckReply, reader: jspb.BinaryReader): CheckReply;
78 | }
79 |
80 | export namespace CheckReply {
81 | export type AsObject = {
82 | exists: boolean,
83 | }
84 | }
85 |
86 |
--------------------------------------------------------------------------------
/proto/download-progress/download-progress_pb_service.js:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/download-progress/download-progress.proto
3 |
4 | var proto_download_progress_download_progress_pb = require("../../proto/download-progress/download-progress_pb");
5 | var grpc = require("@improbable-eng/grpc-web").grpc;
6 |
7 | var DownloadProgress = (function () {
8 | function DownloadProgress() {}
9 | DownloadProgress.serviceName = "DownloadProgress";
10 | return DownloadProgress;
11 | }());
12 |
13 | DownloadProgress.Stat = {
14 | methodName: "Stat",
15 | service: DownloadProgress,
16 | requestStream: false,
17 | responseStream: false,
18 | requestType: proto_download_progress_download_progress_pb.StatRequest,
19 | responseType: proto_download_progress_download_progress_pb.StatReply
20 | };
21 |
22 | DownloadProgress.StatStream = {
23 | methodName: "StatStream",
24 | service: DownloadProgress,
25 | requestStream: false,
26 | responseStream: true,
27 | requestType: proto_download_progress_download_progress_pb.StatRequest,
28 | responseType: proto_download_progress_download_progress_pb.StatReply
29 | };
30 |
31 | exports.DownloadProgress = DownloadProgress;
32 |
33 | function DownloadProgressClient(serviceHost, options) {
34 | this.serviceHost = serviceHost;
35 | this.options = options || {};
36 | }
37 |
38 | DownloadProgressClient.prototype.stat = function stat(requestMessage, metadata, callback) {
39 | if (arguments.length === 2) {
40 | callback = arguments[1];
41 | }
42 | var client = grpc.unary(DownloadProgress.Stat, {
43 | request: requestMessage,
44 | host: this.serviceHost,
45 | metadata: metadata,
46 | transport: this.options.transport,
47 | debug: this.options.debug,
48 | onEnd: function (response) {
49 | if (callback) {
50 | if (response.status !== grpc.Code.OK) {
51 | var err = new Error(response.statusMessage);
52 | err.code = response.status;
53 | err.metadata = response.trailers;
54 | callback(err, null);
55 | } else {
56 | callback(null, response.message);
57 | }
58 | }
59 | }
60 | });
61 | return {
62 | cancel: function () {
63 | callback = null;
64 | client.close();
65 | }
66 | };
67 | };
68 |
69 | DownloadProgressClient.prototype.statStream = function statStream(requestMessage, metadata) {
70 | var listeners = {
71 | data: [],
72 | end: [],
73 | status: []
74 | };
75 | var client = grpc.invoke(DownloadProgress.StatStream, {
76 | request: requestMessage,
77 | host: this.serviceHost,
78 | metadata: metadata,
79 | transport: this.options.transport,
80 | debug: this.options.debug,
81 | onMessage: function (responseMessage) {
82 | listeners.data.forEach(function (handler) {
83 | handler(responseMessage);
84 | });
85 | },
86 | onEnd: function (status, statusMessage, trailers) {
87 | listeners.status.forEach(function (handler) {
88 | handler({ code: status, details: statusMessage, metadata: trailers });
89 | });
90 | listeners.end.forEach(function (handler) {
91 | handler({ code: status, details: statusMessage, metadata: trailers });
92 | });
93 | listeners = null;
94 | }
95 | });
96 | return {
97 | on: function (type, handler) {
98 | listeners[type].push(handler);
99 | return this;
100 | },
101 | cancel: function () {
102 | listeners = null;
103 | client.close();
104 | }
105 | };
106 | };
107 |
108 | exports.DownloadProgressClient = DownloadProgressClient;
109 |
110 |
--------------------------------------------------------------------------------
/proto/torrent-web-seeder/torrent-web-seeder_pb_service.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/torrent-web-seeder/torrent-web-seeder.proto
3 |
4 | import * as proto_torrent_web_seeder_torrent_web_seeder_pb from "../../proto/torrent-web-seeder/torrent-web-seeder_pb";
5 | import {grpc} from "@improbable-eng/grpc-web";
6 |
7 | type TorrentWebSeederStat = {
8 | readonly methodName: string;
9 | readonly service: typeof TorrentWebSeeder;
10 | readonly requestStream: false;
11 | readonly responseStream: false;
12 | readonly requestType: typeof proto_torrent_web_seeder_torrent_web_seeder_pb.StatRequest;
13 | readonly responseType: typeof proto_torrent_web_seeder_torrent_web_seeder_pb.StatReply;
14 | };
15 |
16 | type TorrentWebSeederStatStream = {
17 | readonly methodName: string;
18 | readonly service: typeof TorrentWebSeeder;
19 | readonly requestStream: false;
20 | readonly responseStream: true;
21 | readonly requestType: typeof proto_torrent_web_seeder_torrent_web_seeder_pb.StatRequest;
22 | readonly responseType: typeof proto_torrent_web_seeder_torrent_web_seeder_pb.StatReply;
23 | };
24 |
25 | type TorrentWebSeederFiles = {
26 | readonly methodName: string;
27 | readonly service: typeof TorrentWebSeeder;
28 | readonly requestStream: false;
29 | readonly responseStream: false;
30 | readonly requestType: typeof proto_torrent_web_seeder_torrent_web_seeder_pb.FilesRequest;
31 | readonly responseType: typeof proto_torrent_web_seeder_torrent_web_seeder_pb.FilesReply;
32 | };
33 |
34 | export class TorrentWebSeeder {
35 | static readonly serviceName: string;
36 | static readonly Stat: TorrentWebSeederStat;
37 | static readonly StatStream: TorrentWebSeederStatStream;
38 | static readonly Files: TorrentWebSeederFiles;
39 | }
40 |
41 | export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }
42 | export type Status = { details: string, code: number; metadata: grpc.Metadata }
43 |
44 | interface UnaryResponse {
45 | cancel(): void;
46 | }
47 | interface ResponseStream {
48 | cancel(): void;
49 | on(type: 'data', handler: (message: T) => void): ResponseStream;
50 | on(type: 'end', handler: (status?: Status) => void): ResponseStream;
51 | on(type: 'status', handler: (status: Status) => void): ResponseStream;
52 | }
53 | interface RequestStream {
54 | write(message: T): RequestStream;
55 | end(): void;
56 | cancel(): void;
57 | on(type: 'end', handler: (status?: Status) => void): RequestStream;
58 | on(type: 'status', handler: (status: Status) => void): RequestStream;
59 | }
60 | interface BidirectionalStream {
61 | write(message: ReqT): BidirectionalStream;
62 | end(): void;
63 | cancel(): void;
64 | on(type: 'data', handler: (message: ResT) => void): BidirectionalStream;
65 | on(type: 'end', handler: (status?: Status) => void): BidirectionalStream;
66 | on(type: 'status', handler: (status: Status) => void): BidirectionalStream;
67 | }
68 |
69 | export class TorrentWebSeederClient {
70 | readonly serviceHost: string;
71 |
72 | constructor(serviceHost: string, options?: grpc.RpcOptions);
73 | stat(
74 | requestMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.StatRequest,
75 | metadata: grpc.Metadata,
76 | callback: (error: ServiceError|null, responseMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.StatReply|null) => void
77 | ): UnaryResponse;
78 | stat(
79 | requestMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.StatRequest,
80 | callback: (error: ServiceError|null, responseMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.StatReply|null) => void
81 | ): UnaryResponse;
82 | statStream(requestMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.StatRequest, metadata?: grpc.Metadata): ResponseStream;
83 | files(
84 | requestMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.FilesRequest,
85 | metadata: grpc.Metadata,
86 | callback: (error: ServiceError|null, responseMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.FilesReply|null) => void
87 | ): UnaryResponse;
88 | files(
89 | requestMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.FilesRequest,
90 | callback: (error: ServiceError|null, responseMessage: proto_torrent_web_seeder_torrent_web_seeder_pb.FilesReply|null) => void
91 | ): UnaryResponse;
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/proto/torrent-store/torrent-store_pb_service.js:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/torrent-store/torrent-store.proto
3 |
4 | var proto_torrent_store_torrent_store_pb = require("../../proto/torrent-store/torrent-store_pb");
5 | var grpc = require("@improbable-eng/grpc-web").grpc;
6 |
7 | var TorrentStore = (function () {
8 | function TorrentStore() {}
9 | TorrentStore.serviceName = "TorrentStore";
10 | return TorrentStore;
11 | }());
12 |
13 | TorrentStore.Push = {
14 | methodName: "Push",
15 | service: TorrentStore,
16 | requestStream: false,
17 | responseStream: false,
18 | requestType: proto_torrent_store_torrent_store_pb.PushRequest,
19 | responseType: proto_torrent_store_torrent_store_pb.PushReply
20 | };
21 |
22 | TorrentStore.Pull = {
23 | methodName: "Pull",
24 | service: TorrentStore,
25 | requestStream: false,
26 | responseStream: false,
27 | requestType: proto_torrent_store_torrent_store_pb.PullRequest,
28 | responseType: proto_torrent_store_torrent_store_pb.PullReply
29 | };
30 |
31 | TorrentStore.Touch = {
32 | methodName: "Touch",
33 | service: TorrentStore,
34 | requestStream: false,
35 | responseStream: false,
36 | requestType: proto_torrent_store_torrent_store_pb.TouchRequest,
37 | responseType: proto_torrent_store_torrent_store_pb.TouchReply
38 | };
39 |
40 | exports.TorrentStore = TorrentStore;
41 |
42 | function TorrentStoreClient(serviceHost, options) {
43 | this.serviceHost = serviceHost;
44 | this.options = options || {};
45 | }
46 |
47 | TorrentStoreClient.prototype.push = function push(requestMessage, metadata, callback) {
48 | if (arguments.length === 2) {
49 | callback = arguments[1];
50 | }
51 | var client = grpc.unary(TorrentStore.Push, {
52 | request: requestMessage,
53 | host: this.serviceHost,
54 | metadata: metadata,
55 | transport: this.options.transport,
56 | debug: this.options.debug,
57 | onEnd: function (response) {
58 | if (callback) {
59 | if (response.status !== grpc.Code.OK) {
60 | var err = new Error(response.statusMessage);
61 | err.code = response.status;
62 | err.metadata = response.trailers;
63 | callback(err, null);
64 | } else {
65 | callback(null, response.message);
66 | }
67 | }
68 | }
69 | });
70 | return {
71 | cancel: function () {
72 | callback = null;
73 | client.close();
74 | }
75 | };
76 | };
77 |
78 | TorrentStoreClient.prototype.pull = function pull(requestMessage, metadata, callback) {
79 | if (arguments.length === 2) {
80 | callback = arguments[1];
81 | }
82 | var client = grpc.unary(TorrentStore.Pull, {
83 | request: requestMessage,
84 | host: this.serviceHost,
85 | metadata: metadata,
86 | transport: this.options.transport,
87 | debug: this.options.debug,
88 | onEnd: function (response) {
89 | if (callback) {
90 | if (response.status !== grpc.Code.OK) {
91 | var err = new Error(response.statusMessage);
92 | err.code = response.status;
93 | err.metadata = response.trailers;
94 | callback(err, null);
95 | } else {
96 | callback(null, response.message);
97 | }
98 | }
99 | }
100 | });
101 | return {
102 | cancel: function () {
103 | callback = null;
104 | client.close();
105 | }
106 | };
107 | };
108 |
109 | TorrentStoreClient.prototype.touch = function touch(requestMessage, metadata, callback) {
110 | if (arguments.length === 2) {
111 | callback = arguments[1];
112 | }
113 | var client = grpc.unary(TorrentStore.Touch, {
114 | request: requestMessage,
115 | host: this.serviceHost,
116 | metadata: metadata,
117 | transport: this.options.transport,
118 | debug: this.options.debug,
119 | onEnd: function (response) {
120 | if (callback) {
121 | if (response.status !== grpc.Code.OK) {
122 | var err = new Error(response.statusMessage);
123 | err.code = response.status;
124 | err.metadata = response.trailers;
125 | callback(err, null);
126 | } else {
127 | callback(null, response.message);
128 | }
129 | }
130 | }
131 | });
132 | return {
133 | cancel: function () {
134 | callback = null;
135 | client.close();
136 | }
137 | };
138 | };
139 |
140 | exports.TorrentStoreClient = TorrentStoreClient;
141 |
142 |
--------------------------------------------------------------------------------
/proto/torrent-store/torrent-store_pb_service.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/torrent-store/torrent-store.proto
3 |
4 | import * as proto_torrent_store_torrent_store_pb from "../../proto/torrent-store/torrent-store_pb";
5 | import {grpc} from "@improbable-eng/grpc-web";
6 |
7 | type TorrentStorePush = {
8 | readonly methodName: string;
9 | readonly service: typeof TorrentStore;
10 | readonly requestStream: false;
11 | readonly responseStream: false;
12 | readonly requestType: typeof proto_torrent_store_torrent_store_pb.PushRequest;
13 | readonly responseType: typeof proto_torrent_store_torrent_store_pb.PushReply;
14 | };
15 |
16 | type TorrentStorePull = {
17 | readonly methodName: string;
18 | readonly service: typeof TorrentStore;
19 | readonly requestStream: false;
20 | readonly responseStream: false;
21 | readonly requestType: typeof proto_torrent_store_torrent_store_pb.PullRequest;
22 | readonly responseType: typeof proto_torrent_store_torrent_store_pb.PullReply;
23 | };
24 |
25 | type TorrentStoreTouch = {
26 | readonly methodName: string;
27 | readonly service: typeof TorrentStore;
28 | readonly requestStream: false;
29 | readonly responseStream: false;
30 | readonly requestType: typeof proto_torrent_store_torrent_store_pb.TouchRequest;
31 | readonly responseType: typeof proto_torrent_store_torrent_store_pb.TouchReply;
32 | };
33 |
34 | export class TorrentStore {
35 | static readonly serviceName: string;
36 | static readonly Push: TorrentStorePush;
37 | static readonly Pull: TorrentStorePull;
38 | static readonly Touch: TorrentStoreTouch;
39 | }
40 |
41 | export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }
42 | export type Status = { details: string, code: number; metadata: grpc.Metadata }
43 |
44 | interface UnaryResponse {
45 | cancel(): void;
46 | }
47 | interface ResponseStream {
48 | cancel(): void;
49 | on(type: 'data', handler: (message: T) => void): ResponseStream;
50 | on(type: 'end', handler: (status?: Status) => void): ResponseStream;
51 | on(type: 'status', handler: (status: Status) => void): ResponseStream;
52 | }
53 | interface RequestStream {
54 | write(message: T): RequestStream;
55 | end(): void;
56 | cancel(): void;
57 | on(type: 'end', handler: (status?: Status) => void): RequestStream;
58 | on(type: 'status', handler: (status: Status) => void): RequestStream;
59 | }
60 | interface BidirectionalStream {
61 | write(message: ReqT): BidirectionalStream;
62 | end(): void;
63 | cancel(): void;
64 | on(type: 'data', handler: (message: ResT) => void): BidirectionalStream;
65 | on(type: 'end', handler: (status?: Status) => void): BidirectionalStream;
66 | on(type: 'status', handler: (status: Status) => void): BidirectionalStream;
67 | }
68 |
69 | export class TorrentStoreClient {
70 | readonly serviceHost: string;
71 |
72 | constructor(serviceHost: string, options?: grpc.RpcOptions);
73 | push(
74 | requestMessage: proto_torrent_store_torrent_store_pb.PushRequest,
75 | metadata: grpc.Metadata,
76 | callback: (error: ServiceError|null, responseMessage: proto_torrent_store_torrent_store_pb.PushReply|null) => void
77 | ): UnaryResponse;
78 | push(
79 | requestMessage: proto_torrent_store_torrent_store_pb.PushRequest,
80 | callback: (error: ServiceError|null, responseMessage: proto_torrent_store_torrent_store_pb.PushReply|null) => void
81 | ): UnaryResponse;
82 | pull(
83 | requestMessage: proto_torrent_store_torrent_store_pb.PullRequest,
84 | metadata: grpc.Metadata,
85 | callback: (error: ServiceError|null, responseMessage: proto_torrent_store_torrent_store_pb.PullReply|null) => void
86 | ): UnaryResponse;
87 | pull(
88 | requestMessage: proto_torrent_store_torrent_store_pb.PullRequest,
89 | callback: (error: ServiceError|null, responseMessage: proto_torrent_store_torrent_store_pb.PullReply|null) => void
90 | ): UnaryResponse;
91 | touch(
92 | requestMessage: proto_torrent_store_torrent_store_pb.TouchRequest,
93 | metadata: grpc.Metadata,
94 | callback: (error: ServiceError|null, responseMessage: proto_torrent_store_torrent_store_pb.TouchReply|null) => void
95 | ): UnaryResponse;
96 | touch(
97 | requestMessage: proto_torrent_store_torrent_store_pb.TouchRequest,
98 | callback: (error: ServiceError|null, responseMessage: proto_torrent_store_torrent_store_pb.TouchReply|null) => void
99 | ): UnaryResponse;
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/proto/torrent-web-seeder/torrent-web-seeder_pb_service.js:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/torrent-web-seeder/torrent-web-seeder.proto
3 |
4 | var proto_torrent_web_seeder_torrent_web_seeder_pb = require("../../proto/torrent-web-seeder/torrent-web-seeder_pb");
5 | var grpc = require("@improbable-eng/grpc-web").grpc;
6 |
7 | var TorrentWebSeeder = (function () {
8 | function TorrentWebSeeder() {}
9 | TorrentWebSeeder.serviceName = "TorrentWebSeeder";
10 | return TorrentWebSeeder;
11 | }());
12 |
13 | TorrentWebSeeder.Stat = {
14 | methodName: "Stat",
15 | service: TorrentWebSeeder,
16 | requestStream: false,
17 | responseStream: false,
18 | requestType: proto_torrent_web_seeder_torrent_web_seeder_pb.StatRequest,
19 | responseType: proto_torrent_web_seeder_torrent_web_seeder_pb.StatReply
20 | };
21 |
22 | TorrentWebSeeder.StatStream = {
23 | methodName: "StatStream",
24 | service: TorrentWebSeeder,
25 | requestStream: false,
26 | responseStream: true,
27 | requestType: proto_torrent_web_seeder_torrent_web_seeder_pb.StatRequest,
28 | responseType: proto_torrent_web_seeder_torrent_web_seeder_pb.StatReply
29 | };
30 |
31 | TorrentWebSeeder.Files = {
32 | methodName: "Files",
33 | service: TorrentWebSeeder,
34 | requestStream: false,
35 | responseStream: false,
36 | requestType: proto_torrent_web_seeder_torrent_web_seeder_pb.FilesRequest,
37 | responseType: proto_torrent_web_seeder_torrent_web_seeder_pb.FilesReply
38 | };
39 |
40 | exports.TorrentWebSeeder = TorrentWebSeeder;
41 |
42 | function TorrentWebSeederClient(serviceHost, options) {
43 | this.serviceHost = serviceHost;
44 | this.options = options || {};
45 | }
46 |
47 | TorrentWebSeederClient.prototype.stat = function stat(requestMessage, metadata, callback) {
48 | if (arguments.length === 2) {
49 | callback = arguments[1];
50 | }
51 | var client = grpc.unary(TorrentWebSeeder.Stat, {
52 | request: requestMessage,
53 | host: this.serviceHost,
54 | metadata: metadata,
55 | transport: this.options.transport,
56 | debug: this.options.debug,
57 | onEnd: function (response) {
58 | if (callback) {
59 | if (response.status !== grpc.Code.OK) {
60 | var err = new Error(response.statusMessage);
61 | err.code = response.status;
62 | err.metadata = response.trailers;
63 | callback(err, null);
64 | } else {
65 | callback(null, response.message);
66 | }
67 | }
68 | }
69 | });
70 | return {
71 | cancel: function () {
72 | callback = null;
73 | client.close();
74 | }
75 | };
76 | };
77 |
78 | TorrentWebSeederClient.prototype.statStream = function statStream(requestMessage, metadata) {
79 | var listeners = {
80 | data: [],
81 | end: [],
82 | status: []
83 | };
84 | var client = grpc.invoke(TorrentWebSeeder.StatStream, {
85 | request: requestMessage,
86 | host: this.serviceHost,
87 | metadata: metadata,
88 | transport: this.options.transport,
89 | debug: this.options.debug,
90 | onMessage: function (responseMessage) {
91 | listeners.data.forEach(function (handler) {
92 | handler(responseMessage);
93 | });
94 | },
95 | onEnd: function (status, statusMessage, trailers) {
96 | listeners.status.forEach(function (handler) {
97 | handler({ code: status, details: statusMessage, metadata: trailers });
98 | });
99 | listeners.end.forEach(function (handler) {
100 | handler({ code: status, details: statusMessage, metadata: trailers });
101 | });
102 | listeners = null;
103 | }
104 | });
105 | return {
106 | on: function (type, handler) {
107 | listeners[type].push(handler);
108 | return this;
109 | },
110 | cancel: function () {
111 | listeners = null;
112 | client.close();
113 | }
114 | };
115 | };
116 |
117 | TorrentWebSeederClient.prototype.files = function files(requestMessage, metadata, callback) {
118 | if (arguments.length === 2) {
119 | callback = arguments[1];
120 | }
121 | var client = grpc.unary(TorrentWebSeeder.Files, {
122 | request: requestMessage,
123 | host: this.serviceHost,
124 | metadata: metadata,
125 | transport: this.options.transport,
126 | debug: this.options.debug,
127 | onEnd: function (response) {
128 | if (callback) {
129 | if (response.status !== grpc.Code.OK) {
130 | var err = new Error(response.statusMessage);
131 | err.code = response.status;
132 | err.metadata = response.trailers;
133 | callback(err, null);
134 | } else {
135 | callback(null, response.message);
136 | }
137 | }
138 | }
139 | });
140 | return {
141 | cancel: function () {
142 | callback = null;
143 | client.close();
144 | }
145 | };
146 | };
147 |
148 | exports.TorrentWebSeederClient = TorrentWebSeederClient;
149 |
150 |
--------------------------------------------------------------------------------
/proto/abuse-store/abuse-store_pb.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/abuse-store/abuse-store.proto
3 |
4 | import * as jspb from "google-protobuf";
5 |
6 | export class PushReply extends jspb.Message {
7 | serializeBinary(): Uint8Array;
8 | toObject(includeInstance?: boolean): PushReply.AsObject;
9 | static toObject(includeInstance: boolean, msg: PushReply): PushReply.AsObject;
10 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
11 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
12 | static serializeBinaryToWriter(message: PushReply, writer: jspb.BinaryWriter): void;
13 | static deserializeBinary(bytes: Uint8Array): PushReply;
14 | static deserializeBinaryFromReader(message: PushReply, reader: jspb.BinaryReader): PushReply;
15 | }
16 |
17 | export namespace PushReply {
18 | export type AsObject = {
19 | }
20 | }
21 |
22 | export class PushRequest extends jspb.Message {
23 | getNoticeId(): string;
24 | setNoticeId(value: string): void;
25 |
26 | getInfohash(): string;
27 | setInfohash(value: string): void;
28 |
29 | getFilename(): string;
30 | setFilename(value: string): void;
31 |
32 | getWork(): string;
33 | setWork(value: string): void;
34 |
35 | getStartedAt(): number;
36 | setStartedAt(value: number): void;
37 |
38 | getEmail(): string;
39 | setEmail(value: string): void;
40 |
41 | getDescription(): string;
42 | setDescription(value: string): void;
43 |
44 | getSubject(): string;
45 | setSubject(value: string): void;
46 |
47 | getCause(): PushRequest.CauseMap[keyof PushRequest.CauseMap];
48 | setCause(value: PushRequest.CauseMap[keyof PushRequest.CauseMap]): void;
49 |
50 | getSource(): PushRequest.SourceMap[keyof PushRequest.SourceMap];
51 | setSource(value: PushRequest.SourceMap[keyof PushRequest.SourceMap]): void;
52 |
53 | serializeBinary(): Uint8Array;
54 | toObject(includeInstance?: boolean): PushRequest.AsObject;
55 | static toObject(includeInstance: boolean, msg: PushRequest): PushRequest.AsObject;
56 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
57 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
58 | static serializeBinaryToWriter(message: PushRequest, writer: jspb.BinaryWriter): void;
59 | static deserializeBinary(bytes: Uint8Array): PushRequest;
60 | static deserializeBinaryFromReader(message: PushRequest, reader: jspb.BinaryReader): PushRequest;
61 | }
62 |
63 | export namespace PushRequest {
64 | export type AsObject = {
65 | noticeId: string,
66 | infohash: string,
67 | filename: string,
68 | work: string,
69 | startedAt: number,
70 | email: string,
71 | description: string,
72 | subject: string,
73 | cause: PushRequest.CauseMap[keyof PushRequest.CauseMap],
74 | source: PushRequest.SourceMap[keyof PushRequest.SourceMap],
75 | }
76 |
77 | export interface CauseMap {
78 | ILLEGAL_CONTENT: 0;
79 | MALWARE: 1;
80 | APP_ERROR: 2;
81 | QUESTION: 3;
82 | }
83 |
84 | export const Cause: CauseMap;
85 |
86 | export interface SourceMap {
87 | MAIL: 0;
88 | FORM: 1;
89 | }
90 |
91 | export const Source: SourceMap;
92 | }
93 |
94 | export class CheckRequest extends jspb.Message {
95 | getInfohash(): string;
96 | setInfohash(value: string): void;
97 |
98 | serializeBinary(): Uint8Array;
99 | toObject(includeInstance?: boolean): CheckRequest.AsObject;
100 | static toObject(includeInstance: boolean, msg: CheckRequest): CheckRequest.AsObject;
101 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
102 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
103 | static serializeBinaryToWriter(message: CheckRequest, writer: jspb.BinaryWriter): void;
104 | static deserializeBinary(bytes: Uint8Array): CheckRequest;
105 | static deserializeBinaryFromReader(message: CheckRequest, reader: jspb.BinaryReader): CheckRequest;
106 | }
107 |
108 | export namespace CheckRequest {
109 | export type AsObject = {
110 | infohash: string,
111 | }
112 | }
113 |
114 | export class CheckReply extends jspb.Message {
115 | getExists(): boolean;
116 | setExists(value: boolean): void;
117 |
118 | serializeBinary(): Uint8Array;
119 | toObject(includeInstance?: boolean): CheckReply.AsObject;
120 | static toObject(includeInstance: boolean, msg: CheckReply): CheckReply.AsObject;
121 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
122 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
123 | static serializeBinaryToWriter(message: CheckReply, writer: jspb.BinaryWriter): void;
124 | static deserializeBinary(bytes: Uint8Array): CheckReply;
125 | static deserializeBinaryFromReader(message: CheckReply, reader: jspb.BinaryReader): CheckReply;
126 | }
127 |
128 | export namespace CheckReply {
129 | export type AsObject = {
130 | exists: boolean,
131 | }
132 | }
133 |
134 |
--------------------------------------------------------------------------------
/src/sdk/loader/torrent/resource.js:
--------------------------------------------------------------------------------
1 | import parseTorrent from 'parse-torrent';
2 | class Content {
3 | constructor({path, name, type}, sdk, seeder) {
4 | this.path = path;
5 | this.name = name;
6 | this.type = type;
7 | this.sdk = sdk;
8 | this.seeder = seeder;
9 | }
10 | get isFile() {
11 | return this.type == 'file';
12 | }
13 | get isDir() {
14 | return this.type == 'dir';
15 | }
16 | get mediaType() {
17 | if (this.isDir) return null;
18 | return this.sdk.util.getMediaType(this.name);
19 | }
20 | async getMimeType() {
21 | if (this.isDir) return null;
22 | return this.sdk.util.getMimeType(await this.getStreamUrl());
23 | }
24 | async deliveryType() {
25 | if (this.isDir) return null;
26 | return this.sdk.util.getDeliveryType(this.name);
27 | }
28 | async getStreamUrl() {
29 | if (this.isDir) return null;
30 | return await this.seeder.streamUrl(this.path);
31 | }
32 | async getSegmentUrl(s, c) {
33 | if (this.isDir) return null;
34 | return await this.seeder.segmentUrl(this.path, s, c);
35 | }
36 | }
37 | class File extends Content {
38 | constructor(i, sdk, seeder) {
39 | super({
40 | path: '/' + i.path,
41 | name: i.name,
42 | type: 'file',
43 | }, sdk, seeder);
44 | this.length = i.length;
45 | }
46 | }
47 | class Dir extends Content {
48 | constructor(path, name, sdk, seeder) {
49 | super({
50 | path,
51 | name,
52 | type: 'dir',
53 | }, sdk, seeder);
54 | this.content = {};
55 | }
56 | }
57 | class Resource {
58 | type = 'torrent';
59 | constructor(torrent, sdk, seeder) {
60 | this.id = torrent.infoHash;
61 | this.torrent = torrent;
62 | this.sdk = sdk;
63 | this.seeder = seeder;
64 | }
65 | get title() {
66 | return this.torrent.name;
67 | }
68 | get shortType() {
69 | return this.type.charAt(0);
70 | }
71 | get magnetUri() {
72 | return parseTorrent.toMagnetURI(this.torrent);
73 | }
74 | addBranch(tree, parts, file, path) {
75 | if (parts.length == 0) return new File(file, this.sdk, this.seeder);
76 | const part = parts.shift();
77 | path.push(part);
78 | if (parts.length > 0) {
79 | if (tree[part] == undefined) {
80 | tree[part] = new Dir('/' + path.join('/'), part, this.sdk, this.seeder);
81 | }
82 | tree[part].content = this.addBranch(tree[part].content, parts, file, path);
83 | } else {
84 | tree[part] = new File(file, this.sdk, this.seeder);
85 | }
86 | return tree;
87 | }
88 | get tree() {
89 | let tree = {};
90 | for (let file of this.torrent.files) {
91 | const pathParts = file.path.split('/');
92 | tree = this.addBranch(tree, pathParts, file, []);
93 | }
94 | return tree;
95 | }
96 | get root() {
97 | return '/' + Object.keys(this.tree)[0];
98 | }
99 | dirname(path) {
100 | path = path.replace(/^\//, '').replace(/\/$/, '');
101 | path = path.split('/');
102 | let tree = this.tree;
103 | let dir = [];
104 | while (true) {
105 | const p = path.shift(path);
106 | if (tree[p] && tree[p].isDir) {
107 | dir.push(p);
108 | tree = tree[p].content;
109 | } else {
110 | break;
111 | }
112 | }
113 | return '/' + dir.join('/');
114 | }
115 | filename(path) {
116 | path = path.replace(/^\//, '').replace(/\/$/, '');
117 | path = path.split('/');
118 | let tree = this.tree;
119 | while (true) {
120 | const p = path.shift(path);
121 | if (tree[p]) {
122 | tree = tree[p];
123 | } else {
124 | break;
125 | }
126 | }
127 | if (tree.isFile && tree.isFile) {
128 | return tree.name;
129 | }
130 | return null
131 | }
132 | ls(path) {
133 | path = path.replace(/^\//, '').replace(/\/$/, '');
134 | if (!path) {
135 | path = [];
136 | } else {
137 | path = path.split('/');
138 | }
139 | let c = this.tree;
140 | for (let p of path) {
141 | c = c[p].content;
142 | }
143 | let res = [];
144 | for (let i in c) {
145 | res.push(c[i]);
146 | }
147 | if (path.length > 1) {
148 | path.pop();
149 | res.push(new Dir(
150 | path.join('/'),
151 | '..',
152 | ));
153 | }
154 | res = res.sort((a, b) => a.name.localeCompare(b.name));
155 | return res;
156 | }
157 | }
158 | export default function newResource(torrent, sdk) {
159 |
160 | const seeder = sdk.seeder.get(torrent.infoHash);
161 | return new Resource(torrent, sdk, seeder);
162 | }
--------------------------------------------------------------------------------
/src/sdk/torrent.js:
--------------------------------------------------------------------------------
1 | import {TorrentStore} from '../../proto/torrent-store/torrent-store_pb_service';
2 | import {PullRequest, PushRequest, TouchRequest} from '../../proto/torrent-store/torrent-store_pb';
3 | import {grpc} from '@improbable-eng/grpc-web';
4 | import process from './process';
5 | import parseTorrent from 'parse-torrent';
6 | const debug = require('debug')('webtor:sdk:torrent');
7 |
8 | export default function(params = {}) {
9 | const self = {params};
10 | return {
11 | fromUrl(url) {
12 | debug('fetch torrent from url=%s', url);
13 | return new Promise((resolve, reject) => {
14 | const xhr = new XMLHttpRequest();
15 | xhr.addEventListener('error', reject);
16 | xhr.onreadystatechange = async function() {
17 | if (this.readyState == XMLHttpRequest.DONE) {
18 | const ab = new Uint8Array(this.response);
19 | const buffer = new Buffer(ab.byteLength);
20 | const view = new Uint8Array(ab);
21 | for (let i = 0; i < buffer.length; ++i) {
22 | buffer[i] = view[i];
23 | }
24 | resolve(parseTorrent(buffer));
25 | }
26 | };
27 | xhr.open('GET', url);
28 | xhr.responseType = 'arraybuffer';
29 | xhr.send();
30 | });
31 | },
32 | pull(infoHash, metadata = {}, params = {}) {
33 | params = Object.assign(self.params, params);
34 | const url = params.apiUrl + params.endpoints.torrent;
35 | debug('pull torrent infoHash=%s url=%s metadata=%o', infoHash, url, metadata);
36 | const request = new PullRequest();
37 | request.setInfohash(infoHash);
38 | const client = () => grpc.client(TorrentStore.Pull, {
39 | host: url,
40 | // transport: grpc.WebsocketTransport(),
41 | debug: params.grpcDebug,
42 | });
43 | const onMessage = (message, resolve, reject) => {
44 | if (message.torrent == '') {
45 | return reject('no torrent');
46 | }
47 | let torrent = Buffer.from(message.torrent, 'base64');
48 | torrent = parseTorrent(torrent);
49 | debug('and finally torrent=%o', torrent);
50 | resolve(torrent);
51 | }
52 | const onEnd = (res, resolve, reject) => {
53 | if (res == grpc.Code.PermissionDenied) {
54 | reject('abused');
55 | } else if (res !== grpc.Code.OK) {
56 | reject('failed to pull torrent code=' + res);
57 | }
58 | }
59 | return process(client, request, onMessage, onEnd, metadata, params);
60 | },
61 | push(torrent, expire, metadata = {}, params = {}) {
62 | params = Object.assign(self.params, params);
63 | const url = params.apiUrl + params.endpoints.torrent;
64 | debug('push torrent url=%s metadata=%o', url, metadata);
65 | const request = new PushRequest();
66 | request.setTorrent(parseTorrent.toTorrentFile(torrent));
67 | const client = () => grpc.client(TorrentStore.Push, {
68 | host: url,
69 | // transport: grpc.WebsocketTransport(),
70 | debug: params.grpcDebug,
71 | });
72 | const onEnd = (res, resolve, reject) => {
73 | if (res === grpc.Code.OK) {
74 | debug('torrent stored');
75 | resolve();
76 | } else if (res === grpc.Code.NotFound) {
77 | reject('not found');
78 | } else if (res === grpc.Code.PermissionDenied) {
79 | reject('abused');
80 | } else {
81 | reject('failed to push torrent code=' + res);
82 | }
83 |
84 | }
85 | return process(client, request, null, onEnd, metadata, params);
86 | },
87 | touch(torrent, expire, metadata = {}, params = {}) {
88 | params = Object.assign(self.params, params);
89 | const url = params.apiUrl + params.endpoints.torrent;
90 | debug('touch torrent url=%s metadata=%o', url, metadata);
91 | const request = new TouchRequest();
92 | request.setInfohash(torrent.infoHash);
93 | const client = () => grpc.client(TorrentStore.Touch, {
94 | host: url,
95 | // transport: grpc.WebsocketTransport(),
96 | debug: params.grpcDebug,
97 | });
98 | const onEnd = (res, resolve, reject) => {
99 | if (res === grpc.Code.OK) {
100 | debug('torrent touched');
101 | resolve();
102 | } else if (res === grpc.Code.PermissionDenied) {
103 | reject('abused');
104 | } else if (res === grpc.Code.NotFound) {
105 | reject('not found');
106 | } else {
107 | reject('failed to touch torrent code=' + res);
108 | }
109 | }
110 | return process(client, request, null, onEnd, metadata, params);
111 | },
112 | };
113 | }
--------------------------------------------------------------------------------
/src/sdk/loader.js:
--------------------------------------------------------------------------------
1 | import parseTorrent from 'parse-torrent';
2 | import newTorrentResource from './loader/torrent/resource';
3 | const debug = require('debug')('webtor:sdk:loader');
4 | export default function(params, sdk) {
5 | const self = {params, sdk};
6 | return {
7 | async load(source, metadata, params = {}) {
8 | debug('loading source=%o', source);
9 |
10 | params = Object.assign(self.params, params);
11 | let torrent = false;
12 | if (torrent == false) torrent = await this.loadTorrentObject(source, metadata, params);
13 | if (torrent == false) torrent = await this.loadTorrentFile(source, metadata, params);
14 | if (torrent == false) torrent = await this.loadMagnet(source, metadata, params);
15 | if (torrent == false) torrent = await this.loadTorrentUrl(source, metadata, params);
16 | if (torrent != false) await this.pushTorrent(torrent, metadata, params);
17 | if (torrent == false) throw 'failed to load resource';
18 | return newTorrentResource(torrent, sdk);
19 | },
20 | async loadById(type, id, metadata, params = {}) {
21 | debug('loading type=%o id=%o', type, id);
22 | params = Object.assign(self.params, params);
23 | if (type == 'torrent' || type == 't') {
24 | let torrent = false;
25 | if (torrent == false) torrent = await this.loadMagnet(id, metadata, params);
26 | if (torrent != false) await this.pushTorrent(torrent, metadata, params);
27 | return newTorrentResource(torrent, sdk);
28 | }
29 | },
30 | async pushTorrent(torrent, metadata, params = {}) {
31 | const expire = 60 * 60 * 24 * 30; // 1 month
32 | params = Object.assign(self.params, params);
33 | debug('push torrent infohash=%o', torrent.infoHash);
34 | try {
35 | return await sdk.torrent.touch(torrent, expire, metadata);
36 | } catch (e) {
37 | if (e == 'not found') {
38 | try {
39 | return await sdk.torrent.push(torrent, expire, metadata);
40 | } catch (e) {
41 | debug(e);
42 | throw e;
43 | }
44 | } else {
45 | debug(e);
46 | throw e;
47 | }
48 | }
49 | },
50 | async loadTorrentObject(source, metadata, params = {}) {
51 | if (!(typeof source == 'object' && source.infoHash != undefined && source.files != undefined)) return false;
52 | return source;
53 | },
54 | async loadTorrentUrl(source, metadata, params = {}) {
55 | if (!source.match(/^http/)) return false;
56 | if (!source.match(/\.torrent$/) && !source.match(/[a-fA-F0-9]{40}/)) {
57 | return false;
58 | }
59 | source = await sdk.ext.url(source);
60 | return await new Promise((resolve, reject) => {
61 | const xhr = new XMLHttpRequest();
62 | xhr.addEventListener('error', reject);
63 | xhr.onreadystatechange = async function() {
64 | if (this.readyState == XMLHttpRequest.DONE) {
65 | const ab = new Uint8Array(this.response);
66 | const buffer = new Buffer(ab.byteLength);
67 | const view = new Uint8Array(ab);
68 | for (let i = 0; i < buffer.length; ++i) {
69 | buffer[i] = view[i];
70 | }
71 | resolve(parseTorrent(buffer));
72 | }
73 | };
74 | xhr.open('GET', source);
75 | xhr.responseType = 'arraybuffer';
76 | xhr.send();
77 | });
78 | },
79 | async loadTorrentFile(source, metadata, params = {}) {
80 | if (!(typeof source == 'object' && source.type == 'application/x-bittorrent' && source.size)) return false;
81 | try {
82 | const b = await this.fileToArray(source);
83 | return parseTorrent(b);
84 | } catch (e) {
85 | debug(e);
86 | throw e;
87 | }
88 | },
89 | async loadMagnet(source, metadata, params = {}) {
90 | params = Object.assign(self.params, params);
91 | let torrent = null;
92 | if (!source.match(/^magnet/) && !source.match(/^[a-fA-F0-9]{40}$/)) {
93 | return false;
94 | }
95 | try {
96 | torrent = parseTorrent(source);
97 | } catch (e) {
98 | debug(e);
99 | throw e;
100 | }
101 | const infoHash = torrent.infoHash;
102 | if (infoHash && params.db) {
103 | debug('loading from local db infohash=%o', infoHash)
104 | torrent = await params.db.pullTorrent(infoHash);
105 | }
106 | if (!torrent || !torrent.pieces || torrent.pieces.length == 0) {
107 | try {
108 | debug('loading from torrent store infohash=%o', infoHash)
109 | torrent = await sdk.torrent.pull(infoHash, metadata);
110 | } catch (e) {
111 | debug(e);
112 | throw e;
113 | }
114 | }
115 | if (!torrent) {
116 | debug('loading by magnet uri from peers magnet=%o', source);
117 | torrent = await sdk.magnet.fetchTorrent(source, metadata);
118 | }
119 | return torrent;
120 | },
121 | fileToArray(file) {
122 | return new Promise((resolve, reject) => {
123 | const reader = new FileReader();
124 | reader.addEventListener('load', (e) => {
125 | const arr = new Uint8Array(e.target.result);
126 | const buffer = new Buffer(arr);
127 | try {
128 | resolve(buffer);
129 | } catch(e) {
130 | reject(e);
131 | }
132 | });
133 | reader.addEventListener('error', (err) => {
134 | reject(err);
135 | });
136 | reader.readAsArrayBuffer(file);
137 | });
138 | }
139 | };
140 | };
--------------------------------------------------------------------------------
/proto/torrent-web-seeder/torrent-web-seeder_pb.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/torrent-web-seeder/torrent-web-seeder.proto
3 |
4 | import * as jspb from "google-protobuf";
5 |
6 | export class StatRequest extends jspb.Message {
7 | getPath(): string;
8 | setPath(value: string): void;
9 |
10 | serializeBinary(): Uint8Array;
11 | toObject(includeInstance?: boolean): StatRequest.AsObject;
12 | static toObject(includeInstance: boolean, msg: StatRequest): StatRequest.AsObject;
13 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
14 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
15 | static serializeBinaryToWriter(message: StatRequest, writer: jspb.BinaryWriter): void;
16 | static deserializeBinary(bytes: Uint8Array): StatRequest;
17 | static deserializeBinaryFromReader(message: StatRequest, reader: jspb.BinaryReader): StatRequest;
18 | }
19 |
20 | export namespace StatRequest {
21 | export type AsObject = {
22 | path: string,
23 | }
24 | }
25 |
26 | export class StatReply extends jspb.Message {
27 | getTotal(): number;
28 | setTotal(value: number): void;
29 |
30 | getCompleted(): number;
31 | setCompleted(value: number): void;
32 |
33 | getPeers(): number;
34 | setPeers(value: number): void;
35 |
36 | getStatus(): StatReply.StatusMap[keyof StatReply.StatusMap];
37 | setStatus(value: StatReply.StatusMap[keyof StatReply.StatusMap]): void;
38 |
39 | clearPiecesList(): void;
40 | getPiecesList(): Array;
41 | setPiecesList(value: Array): void;
42 | addPieces(value?: Piece, index?: number): Piece;
43 |
44 | getSeeders(): number;
45 | setSeeders(value: number): void;
46 |
47 | getLeechers(): number;
48 | setLeechers(value: number): void;
49 |
50 | serializeBinary(): Uint8Array;
51 | toObject(includeInstance?: boolean): StatReply.AsObject;
52 | static toObject(includeInstance: boolean, msg: StatReply): StatReply.AsObject;
53 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
54 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
55 | static serializeBinaryToWriter(message: StatReply, writer: jspb.BinaryWriter): void;
56 | static deserializeBinary(bytes: Uint8Array): StatReply;
57 | static deserializeBinaryFromReader(message: StatReply, reader: jspb.BinaryReader): StatReply;
58 | }
59 |
60 | export namespace StatReply {
61 | export type AsObject = {
62 | total: number,
63 | completed: number,
64 | peers: number,
65 | status: StatReply.StatusMap[keyof StatReply.StatusMap],
66 | piecesList: Array,
67 | seeders: number,
68 | leechers: number,
69 | }
70 |
71 | export interface StatusMap {
72 | INITIALIZATION: 0;
73 | SEEDING: 1;
74 | IDLE: 2;
75 | TERMINATED: 3;
76 | WAITING_FOR_PEERS: 4;
77 | RESTORING: 5;
78 | BACKINGUP: 6;
79 | }
80 |
81 | export const Status: StatusMap;
82 | }
83 |
84 | export class Piece extends jspb.Message {
85 | getPosition(): number;
86 | setPosition(value: number): void;
87 |
88 | getComplete(): boolean;
89 | setComplete(value: boolean): void;
90 |
91 | getPriority(): Piece.PriorityMap[keyof Piece.PriorityMap];
92 | setPriority(value: Piece.PriorityMap[keyof Piece.PriorityMap]): void;
93 |
94 | serializeBinary(): Uint8Array;
95 | toObject(includeInstance?: boolean): Piece.AsObject;
96 | static toObject(includeInstance: boolean, msg: Piece): Piece.AsObject;
97 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
98 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
99 | static serializeBinaryToWriter(message: Piece, writer: jspb.BinaryWriter): void;
100 | static deserializeBinary(bytes: Uint8Array): Piece;
101 | static deserializeBinaryFromReader(message: Piece, reader: jspb.BinaryReader): Piece;
102 | }
103 |
104 | export namespace Piece {
105 | export type AsObject = {
106 | position: number,
107 | complete: boolean,
108 | priority: Piece.PriorityMap[keyof Piece.PriorityMap],
109 | }
110 |
111 | export interface PriorityMap {
112 | NONE: 0;
113 | NORMAL: 1;
114 | HIGH: 2;
115 | READAHEAD: 3;
116 | NEXT: 4;
117 | NOW: 5;
118 | }
119 |
120 | export const Priority: PriorityMap;
121 | }
122 |
123 | export class FilesRequest extends jspb.Message {
124 | serializeBinary(): Uint8Array;
125 | toObject(includeInstance?: boolean): FilesRequest.AsObject;
126 | static toObject(includeInstance: boolean, msg: FilesRequest): FilesRequest.AsObject;
127 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
128 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
129 | static serializeBinaryToWriter(message: FilesRequest, writer: jspb.BinaryWriter): void;
130 | static deserializeBinary(bytes: Uint8Array): FilesRequest;
131 | static deserializeBinaryFromReader(message: FilesRequest, reader: jspb.BinaryReader): FilesRequest;
132 | }
133 |
134 | export namespace FilesRequest {
135 | export type AsObject = {
136 | }
137 | }
138 |
139 | export class File extends jspb.Message {
140 | getPath(): string;
141 | setPath(value: string): void;
142 |
143 | serializeBinary(): Uint8Array;
144 | toObject(includeInstance?: boolean): File.AsObject;
145 | static toObject(includeInstance: boolean, msg: File): File.AsObject;
146 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
147 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
148 | static serializeBinaryToWriter(message: File, writer: jspb.BinaryWriter): void;
149 | static deserializeBinary(bytes: Uint8Array): File;
150 | static deserializeBinaryFromReader(message: File, reader: jspb.BinaryReader): File;
151 | }
152 |
153 | export namespace File {
154 | export type AsObject = {
155 | path: string,
156 | }
157 | }
158 |
159 | export class FilesReply extends jspb.Message {
160 | clearFilesList(): void;
161 | getFilesList(): Array;
162 | setFilesList(value: Array): void;
163 | addFiles(value?: File, index?: number): File;
164 |
165 | serializeBinary(): Uint8Array;
166 | toObject(includeInstance?: boolean): FilesReply.AsObject;
167 | static toObject(includeInstance: boolean, msg: FilesReply): FilesReply.AsObject;
168 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
169 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
170 | static serializeBinaryToWriter(message: FilesReply, writer: jspb.BinaryWriter): void;
171 | static deserializeBinary(bytes: Uint8Array): FilesReply;
172 | static deserializeBinaryFromReader(message: FilesReply, reader: jspb.BinaryReader): FilesReply;
173 | }
174 |
175 | export namespace FilesReply {
176 | export type AsObject = {
177 | filesList: Array,
178 | }
179 | }
180 |
181 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ⚠️ [ARCHIVED] Webtor Platform SDK (JS)
2 |
3 | This repository is now **archived** and no longer maintained.
4 | For continued development and self-hosted solutions, please refer to the **new repository**:
5 |
6 | 👉 **[Webtor.io Self-Hosted](https://github.com/webtor-io/self-hosted)**
7 |
8 | ## ❓ What This Means
9 | - No further updates or maintenance will be provided for this repository.
10 | - We recommend **migrating** to the **self-hosted** Webtor.io solution.
11 | - Issues and feature requests will no longer be addressed here.
12 |
13 | ## 🔗 Migration Guide
14 | To set up and use Webtor.io in a self-hosted environment, visit:
15 | 📌 **[Webtor.io Self-Hosted Documentation](https://github.com/webtor-io/self-hosted)**
16 |
17 | ---
18 |
19 | Thank you for your support and contributions! 🚀
20 |
21 | ## Features
22 | 1. Online torrent content streaming without waiting for full download
23 | 2. On-the-fly content transcoding
24 | 3. Downloading torrent as ZIP-archive
25 | 4. Subtitle transcoding, srt to vtt
26 | 5. OpenSubtitles support
27 | 6. Streaming of external resources (including transcoding)
28 |
29 | ## Supported formats
30 | * Video: avi, mkv, mp4, webm, m4v
31 | * Audio: mp3, wav, ogg, flac, m4a
32 | * Images: png, gif, jpg, jpeg
33 | * Subtitles: srt, vtt
34 |
35 | ## Prerequisites
36 | Before moving further we must be sure that webtor backend api is already installed.
37 | Just follow [this guide](https://github.com/webtor-io/helm-charts) to setup all the things.
38 |
39 | ## Installation
40 | ```bash
41 | npm install @webtor/platform-sdk-js
42 | ```
43 | or
44 | ```bash
45 | yarn add @webtor/platform-sdk-js
46 | ```
47 |
48 | ## Basic usage
49 | Just a simple example of fetching torrent by magnet-uri, getting streaming url and stats:
50 | ```js
51 | import webtor from '@webtor/platform-sdk-js';
52 |
53 | const sdk = webtor({
54 | apiUrl: '...',
55 | });
56 |
57 | const magnetUri = '...';
58 |
59 | const torrent = await sdk.magnet.fetchTorrent(magnetUri);
60 |
61 | const expire = 60*60*24;
62 |
63 | await sdk.torrent.push(torrent, expire);
64 |
65 | const seeder = sdk.seeder.get(torrent.infoHash);
66 |
67 | const filePath = torrent.files[0].path;
68 |
69 | const url = await seeder.streamUrl(filePath);
70 | console.log(url);
71 |
72 | // NOTE: stats will become available only after content url access
73 | seeder.stats(filePath, (path, data) => {
74 | console.log(data);
75 | });
76 | ```
77 | You can find fully working example [here](https://github.com/webtor-io/platform-sdk-js/tree/master/example)!
78 |
79 | ## Initialization
80 |
81 | ### `const sdk = webtor(options)`
82 |
83 | `options` should be the following:
84 |
85 | ```
86 | {
87 | apiUrl: String, // API url (required)
88 | apiKey: String, // API key
89 | downloadUrl: String, // All download urls will contain this location
90 | tokenUrl: String, // API will get access-token from this location
91 | tokenRenewInterval: Number, // Renews access-token after specific period in ms
92 | grpcDebug: Boolean, // If enabled shows grpc-web debug output
93 | statsRetryInterval: Number, // If stats not available for this file it will retry after specific period in ms (default=3000)
94 | getToken: function() Promise // If defined custom token-function will be used
95 | }
96 | ```
97 |
98 | ## sdk.torrent
99 | Provides functions for storing and retriving torrent-files.
100 |
101 | ### `sdk.torrent.fromUrl(url)`
102 | Fetches parsed torrent from specific url. Be sure that appropriate CORS-headers are set on server-side in case of cross-site request (`Access-Control-Allow-Origin: *`).
103 |
104 | ### `sdk.torrent.pull(infoHash)`
105 | Pulls parsed torrent by infoHash from torrent-store.
106 |
107 | ### `sdk.torrent.push(torrent, expire)`
108 | Pushes parsed torrent to torrent-store with specific expiration time in seconds. We can use any parsed torrent generated by [parse-torrent](https://github.com/webtorrent/parse-torrent) there.
109 |
110 | ### `sdk.torrent.touch(torrent, expire)`
111 | Just renews expiration date of torrent-file.
112 |
113 | ## sdk.magnet
114 | Provides functions for working with magnet-urls.
115 |
116 | ### `sdk.magnet.fetchTorrent(magnet)`
117 | Fetches parsed torrent by magnet-uri.
118 |
119 | ## sdk.seeder
120 | Provides functions for retriving and streaming torrent-content.
121 |
122 | ### `const seeder = sdk.seeder.get(infoHash)`
123 | Returns seeder instance for the specific torrent stored in torrent-store.
124 |
125 | ### `seeder.url(path)`
126 | Returns `url` for original source file.
127 |
128 | ### `seeder.streamUrl(path, viewSettings = {})`
129 | Returns url capable for web-streaming.
130 | `viewSettings` should be provided only in case of content trnascoding.
131 | Possible `viewSettings`:
132 | ```
133 | {
134 | a: Number, // Selected audio channel
135 | s: Number, // Selected subtitle channel
136 | }
137 | ```
138 |
139 | ### `seeder.streamSubtitleUrl(path, viewSettings = {})`
140 | Returns subtitle-url capable for web-streaming. Can be used only for hls-transcoded content.
141 | `viewSettings` should be provided only in case of content trnascoding.
142 | Possible `viewSettings`:
143 | ```
144 | {
145 | a: Number, // Selected audio channel
146 | s: Number, // Selected subtitle channel
147 | }
148 | ```
149 |
150 | ### `seeder.mediaInfo(path)`
151 | Returns FFmpeg probing data. If content should not be transcoded only empty object `{}` will be returned.
152 |
153 | ### `seeder.downloadUrl(path)`
154 | Returns download url.
155 |
156 | ### `seeder.zipUrl(path)`
157 | Returns download url of zip-archive. Generates zip-archive of all files under directory and subdirectories specified by the `path`.
158 |
159 | ### `seeder.openSubtitles(path)`
160 | Returns object that includes all subtitles from [OpenSubtitles.org](https://opensubtitles.org). Automatically generates streaming urls for every subtitle (srt => vtt encoding).
161 |
162 | ### `const statClient = seeder.stats(path, function(path, data) { ... })`
163 | Receives status of specific file. Possible data:
164 | ```
165 | {
166 | total: Number // Number of total bytes
167 | completed: Number // Number of completed bytes
168 | peers: Number // Total number of peers
169 | piecesList: [] // Array of pieces
170 | }
171 | ```
172 | Also returns instance of stat client.
173 |
174 | ### `statClient.close()`
175 | Closes stat client
176 |
177 | ## sdk.ext
178 | Provides functions for retriving and streaming external resources.
179 |
180 | ### `sdk.ext.url(url)`
181 | Returns `url` for original external file proxied by the api. Can resolve CORS-issues.
182 |
183 | ### `sdk.ext.streamUrl(url, viewSettings = {})`
184 | Same as [`seeder.streamUrl`](#seeder-stream-url) but for external resource.
185 |
186 | ### `sdk.ext.streamSubtitleUrl(url, viewSettings = {})`
187 | Same as [`seeder.streamSubtitleUrl`](#seeder-stream-subtitle-url) but for external resource.
188 |
189 | ### `sdk.ext.mediaInfo(url)`
190 | Same as [`seeder.mediaInfo`](#seeder-media-info) but for external resource.
191 |
192 | ### `sdk.ext.openSubtitles(url)`
193 | Same as [`seeder.openSubtitles`](#seeder-opensubtitles) but for external resource.
194 |
--------------------------------------------------------------------------------
/proto/torrent-store/torrent-store_pb.d.ts:
--------------------------------------------------------------------------------
1 | // package:
2 | // file: proto/torrent-store/torrent-store.proto
3 |
4 | import * as jspb from "google-protobuf";
5 |
6 | export class PushReply extends jspb.Message {
7 | getInfohash(): string;
8 | setInfohash(value: string): void;
9 |
10 | serializeBinary(): Uint8Array;
11 | toObject(includeInstance?: boolean): PushReply.AsObject;
12 | static toObject(includeInstance: boolean, msg: PushReply): PushReply.AsObject;
13 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
14 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
15 | static serializeBinaryToWriter(message: PushReply, writer: jspb.BinaryWriter): void;
16 | static deserializeBinary(bytes: Uint8Array): PushReply;
17 | static deserializeBinaryFromReader(message: PushReply, reader: jspb.BinaryReader): PushReply;
18 | }
19 |
20 | export namespace PushReply {
21 | export type AsObject = {
22 | infohash: string,
23 | }
24 | }
25 |
26 | export class PushRequest extends jspb.Message {
27 | getTorrent(): Uint8Array | string;
28 | getTorrent_asU8(): Uint8Array;
29 | getTorrent_asB64(): string;
30 | setTorrent(value: Uint8Array | string): void;
31 |
32 | getExpire(): number;
33 | setExpire(value: number): void;
34 |
35 | serializeBinary(): Uint8Array;
36 | toObject(includeInstance?: boolean): PushRequest.AsObject;
37 | static toObject(includeInstance: boolean, msg: PushRequest): PushRequest.AsObject;
38 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
39 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
40 | static serializeBinaryToWriter(message: PushRequest, writer: jspb.BinaryWriter): void;
41 | static deserializeBinary(bytes: Uint8Array): PushRequest;
42 | static deserializeBinaryFromReader(message: PushRequest, reader: jspb.BinaryReader): PushRequest;
43 | }
44 |
45 | export namespace PushRequest {
46 | export type AsObject = {
47 | torrent: Uint8Array | string,
48 | expire: number,
49 | }
50 | }
51 |
52 | export class PullRequest extends jspb.Message {
53 | getInfohash(): string;
54 | setInfohash(value: string): void;
55 |
56 | serializeBinary(): Uint8Array;
57 | toObject(includeInstance?: boolean): PullRequest.AsObject;
58 | static toObject(includeInstance: boolean, msg: PullRequest): PullRequest.AsObject;
59 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
60 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
61 | static serializeBinaryToWriter(message: PullRequest, writer: jspb.BinaryWriter): void;
62 | static deserializeBinary(bytes: Uint8Array): PullRequest;
63 | static deserializeBinaryFromReader(message: PullRequest, reader: jspb.BinaryReader): PullRequest;
64 | }
65 |
66 | export namespace PullRequest {
67 | export type AsObject = {
68 | infohash: string,
69 | }
70 | }
71 |
72 | export class PullReply extends jspb.Message {
73 | getTorrent(): Uint8Array | string;
74 | getTorrent_asU8(): Uint8Array;
75 | getTorrent_asB64(): string;
76 | setTorrent(value: Uint8Array | string): void;
77 |
78 | serializeBinary(): Uint8Array;
79 | toObject(includeInstance?: boolean): PullReply.AsObject;
80 | static toObject(includeInstance: boolean, msg: PullReply): PullReply.AsObject;
81 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
82 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
83 | static serializeBinaryToWriter(message: PullReply, writer: jspb.BinaryWriter): void;
84 | static deserializeBinary(bytes: Uint8Array): PullReply;
85 | static deserializeBinaryFromReader(message: PullReply, reader: jspb.BinaryReader): PullReply;
86 | }
87 |
88 | export namespace PullReply {
89 | export type AsObject = {
90 | torrent: Uint8Array | string,
91 | }
92 | }
93 |
94 | export class CheckRequest extends jspb.Message {
95 | getInfohash(): string;
96 | setInfohash(value: string): void;
97 |
98 | serializeBinary(): Uint8Array;
99 | toObject(includeInstance?: boolean): CheckRequest.AsObject;
100 | static toObject(includeInstance: boolean, msg: CheckRequest): CheckRequest.AsObject;
101 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
102 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
103 | static serializeBinaryToWriter(message: CheckRequest, writer: jspb.BinaryWriter): void;
104 | static deserializeBinary(bytes: Uint8Array): CheckRequest;
105 | static deserializeBinaryFromReader(message: CheckRequest, reader: jspb.BinaryReader): CheckRequest;
106 | }
107 |
108 | export namespace CheckRequest {
109 | export type AsObject = {
110 | infohash: string,
111 | }
112 | }
113 |
114 | export class CheckReply extends jspb.Message {
115 | getExists(): boolean;
116 | setExists(value: boolean): void;
117 |
118 | serializeBinary(): Uint8Array;
119 | toObject(includeInstance?: boolean): CheckReply.AsObject;
120 | static toObject(includeInstance: boolean, msg: CheckReply): CheckReply.AsObject;
121 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
122 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
123 | static serializeBinaryToWriter(message: CheckReply, writer: jspb.BinaryWriter): void;
124 | static deserializeBinary(bytes: Uint8Array): CheckReply;
125 | static deserializeBinaryFromReader(message: CheckReply, reader: jspb.BinaryReader): CheckReply;
126 | }
127 |
128 | export namespace CheckReply {
129 | export type AsObject = {
130 | exists: boolean,
131 | }
132 | }
133 |
134 | export class TouchReply extends jspb.Message {
135 | serializeBinary(): Uint8Array;
136 | toObject(includeInstance?: boolean): TouchReply.AsObject;
137 | static toObject(includeInstance: boolean, msg: TouchReply): TouchReply.AsObject;
138 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
139 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
140 | static serializeBinaryToWriter(message: TouchReply, writer: jspb.BinaryWriter): void;
141 | static deserializeBinary(bytes: Uint8Array): TouchReply;
142 | static deserializeBinaryFromReader(message: TouchReply, reader: jspb.BinaryReader): TouchReply;
143 | }
144 |
145 | export namespace TouchReply {
146 | export type AsObject = {
147 | }
148 | }
149 |
150 | export class TouchRequest extends jspb.Message {
151 | getInfohash(): string;
152 | setInfohash(value: string): void;
153 |
154 | getExpire(): number;
155 | setExpire(value: number): void;
156 |
157 | serializeBinary(): Uint8Array;
158 | toObject(includeInstance?: boolean): TouchRequest.AsObject;
159 | static toObject(includeInstance: boolean, msg: TouchRequest): TouchRequest.AsObject;
160 | static extensions: {[key: number]: jspb.ExtensionFieldInfo};
161 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
162 | static serializeBinaryToWriter(message: TouchRequest, writer: jspb.BinaryWriter): void;
163 | static deserializeBinary(bytes: Uint8Array): TouchRequest;
164 | static deserializeBinaryFromReader(message: TouchRequest, reader: jspb.BinaryReader): TouchRequest;
165 | }
166 |
167 | export namespace TouchRequest {
168 | export type AsObject = {
169 | infohash: string,
170 | expire: number,
171 | }
172 | }
173 |
174 |
--------------------------------------------------------------------------------
/src/sdk/seeder.js:
--------------------------------------------------------------------------------
1 | import stats from './seeder/stats';
2 | import downloadProgress from './seeder/downloadProgress';
3 | const debug = require('debug')('webtor:sdk:seeder');
4 | const Url = require('url-parse');
5 | var md5 = require('md5');
6 |
7 | class WebSeeder {
8 | constructor(infoHash, params, sdk) {
9 | this.infoHash = infoHash;
10 | this.params = params;
11 | this.sdk = sdk;
12 | }
13 |
14 | addDownloadId(metadata = {}, path) {
15 | if (!metadata['download-id']) {
16 | metadata = Object.assign({}, metadata, {
17 | 'download-id': md5(metadata['user-id'] + this.infoHash + path + Date.now().toString()),
18 | });
19 | }
20 | return metadata;
21 | }
22 |
23 | async url(path, metadata = {}, params = {}, context = {}) {
24 | params = Object.assign({}, this.params, params);
25 | path = path.replace(/^\//, '');
26 | let url = new Url(params.apiUrl);
27 | metadata = this.addDownloadId(metadata, path);
28 | url.infoHash = this.infoHash;
29 | url.path = path;
30 | const pathname = '/' + this.infoHash + '/' + encodeURIComponent(path);
31 | url.infoHash = this.infoHash;
32 | url.set('pathname', pathname);
33 | const query = await this.sdk.util.makeQuery(metadata, params);
34 | url.set('query', query);
35 |
36 | if (params.subdomains) {
37 | url = await this.sdk.util.cacheUrl(url, metadata, params);
38 | const cached = await this.sdk.util.isCached(url, metadata, params);
39 | // const completedPieces = await this.sdk.util.throttledCompletedPieces(url, metadata, params);
40 | // const pieceCache = completedPieces.length > 0;
41 | const deliveryType = this.sdk.util.getDeliveryType(url.pathname);
42 | if (deliveryType === undefined) return url;
43 | let pool = deliveryType == 'transcode' ? params.pools.transcoder : params.pools.seeder;
44 | pool = cached ? params.pools.cache : pool;
45 | const m = {
46 | infohash: this.infoHash,
47 | "use-bandwidth": cached,
48 | "use-cpu": !cached,
49 | "skip-active-job-search": cached,
50 | pool: pool.join(','),
51 | }
52 | const subdomainUrl = await this.sdk.util.subdomainUrl(url, context, m, params);
53 | if (subdomainUrl === false) return false;
54 | subdomainUrl.primaryHost = url.host;
55 | if (subdomainUrl) {
56 | return subdomainUrl;
57 | }
58 | }
59 | return url;
60 | }
61 |
62 | async urlPostProcess(url, metadata, params) {
63 | const cp = await this.completedPieces(metadata, params);
64 | if (cp.length == 0) {
65 | return url;
66 | }
67 | const cdnUrl = this.sdk.util.cdnUrl(url, metadata, params);
68 | if (cdnUrl) {
69 | return cdnUrl;
70 | }
71 | return url;
72 | }
73 |
74 | async streamUrl(path, metadata = {}, params = {}, context = {}) {
75 | params = Object.assign({}, this.params, params);
76 | let url = await this.url(path, metadata, params, context);
77 | url = await this.sdk.util.streamUrl(url, metadata, params, context);
78 | url = await this.urlPostProcess(url, metadata, params);
79 | return url;
80 | }
81 |
82 | async segmentUrl(path, segment, context = {}, metadata = {}, params = {}) {
83 | params = Object.assign({}, this.params, params);
84 | let url = await this.url(path, metadata, params, context);
85 | if (url === false) return false;
86 | url = await this.sdk.util.segmentUrl(url, segment, metadata, params, context);
87 | url = await this.urlPostProcess(url, metadata, params);
88 | return url;
89 | }
90 |
91 | async error(path, metadata = {}, params = {}, context = {}) {
92 | params = Object.assign({}, this.params, params);
93 | let url = await this.url(path, metadata, params, context);
94 | return await this.sdk.util.error(url, metadata, params);
95 | }
96 |
97 | async pieceUrl(id, metadata = {}, params = {}) {
98 | let url = await this.url('', metadata, params);
99 | return this.sdk.util.pieceUrl(url, id);
100 | }
101 |
102 | async mediaInfo(path, metadata = {}, params = {}) {
103 | params = Object.assign({}, this.params, params);
104 | const url = await this.url(path, metadata, params);
105 | return await this.sdk.util.mediaInfo(url, metadata, params);
106 | }
107 |
108 | async completedPieces(metadata = {}, params = {}) {
109 | params = Object.assign({}, this.params, params);
110 | const url = await this.url('', metadata, params);
111 | return await this.sdk.util.throttledCompletedPieces(url, metadata, params);
112 | }
113 |
114 | async isCached(path, metadata = {}, params = {}) {
115 | params = Object.assign({}, this.params, params);
116 | const url = await this.url(path, metadata, params);
117 | const cached = await this.sdk.util.isCached(url, metadata, params);
118 | return cached;
119 | }
120 |
121 | async openSubtitles(path, metadata = {}, params = {}) {
122 | const url = await this.url(path, metadata, params);
123 | return await this.sdk.util.openSubtitles(url);
124 | }
125 |
126 | async downloadUrl(path, metadata = {}, params = {}, context = {}) {
127 | params = Object.assign({}, this.params, params);
128 | if (params.downloadUrl) {
129 | params.apiUrl = params.downloadUrl;
130 | }
131 | metadata.download = true;
132 | let url = await this.url(path, metadata, params, context);
133 | url = await this.urlPostProcess(url, metadata, params);
134 | return url;
135 | }
136 |
137 | async downloadUrlWithProgress(path, onMessage, onEnd, metadata = {}, params = {}, context = {}) {
138 | params = Object.assign({}, this.params, params, {cdn: false});
139 | metadata = this.addDownloadId(metadata, path);
140 | const downloadUrl = await this.downloadUrl(path, metadata, params, context);
141 | const fileName = path.split('/').pop();
142 | const url = this.sdk.util.dpUrl(downloadUrl, fileName);
143 | const statUrl = this.sdk.util.dpStatUrl(downloadUrl);
144 | downloadProgress(statUrl, path, onMessage, onEnd, metadata, params);
145 | return url;
146 | }
147 |
148 | async zipUrl(path, metadata = {}, params = {}, context = {}) {
149 | params = Object.assign({}, this.params, params);
150 | if (params.downloadUrl) {
151 | params.apiUrl = params.downloadUrl;
152 | }
153 | const fileName = path.split('/').pop();
154 | let url = await this.url(path, metadata, params, context);
155 | url.set('pathname', url.pathname + '~arch/' + fileName + '.zip');
156 | return url;
157 | }
158 | async zipUrlWithProgress(path, onMessage, onEnd, metadata = {}, params = {}, context = {}) {
159 | params = Object.assign({}, this.params, params, {cdn: false});
160 | metadata = this.addDownloadId(metadata, path);
161 | const zipUrl = await this.zipUrl(path, metadata, params, context);
162 | const fileName = path.split('/').pop() + '.zip';
163 | const url = this.sdk.util.dpUrl(zipUrl, fileName);
164 | const statUrl = this.sdk.util.dpStatUrl(zipUrl);
165 | downloadProgress(statUrl, path, onMessage, onEnd, metadata, params);
166 | return url;
167 | }
168 |
169 | stats(path, onMessage, metadata = {}, params = {}) {
170 | params = Object.assign({}, this.params, params);
171 | const url = `${params.apiUrl}/${this.infoHash}`;
172 | debug('get file stats infoHash=%s url=%s path=%s metadata=%o', this.infoHash, url, path, metadata);
173 | return stats(url, path, onMessage, metadata, params);
174 | }
175 | }
176 |
177 | export default function(params, sdk) {
178 | const self = {params, sdk};
179 | return {
180 | get(infoHash, metadata = {}, params = {}) {
181 | params = Object.assign({}, self.params, params);
182 | return new WebSeeder(infoHash, params, self.sdk);
183 | },
184 | };
185 | };
--------------------------------------------------------------------------------
/proto/magnet2torrent/magnet2torrent_pb.js:
--------------------------------------------------------------------------------
1 | // source: proto/magnet2torrent/magnet2torrent.proto
2 | /**
3 | * @fileoverview
4 | * @enhanceable
5 | * @suppress {messageConventions} JS Compiler reports an error if a variable or
6 | * field starts with 'MSG_' and isn't a translatable message.
7 | * @public
8 | */
9 | // GENERATED CODE -- DO NOT EDIT!
10 | /* eslint-disable */
11 | // @ts-nocheck
12 |
13 | var jspb = require('google-protobuf');
14 | var goog = jspb;
15 | var proto = {};
16 |
17 | goog.exportSymbol('Magnet2TorrentReply', null, proto);
18 | goog.exportSymbol('Magnet2TorrentRequest', null, proto);
19 | /**
20 | * Generated by JsPbCodeGenerator.
21 | * @param {Array=} opt_data Optional initial data array, typically from a
22 | * server response, or constructed directly in Javascript. The array is used
23 | * in place and becomes part of the constructed object. It is not cloned.
24 | * If no data is provided, the constructed object will be empty, but still
25 | * valid.
26 | * @extends {jspb.Message}
27 | * @constructor
28 | */
29 | proto.Magnet2TorrentRequest = function(opt_data) {
30 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
31 | };
32 | goog.inherits(proto.Magnet2TorrentRequest, jspb.Message);
33 | if (goog.DEBUG && !COMPILED) {
34 | /**
35 | * @public
36 | * @override
37 | */
38 | proto.Magnet2TorrentRequest.displayName = 'proto.Magnet2TorrentRequest';
39 | }
40 | /**
41 | * Generated by JsPbCodeGenerator.
42 | * @param {Array=} opt_data Optional initial data array, typically from a
43 | * server response, or constructed directly in Javascript. The array is used
44 | * in place and becomes part of the constructed object. It is not cloned.
45 | * If no data is provided, the constructed object will be empty, but still
46 | * valid.
47 | * @extends {jspb.Message}
48 | * @constructor
49 | */
50 | proto.Magnet2TorrentReply = function(opt_data) {
51 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
52 | };
53 | goog.inherits(proto.Magnet2TorrentReply, jspb.Message);
54 | if (goog.DEBUG && !COMPILED) {
55 | /**
56 | * @public
57 | * @override
58 | */
59 | proto.Magnet2TorrentReply.displayName = 'proto.Magnet2TorrentReply';
60 | }
61 |
62 |
63 |
64 | if (jspb.Message.GENERATE_TO_OBJECT) {
65 | /**
66 | * Creates an object representation of this proto.
67 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
68 | * Optional fields that are not set will be set to undefined.
69 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
70 | * For the list of reserved names please see:
71 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
72 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
73 | * JSPB instance for transitional soy proto support:
74 | * http://goto/soy-param-migration
75 | * @return {!Object}
76 | */
77 | proto.Magnet2TorrentRequest.prototype.toObject = function(opt_includeInstance) {
78 | return proto.Magnet2TorrentRequest.toObject(opt_includeInstance, this);
79 | };
80 |
81 |
82 | /**
83 | * Static version of the {@see toObject} method.
84 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
85 | * the JSPB instance for transitional soy proto support:
86 | * http://goto/soy-param-migration
87 | * @param {!proto.Magnet2TorrentRequest} msg The msg instance to transform.
88 | * @return {!Object}
89 | * @suppress {unusedLocalVariables} f is only used for nested messages
90 | */
91 | proto.Magnet2TorrentRequest.toObject = function(includeInstance, msg) {
92 | var f, obj = {
93 | magnet: jspb.Message.getFieldWithDefault(msg, 1, "")
94 | };
95 |
96 | if (includeInstance) {
97 | obj.$jspbMessageInstance = msg;
98 | }
99 | return obj;
100 | };
101 | }
102 |
103 |
104 | /**
105 | * Deserializes binary data (in protobuf wire format).
106 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
107 | * @return {!proto.Magnet2TorrentRequest}
108 | */
109 | proto.Magnet2TorrentRequest.deserializeBinary = function(bytes) {
110 | var reader = new jspb.BinaryReader(bytes);
111 | var msg = new proto.Magnet2TorrentRequest;
112 | return proto.Magnet2TorrentRequest.deserializeBinaryFromReader(msg, reader);
113 | };
114 |
115 |
116 | /**
117 | * Deserializes binary data (in protobuf wire format) from the
118 | * given reader into the given message object.
119 | * @param {!proto.Magnet2TorrentRequest} msg The message object to deserialize into.
120 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
121 | * @return {!proto.Magnet2TorrentRequest}
122 | */
123 | proto.Magnet2TorrentRequest.deserializeBinaryFromReader = function(msg, reader) {
124 | while (reader.nextField()) {
125 | if (reader.isEndGroup()) {
126 | break;
127 | }
128 | var field = reader.getFieldNumber();
129 | switch (field) {
130 | case 1:
131 | var value = /** @type {string} */ (reader.readString());
132 | msg.setMagnet(value);
133 | break;
134 | default:
135 | reader.skipField();
136 | break;
137 | }
138 | }
139 | return msg;
140 | };
141 |
142 |
143 | /**
144 | * Serializes the message to binary data (in protobuf wire format).
145 | * @return {!Uint8Array}
146 | */
147 | proto.Magnet2TorrentRequest.prototype.serializeBinary = function() {
148 | var writer = new jspb.BinaryWriter();
149 | proto.Magnet2TorrentRequest.serializeBinaryToWriter(this, writer);
150 | return writer.getResultBuffer();
151 | };
152 |
153 |
154 | /**
155 | * Serializes the given message to binary data (in protobuf wire
156 | * format), writing to the given BinaryWriter.
157 | * @param {!proto.Magnet2TorrentRequest} message
158 | * @param {!jspb.BinaryWriter} writer
159 | * @suppress {unusedLocalVariables} f is only used for nested messages
160 | */
161 | proto.Magnet2TorrentRequest.serializeBinaryToWriter = function(message, writer) {
162 | var f = undefined;
163 | f = message.getMagnet();
164 | if (f.length > 0) {
165 | writer.writeString(
166 | 1,
167 | f
168 | );
169 | }
170 | };
171 |
172 |
173 | /**
174 | * optional string magnet = 1;
175 | * @return {string}
176 | */
177 | proto.Magnet2TorrentRequest.prototype.getMagnet = function() {
178 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
179 | };
180 |
181 |
182 | /**
183 | * @param {string} value
184 | * @return {!proto.Magnet2TorrentRequest} returns this
185 | */
186 | proto.Magnet2TorrentRequest.prototype.setMagnet = function(value) {
187 | return jspb.Message.setProto3StringField(this, 1, value);
188 | };
189 |
190 |
191 |
192 |
193 |
194 | if (jspb.Message.GENERATE_TO_OBJECT) {
195 | /**
196 | * Creates an object representation of this proto.
197 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
198 | * Optional fields that are not set will be set to undefined.
199 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
200 | * For the list of reserved names please see:
201 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
202 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
203 | * JSPB instance for transitional soy proto support:
204 | * http://goto/soy-param-migration
205 | * @return {!Object}
206 | */
207 | proto.Magnet2TorrentReply.prototype.toObject = function(opt_includeInstance) {
208 | return proto.Magnet2TorrentReply.toObject(opt_includeInstance, this);
209 | };
210 |
211 |
212 | /**
213 | * Static version of the {@see toObject} method.
214 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
215 | * the JSPB instance for transitional soy proto support:
216 | * http://goto/soy-param-migration
217 | * @param {!proto.Magnet2TorrentReply} msg The msg instance to transform.
218 | * @return {!Object}
219 | * @suppress {unusedLocalVariables} f is only used for nested messages
220 | */
221 | proto.Magnet2TorrentReply.toObject = function(includeInstance, msg) {
222 | var f, obj = {
223 | torrent: msg.getTorrent_asB64()
224 | };
225 |
226 | if (includeInstance) {
227 | obj.$jspbMessageInstance = msg;
228 | }
229 | return obj;
230 | };
231 | }
232 |
233 |
234 | /**
235 | * Deserializes binary data (in protobuf wire format).
236 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
237 | * @return {!proto.Magnet2TorrentReply}
238 | */
239 | proto.Magnet2TorrentReply.deserializeBinary = function(bytes) {
240 | var reader = new jspb.BinaryReader(bytes);
241 | var msg = new proto.Magnet2TorrentReply;
242 | return proto.Magnet2TorrentReply.deserializeBinaryFromReader(msg, reader);
243 | };
244 |
245 |
246 | /**
247 | * Deserializes binary data (in protobuf wire format) from the
248 | * given reader into the given message object.
249 | * @param {!proto.Magnet2TorrentReply} msg The message object to deserialize into.
250 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
251 | * @return {!proto.Magnet2TorrentReply}
252 | */
253 | proto.Magnet2TorrentReply.deserializeBinaryFromReader = function(msg, reader) {
254 | while (reader.nextField()) {
255 | if (reader.isEndGroup()) {
256 | break;
257 | }
258 | var field = reader.getFieldNumber();
259 | switch (field) {
260 | case 1:
261 | var value = /** @type {!Uint8Array} */ (reader.readBytes());
262 | msg.setTorrent(value);
263 | break;
264 | default:
265 | reader.skipField();
266 | break;
267 | }
268 | }
269 | return msg;
270 | };
271 |
272 |
273 | /**
274 | * Serializes the message to binary data (in protobuf wire format).
275 | * @return {!Uint8Array}
276 | */
277 | proto.Magnet2TorrentReply.prototype.serializeBinary = function() {
278 | var writer = new jspb.BinaryWriter();
279 | proto.Magnet2TorrentReply.serializeBinaryToWriter(this, writer);
280 | return writer.getResultBuffer();
281 | };
282 |
283 |
284 | /**
285 | * Serializes the given message to binary data (in protobuf wire
286 | * format), writing to the given BinaryWriter.
287 | * @param {!proto.Magnet2TorrentReply} message
288 | * @param {!jspb.BinaryWriter} writer
289 | * @suppress {unusedLocalVariables} f is only used for nested messages
290 | */
291 | proto.Magnet2TorrentReply.serializeBinaryToWriter = function(message, writer) {
292 | var f = undefined;
293 | f = message.getTorrent_asU8();
294 | if (f.length > 0) {
295 | writer.writeBytes(
296 | 1,
297 | f
298 | );
299 | }
300 | };
301 |
302 |
303 | /**
304 | * optional bytes torrent = 1;
305 | * @return {!(string|Uint8Array)}
306 | */
307 | proto.Magnet2TorrentReply.prototype.getTorrent = function() {
308 | return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
309 | };
310 |
311 |
312 | /**
313 | * optional bytes torrent = 1;
314 | * This is a type-conversion wrapper around `getTorrent()`
315 | * @return {string}
316 | */
317 | proto.Magnet2TorrentReply.prototype.getTorrent_asB64 = function() {
318 | return /** @type {string} */ (jspb.Message.bytesAsB64(
319 | this.getTorrent()));
320 | };
321 |
322 |
323 | /**
324 | * optional bytes torrent = 1;
325 | * Note that Uint8Array is not supported on all browsers.
326 | * @see http://caniuse.com/Uint8Array
327 | * This is a type-conversion wrapper around `getTorrent()`
328 | * @return {!Uint8Array}
329 | */
330 | proto.Magnet2TorrentReply.prototype.getTorrent_asU8 = function() {
331 | return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8(
332 | this.getTorrent()));
333 | };
334 |
335 |
336 | /**
337 | * @param {!(string|Uint8Array)} value
338 | * @return {!proto.Magnet2TorrentReply} returns this
339 | */
340 | proto.Magnet2TorrentReply.prototype.setTorrent = function(value) {
341 | return jspb.Message.setProto3BytesField(this, 1, value);
342 | };
343 |
344 |
345 | goog.object.extend(exports, proto);
346 |
--------------------------------------------------------------------------------
/proto/download-progress/download-progress_pb.js:
--------------------------------------------------------------------------------
1 | // source: proto/download-progress/download-progress.proto
2 | /**
3 | * @fileoverview
4 | * @enhanceable
5 | * @suppress {messageConventions} JS Compiler reports an error if a variable or
6 | * field starts with 'MSG_' and isn't a translatable message.
7 | * @public
8 | */
9 | // GENERATED CODE -- DO NOT EDIT!
10 | /* eslint-disable */
11 | // @ts-nocheck
12 |
13 | var jspb = require('google-protobuf');
14 | var goog = jspb;
15 | var proto = {};
16 |
17 | goog.exportSymbol('StatReply', null, proto);
18 | goog.exportSymbol('StatReply.Status', null, proto);
19 | goog.exportSymbol('StatRequest', null, proto);
20 | /**
21 | * Generated by JsPbCodeGenerator.
22 | * @param {Array=} opt_data Optional initial data array, typically from a
23 | * server response, or constructed directly in Javascript. The array is used
24 | * in place and becomes part of the constructed object. It is not cloned.
25 | * If no data is provided, the constructed object will be empty, but still
26 | * valid.
27 | * @extends {jspb.Message}
28 | * @constructor
29 | */
30 | proto.StatRequest = function(opt_data) {
31 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
32 | };
33 | goog.inherits(proto.StatRequest, jspb.Message);
34 | if (goog.DEBUG && !COMPILED) {
35 | /**
36 | * @public
37 | * @override
38 | */
39 | proto.StatRequest.displayName = 'proto.StatRequest';
40 | }
41 | /**
42 | * Generated by JsPbCodeGenerator.
43 | * @param {Array=} opt_data Optional initial data array, typically from a
44 | * server response, or constructed directly in Javascript. The array is used
45 | * in place and becomes part of the constructed object. It is not cloned.
46 | * If no data is provided, the constructed object will be empty, but still
47 | * valid.
48 | * @extends {jspb.Message}
49 | * @constructor
50 | */
51 | proto.StatReply = function(opt_data) {
52 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
53 | };
54 | goog.inherits(proto.StatReply, jspb.Message);
55 | if (goog.DEBUG && !COMPILED) {
56 | /**
57 | * @public
58 | * @override
59 | */
60 | proto.StatReply.displayName = 'proto.StatReply';
61 | }
62 |
63 |
64 |
65 | if (jspb.Message.GENERATE_TO_OBJECT) {
66 | /**
67 | * Creates an object representation of this proto.
68 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
69 | * Optional fields that are not set will be set to undefined.
70 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
71 | * For the list of reserved names please see:
72 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
73 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
74 | * JSPB instance for transitional soy proto support:
75 | * http://goto/soy-param-migration
76 | * @return {!Object}
77 | */
78 | proto.StatRequest.prototype.toObject = function(opt_includeInstance) {
79 | return proto.StatRequest.toObject(opt_includeInstance, this);
80 | };
81 |
82 |
83 | /**
84 | * Static version of the {@see toObject} method.
85 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
86 | * the JSPB instance for transitional soy proto support:
87 | * http://goto/soy-param-migration
88 | * @param {!proto.StatRequest} msg The msg instance to transform.
89 | * @return {!Object}
90 | * @suppress {unusedLocalVariables} f is only used for nested messages
91 | */
92 | proto.StatRequest.toObject = function(includeInstance, msg) {
93 | var f, obj = {
94 |
95 | };
96 |
97 | if (includeInstance) {
98 | obj.$jspbMessageInstance = msg;
99 | }
100 | return obj;
101 | };
102 | }
103 |
104 |
105 | /**
106 | * Deserializes binary data (in protobuf wire format).
107 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
108 | * @return {!proto.StatRequest}
109 | */
110 | proto.StatRequest.deserializeBinary = function(bytes) {
111 | var reader = new jspb.BinaryReader(bytes);
112 | var msg = new proto.StatRequest;
113 | return proto.StatRequest.deserializeBinaryFromReader(msg, reader);
114 | };
115 |
116 |
117 | /**
118 | * Deserializes binary data (in protobuf wire format) from the
119 | * given reader into the given message object.
120 | * @param {!proto.StatRequest} msg The message object to deserialize into.
121 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
122 | * @return {!proto.StatRequest}
123 | */
124 | proto.StatRequest.deserializeBinaryFromReader = function(msg, reader) {
125 | while (reader.nextField()) {
126 | if (reader.isEndGroup()) {
127 | break;
128 | }
129 | var field = reader.getFieldNumber();
130 | switch (field) {
131 | default:
132 | reader.skipField();
133 | break;
134 | }
135 | }
136 | return msg;
137 | };
138 |
139 |
140 | /**
141 | * Serializes the message to binary data (in protobuf wire format).
142 | * @return {!Uint8Array}
143 | */
144 | proto.StatRequest.prototype.serializeBinary = function() {
145 | var writer = new jspb.BinaryWriter();
146 | proto.StatRequest.serializeBinaryToWriter(this, writer);
147 | return writer.getResultBuffer();
148 | };
149 |
150 |
151 | /**
152 | * Serializes the given message to binary data (in protobuf wire
153 | * format), writing to the given BinaryWriter.
154 | * @param {!proto.StatRequest} message
155 | * @param {!jspb.BinaryWriter} writer
156 | * @suppress {unusedLocalVariables} f is only used for nested messages
157 | */
158 | proto.StatRequest.serializeBinaryToWriter = function(message, writer) {
159 | var f = undefined;
160 | };
161 |
162 |
163 |
164 |
165 |
166 | if (jspb.Message.GENERATE_TO_OBJECT) {
167 | /**
168 | * Creates an object representation of this proto.
169 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
170 | * Optional fields that are not set will be set to undefined.
171 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
172 | * For the list of reserved names please see:
173 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
174 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
175 | * JSPB instance for transitional soy proto support:
176 | * http://goto/soy-param-migration
177 | * @return {!Object}
178 | */
179 | proto.StatReply.prototype.toObject = function(opt_includeInstance) {
180 | return proto.StatReply.toObject(opt_includeInstance, this);
181 | };
182 |
183 |
184 | /**
185 | * Static version of the {@see toObject} method.
186 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
187 | * the JSPB instance for transitional soy proto support:
188 | * http://goto/soy-param-migration
189 | * @param {!proto.StatReply} msg The msg instance to transform.
190 | * @return {!Object}
191 | * @suppress {unusedLocalVariables} f is only used for nested messages
192 | */
193 | proto.StatReply.toObject = function(includeInstance, msg) {
194 | var f, obj = {
195 | status: jspb.Message.getFieldWithDefault(msg, 1, 0),
196 | downloaded: jspb.Message.getFieldWithDefault(msg, 2, 0),
197 | rate: jspb.Message.getFieldWithDefault(msg, 3, 0),
198 | length: jspb.Message.getFieldWithDefault(msg, 4, 0)
199 | };
200 |
201 | if (includeInstance) {
202 | obj.$jspbMessageInstance = msg;
203 | }
204 | return obj;
205 | };
206 | }
207 |
208 |
209 | /**
210 | * Deserializes binary data (in protobuf wire format).
211 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
212 | * @return {!proto.StatReply}
213 | */
214 | proto.StatReply.deserializeBinary = function(bytes) {
215 | var reader = new jspb.BinaryReader(bytes);
216 | var msg = new proto.StatReply;
217 | return proto.StatReply.deserializeBinaryFromReader(msg, reader);
218 | };
219 |
220 |
221 | /**
222 | * Deserializes binary data (in protobuf wire format) from the
223 | * given reader into the given message object.
224 | * @param {!proto.StatReply} msg The message object to deserialize into.
225 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
226 | * @return {!proto.StatReply}
227 | */
228 | proto.StatReply.deserializeBinaryFromReader = function(msg, reader) {
229 | while (reader.nextField()) {
230 | if (reader.isEndGroup()) {
231 | break;
232 | }
233 | var field = reader.getFieldNumber();
234 | switch (field) {
235 | case 1:
236 | var value = /** @type {!proto.StatReply.Status} */ (reader.readEnum());
237 | msg.setStatus(value);
238 | break;
239 | case 2:
240 | var value = /** @type {number} */ (reader.readInt64());
241 | msg.setDownloaded(value);
242 | break;
243 | case 3:
244 | var value = /** @type {number} */ (reader.readInt64());
245 | msg.setRate(value);
246 | break;
247 | case 4:
248 | var value = /** @type {number} */ (reader.readInt64());
249 | msg.setLength(value);
250 | break;
251 | default:
252 | reader.skipField();
253 | break;
254 | }
255 | }
256 | return msg;
257 | };
258 |
259 |
260 | /**
261 | * Serializes the message to binary data (in protobuf wire format).
262 | * @return {!Uint8Array}
263 | */
264 | proto.StatReply.prototype.serializeBinary = function() {
265 | var writer = new jspb.BinaryWriter();
266 | proto.StatReply.serializeBinaryToWriter(this, writer);
267 | return writer.getResultBuffer();
268 | };
269 |
270 |
271 | /**
272 | * Serializes the given message to binary data (in protobuf wire
273 | * format), writing to the given BinaryWriter.
274 | * @param {!proto.StatReply} message
275 | * @param {!jspb.BinaryWriter} writer
276 | * @suppress {unusedLocalVariables} f is only used for nested messages
277 | */
278 | proto.StatReply.serializeBinaryToWriter = function(message, writer) {
279 | var f = undefined;
280 | f = message.getStatus();
281 | if (f !== 0.0) {
282 | writer.writeEnum(
283 | 1,
284 | f
285 | );
286 | }
287 | f = message.getDownloaded();
288 | if (f !== 0) {
289 | writer.writeInt64(
290 | 2,
291 | f
292 | );
293 | }
294 | f = message.getRate();
295 | if (f !== 0) {
296 | writer.writeInt64(
297 | 3,
298 | f
299 | );
300 | }
301 | f = message.getLength();
302 | if (f !== 0) {
303 | writer.writeInt64(
304 | 4,
305 | f
306 | );
307 | }
308 | };
309 |
310 |
311 | /**
312 | * @enum {number}
313 | */
314 | proto.StatReply.Status = {
315 | NOT_STARTED: 0,
316 | PENDING: 1,
317 | ACTIVE: 2,
318 | DONE: 3,
319 | FAILED: 4
320 | };
321 |
322 | /**
323 | * optional Status status = 1;
324 | * @return {!proto.StatReply.Status}
325 | */
326 | proto.StatReply.prototype.getStatus = function() {
327 | return /** @type {!proto.StatReply.Status} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
328 | };
329 |
330 |
331 | /**
332 | * @param {!proto.StatReply.Status} value
333 | * @return {!proto.StatReply} returns this
334 | */
335 | proto.StatReply.prototype.setStatus = function(value) {
336 | return jspb.Message.setProto3EnumField(this, 1, value);
337 | };
338 |
339 |
340 | /**
341 | * optional int64 downloaded = 2;
342 | * @return {number}
343 | */
344 | proto.StatReply.prototype.getDownloaded = function() {
345 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
346 | };
347 |
348 |
349 | /**
350 | * @param {number} value
351 | * @return {!proto.StatReply} returns this
352 | */
353 | proto.StatReply.prototype.setDownloaded = function(value) {
354 | return jspb.Message.setProto3IntField(this, 2, value);
355 | };
356 |
357 |
358 | /**
359 | * optional int64 rate = 3;
360 | * @return {number}
361 | */
362 | proto.StatReply.prototype.getRate = function() {
363 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));
364 | };
365 |
366 |
367 | /**
368 | * @param {number} value
369 | * @return {!proto.StatReply} returns this
370 | */
371 | proto.StatReply.prototype.setRate = function(value) {
372 | return jspb.Message.setProto3IntField(this, 3, value);
373 | };
374 |
375 |
376 | /**
377 | * optional int64 length = 4;
378 | * @return {number}
379 | */
380 | proto.StatReply.prototype.getLength = function() {
381 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));
382 | };
383 |
384 |
385 | /**
386 | * @param {number} value
387 | * @return {!proto.StatReply} returns this
388 | */
389 | proto.StatReply.prototype.setLength = function(value) {
390 | return jspb.Message.setProto3IntField(this, 4, value);
391 | };
392 |
393 |
394 | goog.object.extend(exports, proto);
395 |
--------------------------------------------------------------------------------
/src/sdk/util.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const Url = require('url-parse');
3 | import ISO6391 from 'iso-639-1';
4 | import mime from 'mime';
5 | var md5 = require('md5');
6 | const debug = require('debug')('webtor:sdk:util');
7 | import bind from 'lodash/bind';
8 | import throttle from 'lodash/throttle';
9 | const debugFetch = function(url) {
10 | debug('fetch url=%o', url.href);
11 | return fetch(url);
12 | }
13 | const retryFetch = require('fetch-retry')(debugFetch, {
14 | retries: 3,
15 | retryDelay: function(attempt, error, response) {
16 | return Math.pow(2, attempt) * 1000;
17 | },
18 | retryOn: function(attempt, error, response) {
19 | if (error !== null || response.status >= 500) {
20 | debug('got fetch error retry count=%o', attempt);
21 | return true;
22 | }
23 | },
24 | });
25 |
26 | function cleanExt(ext) {
27 | return ext.toLowerCase().replace(/~[a-z0-9]+$/, '');
28 | }
29 | function cleanPath(p) {
30 | return p.replace(/\/\//, '/');
31 | }
32 | function buf2hex(buffer) { // buffer is an ArrayBuffer
33 | return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
34 | }
35 |
36 | export default function(params, sdk) {
37 | const self = {params, sdk};
38 | const throttledFuncs = {};
39 | const util = {
40 | async makeQuery(metadata = {}, params = {}) {
41 | params = Object.assign({}, self.params, params);
42 | metadata = Object.assign({}, metadata);
43 | const query = metadata;
44 | const token = await params.getToken();
45 | if (token) query.token = token;
46 | if (params.apiKey) query["api-key"] = params.apiKey;
47 | return query;
48 | },
49 | getDeliveryType(file) {
50 | if (!file) return;
51 | let ext = path.extname(file);
52 | ext = cleanExt(ext);
53 | // Browser unsupported streaming formats
54 | if ('.avi .mkv .flac .m4a .m4v .ts .vob'.split(' ').includes(ext)) return 'transcode';
55 | // Browser supported streaming formats
56 | if ('.mp4 .mp3 .wav .ogg .webm'.split(' ').includes(ext)) return 'webseed';
57 | // Browser supported image formats
58 | if ('.png .gif .jpg .jpeg'.split(' ').includes(ext)) return 'webseed';
59 | // Browser unsupported subtitle formats
60 | if ('.vtt .srt'.split(' ').includes(ext)) return 'webseed';
61 | },
62 | getMediaType(file) {
63 | if (!file) return;
64 | let ext = path.extname(file);
65 | ext = cleanExt(ext);
66 | // Video
67 | if ('.avi .mkv .mp4 .webm .m4v .ts .vob'.split(' ').includes(ext)) return 'video';
68 | // Audio
69 | if ('.mp3 .wav .ogg .flac .m4a'.split(' ').includes(ext)) return 'audio';
70 | // Images
71 | if ('.png .gif .jpg .jpeg'.split(' ').includes(ext)) return 'image';
72 | // Subtitles
73 | if ('.srt .vtt'.split(' ').includes(ext)) return 'subtitle';
74 | },
75 | getMimeType(file) {
76 | if (typeof file == 'object') {
77 | file = file.pathname;
78 | }
79 | const ext = path.extname(file);
80 | return mime.getType(ext);
81 | },
82 | getSubtitleSrcLang(name) {
83 | const baseName = path.basename(name, path.extname(name));
84 | for (const code of ISO6391.getAllCodes()) {
85 | if (baseName.endsWith('.' + code)) return code;
86 | }
87 | return false;
88 | },
89 | getSubtitleLang(name) {
90 | const code = this.getSubtitleSrcLang(name);
91 | if (code == false) return false;
92 | return this.getLang(code);
93 | },
94 | getLang(code) {
95 | return {
96 | code,
97 | name: ISO6391.getName(code),
98 | nativeName: ISO6391.getNativeName(code),
99 | };
100 | },
101 | cloneUrl(url) {
102 | return Object.assign(new Url(), url);
103 | },
104 | vttUrl(url) {
105 | url = this.cloneUrl(url);
106 | url.set('pathname', cleanPath(url.pathname + '~vtt/' + encodeURIComponent(path.basename(url.pathname).replace(/srt$/, 'vtt'))));
107 | return url;
108 | },
109 | primaryUrl(url) {
110 | if (!url) return url;
111 | url = this.cloneUrl(url);
112 | if (url.primaryHost) {
113 | url.host = url.primaryHost;
114 | }
115 | return url;
116 | },
117 | completedPiecesUrl(url) {
118 | url = this.cloneUrl(url);
119 | url = this.tcUrl(url);
120 | url.set('pathname', cleanPath(url.pathname.replace(/~tc.*$/, '~tc/completed_pieces')));
121 | return url;
122 | },
123 | transcodeDoneMarkerUrl(url) {
124 | url = this.cloneUrl(url);
125 | url = this.primaryUrl(url);
126 | url.set('pathname', cleanPath(url.pathname + '~trc/done'));
127 | return url;
128 | },
129 | multibitrateDoneMarkerUrl(url) {
130 | url = this.cloneUrl(url);
131 | url = this.primaryUrl(url);
132 | url.set('pathname', cleanPath(url.pathname + '~mtrc/done'));
133 | return url;
134 | },
135 | transcodeIndexUrl(url) {
136 | url = this.cloneUrl(url);
137 | url.set('pathname', cleanPath(url.pathname + '~trc/index.m3u8'));
138 | return url;
139 | },
140 | multibitrateIndexUrl(url) {
141 | url = this.cloneUrl(url);
142 | url.set('pathname', cleanPath(url.pathname + '~mtrc/index.m3u8'));
143 | return url;
144 | },
145 | pieceUrl(url, id) {
146 | url = this.cloneUrl(url);
147 | url.set('pathname', cleanPath(url.pathname + '/piece/' + id));
148 | return url;
149 | },
150 | tcUrl(url) {
151 | url = this.cloneUrl(url);
152 | if (url.pathname.includes('~tc')) return url;
153 | url.set('pathname', cleanPath(url.pathname + '~tc/' + encodeURIComponent(path.basename(url.path))));
154 | return url;
155 | },
156 | hlsUrl(url, file) {
157 | url = this.cloneUrl(url);
158 | url.set('pathname', cleanPath(url.pathname + '~hls/' + file));
159 | return url;
160 | },
161 | trcUrl(url, file) {
162 | url = this.cloneUrl(url);
163 | url.set('pathname', cleanPath(url.pathname + '~trc/' + file));
164 | return url;
165 | },
166 | mtrcUrl(url, file) {
167 | url = this.cloneUrl(url);
168 | url.set('pathname', cleanPath(url.pathname + '~mtrc/' + file));
169 | return url;
170 | },
171 | vodUrl(url, file) {
172 | url = this.cloneUrl(url);
173 | url.set('pathname', cleanPath(url.pathname + '~vod/hls/' + md5(cleanPath(url.pathname)) + '/' + file));
174 | return url;
175 | },
176 | viUrl(url, path) {
177 | url = this.cloneUrl(url);
178 | url.set('pathname', cleanPath(url.pathname + '~vi' + path));
179 | return url;
180 | },
181 | dpUrl(url, file) {
182 | url = this.cloneUrl(url);
183 | url.set('pathname', cleanPath(url.pathname + '~dp/' + file));
184 | return url;
185 | },
186 | dpStatUrl(url) {
187 | url = this.cloneUrl(url);
188 | url.set('pathname', '/dp');
189 | url.set('query', '');
190 | return url;
191 | },
192 | async baseStreamUrl(url, file, metadata, params, context) {
193 | url = this.cloneUrl(url);
194 | const deliveryType = this.getDeliveryType(url.pathname);
195 | if (params.vod && cleanExt(path.extname(url.pathname)) == '.mp4') {
196 | if (params.multibitrate) {
197 | const done = await this.throttledMultibitrateDoneMarker(url, metadata, params);
198 | if (done) {
199 | url.multibitrate = true;
200 | url.cached = true;
201 | return this.mtrcUrl(url, file);
202 | }
203 | }
204 | return this.vodUrl(url, file);
205 | } else if (cleanExt(path.extname(url.pathname)) == '.srt') {
206 | return this.vttUrl(url);
207 | } else if (deliveryType == 'transcode') {
208 | if (params.multibitrate) {
209 | const done = await this.throttledMultibitrateDoneMarker(url, metadata, params);
210 | if (done) {
211 | url.multibitrate = true;
212 | url.cached = true;
213 | return this.mtrcUrl(url, file);
214 | }
215 | }
216 | if (params.cache) {
217 | const done = await this.throttledTranscodeDoneMarker(url, metadata, params);
218 | if (done) {
219 | url.cached = true;
220 | return this.trcUrl(url, file);
221 | }
222 | }
223 | return this.hlsUrl(url, file);
224 | }
225 | return url;
226 | },
227 | async streamUrl(url, metadata, params, context) {
228 | return this.baseStreamUrl(url, 'index.m3u8', metadata, params, context);
229 | },
230 | async segmentUrl(url, segment, metadata, params, context) {
231 | return this.baseStreamUrl(url, segment, metadata, params, context);
232 | },
233 | async error(url, metadata, params) {
234 | url = this.cloneUrl(url);
235 | const deliveryType = this.getDeliveryType(url.pathname);
236 | const mediaType = this.getMediaType(url.pathname);
237 | if (deliveryType == 'webseed' || mediaType == 'subtitle') return;
238 | if (params.cache) {
239 | const done = await this.throttledTranscodeDoneMarker(url, metadata, params);
240 | if (done) {
241 | return;
242 | } else {
243 | url = this.hlsUrl(url, 'error.log');
244 | }
245 | } else {
246 | url = this.hlsUrl(url, 'error.log');
247 | }
248 | const res = await fetch(url);
249 | const err = await res.text();
250 | return err;
251 | },
252 | async transcodeDoneMarker(url) {
253 | url = this.cloneUrl(url);
254 | url = this.transcodeDoneMarkerUrl(url);
255 | const res = await(retryFetch(url));
256 | return res.status == 200;
257 | },
258 | async multibitrateDoneMarker(url) {
259 | url = this.cloneUrl(url);
260 | url = this.multibitrateDoneMarkerUrl(url);
261 | const res = await(retryFetch(url));
262 | return res.status == 200;
263 | },
264 |
265 | async transcodeIndexExists(url) {
266 | url = this.cloneUrl(url);
267 | url = this.transcodeIndexUrl(url);
268 | const res = await(retryFetch(url));
269 | return res.status == 200;
270 | },
271 |
272 | async multibitrateIndexExists(url) {
273 | url = this.cloneUrl(url);
274 | url = this.multibitrateIndexUrl(url);
275 | const res = await(retryFetch(url));
276 | return res.status == 200;
277 | },
278 |
279 | async completedPieces(url) {
280 | url = this.cloneUrl(url);
281 | url = this.completedPiecesUrl(url);
282 | const res = await(retryFetch(url));
283 | const buf = await res.arrayBuffer();
284 | const byteArr = new Uint8Array(buf);
285 | const hex = buf2hex(byteArr);
286 | const pieces = [];
287 | let p = '';
288 | for (const c of hex) {
289 | p += c;
290 | if (p.length == 40) {
291 | pieces.push(p);
292 | p = '';
293 | }
294 | }
295 | return pieces;
296 | },
297 |
298 | async mediaInfo(url, metadata = {}, params = {}) {
299 | url = this.cloneUrl(url);
300 | const deliveryType = this.getDeliveryType(url.pathname);
301 | const mediaType = this.getMediaType(url.pathname);
302 | if (deliveryType == 'webseed' || mediaType == 'subtitle') return {};
303 | if (params.cache) {
304 | const done = await this.throttledTranscodeDoneMarker(url, metadata, params);
305 | if (done) {
306 | url = this.trcUrl(url, 'index.json');
307 | } else {
308 | url = this.hlsUrl(url, 'index.json');
309 | }
310 | } else {
311 | url = this.hlsUrl(url, 'index.json');
312 | }
313 | const res = await(retryFetch(url));
314 | const mediaInfo = await res.json();
315 | return mediaInfo;
316 | },
317 | async openSubtitles(url) {
318 | url = this.cloneUrl(url);
319 | const mediaType = this.getMediaType(url.pathname);
320 | if (mediaType != 'video') return {};
321 | const subtitlesUrl = this.viUrl(url, '/subtitles.json');
322 | const res = await(retryFetch(subtitlesUrl));
323 | const data = await res.json();
324 |
325 | for (const k in data) {
326 | const format = data[k].format;
327 | if (format != 'srt' && format != 'vtt') continue;
328 | let src = data[k].src;
329 | let sUrl = this.viUrl(url, src);
330 | if (format != 'vtt') {
331 | sUrl = this.vttUrl(sUrl);
332 | }
333 | data[k].src = sUrl
334 | }
335 | return data;
336 | },
337 | async subdomainsUrl(metadata = {}, params = {}) {
338 | params = Object.assign({}, self.params, params);
339 | const url = new Url(params.apiUrl);
340 | const pathname = '/subdomains.json';
341 | url.set('pathname', pathname);
342 | const query = await self.sdk.util.makeQuery(metadata, params);
343 | url.set('query', query);
344 | return url;
345 | },
346 | async subdomains(u, path, metadata = {}, params = {}) {
347 | params = Object.assign({}, self.params, params);
348 | const url = await this.subdomainsUrl(metadata, params);
349 | const res = await(retryFetch(url));
350 | const s = await res.json();
351 | const rr = [];
352 | for (const e of s) {
353 | rr.push(e);
354 | }
355 | return rr;
356 | },
357 | isCDNAllowed(path, params = {}) {
358 | params = Object.assign({}, self.params, params);
359 | for (const a of params.cdnPathSuffixes) {
360 | if (cleanExt(path).endsWith(a)) return true;
361 | }
362 | return false;
363 | },
364 | cdnUrl(url, metadata = {}, params = {}) {
365 | url = this.cloneUrl(url);
366 | params = Object.assign({}, self.params, params);
367 | if (params.cdn && params.cdnUrl && this.isCDNAllowed(url.pathname, params)) {
368 | let cdnUrl = new Url(params.cdnUrl);
369 | url.set('hostname', cdnUrl.hostname);
370 | url.set('protocol', cdnUrl.protocol);
371 | url.set('query', '?api-key=' + params.apiKey);
372 | return url;
373 | }
374 | return false;
375 | },
376 | async throttled(func, interval, url, file, metadata, params, k) {
377 | let key = url.infoHash + file + func.name;
378 | if (k) key += k;
379 | if (!throttledFuncs[key]) {
380 | throttledFuncs[key] = throttle(bind(func, this, url, file, metadata, params), interval, {
381 | trailing: false,
382 | });
383 | }
384 | const tf = throttledFuncs[key];
385 | return await tf();
386 | },
387 | async cacheUrl(url, metadata, params) {
388 | const completedPieces = await this.throttledCompletedPieces(url, metadata, params);
389 | if (completedPieces.length > 0) {
390 | return this.tcUrl(url);
391 | }
392 | return url;
393 |
394 | },
395 | async throttledCompletedPieces(url, metadata = {}, params = {}) {
396 | let completedPieces = [];
397 | if (params.cache) {
398 | completedPieces = await this.throttled(this.completedPieces, 10*60*1000, url, null, metadata, params);
399 | }
400 | return completedPieces;
401 | },
402 | async throttledTranscodeIndexExists(url, metadata = {}, params = {}) {
403 | let done = false;
404 | if (params.cache) {
405 | done = await this.throttled(this.transcodeIndexExists, 10*60*1000, url, url.path, metadata, params);
406 | }
407 | return done;
408 | },
409 | async throttledTranscodeDoneMarker(url, metadata = {}, params = {}) {
410 | let done = false;
411 | if (params.cache) {
412 | done = await this.throttled(this.transcodeDoneMarker, 10*60*1000, url, url.path, metadata, params);
413 | }
414 | return done;
415 | },
416 | async throttledMultibitrateDoneMarker(url, metadata = {}, params = {}) {
417 | let done = false;
418 | if (params.cache) {
419 | done = await this.throttled(this.multibitrateDoneMarker, 10*60*1000, url, url.path, metadata, params);
420 | }
421 | return done;
422 | },
423 | async throttledMultibitrateIndexExists(url, metadata = {}, params = {}) {
424 | let done = false;
425 | if (params.cache) {
426 | done = await this.throttled(this.multibitrateIndexExists, 10*60*1000, url, url.path, metadata, params);
427 | }
428 | return done;
429 | },
430 | async isCached(url, metadata = {}, params = {}) {
431 | const deliveryType = this.getDeliveryType(url.pathname);
432 | const mediaType = this.getMediaType(url.pathname);
433 | if (mediaType == 'video') {
434 | if (await this.throttledMultibitrateDoneMarker(url, metadata, params)) return true;
435 | }
436 | if (deliveryType == 'transcode') {
437 | if (await this.throttledTranscodeDoneMarker(url, metadata, params)) return true;
438 | }
439 | if (deliveryType == 'webseed') {
440 | const completedPieces = await this.throttledCompletedPieces(url, metadata, params);
441 | return completedPieces.length > 0;
442 | }
443 | return false;
444 | },
445 | async subdomainUrl(url, context = {}, metadata = {}, params = {}) {
446 | url = this.cloneUrl(url);
447 | params = Object.assign({}, self.params, params);
448 | if (!params.subdomains) {
449 | return url;
450 | }
451 | try {
452 | // const cached = await this.isCached(url, metadata, params);
453 | const subdomains = await this.throttled(this.subdomains, 30*1000, url, null, metadata, params, metadata.pool);
454 | if (!context.usedSubdomains) context.usedSubdomains = [];
455 | let sub = subdomains.filter(e => !context.usedSubdomains.includes(e));
456 | if (sub.length == 0 && subdomains.length > 0) {
457 | sub = [subdomains[0]];
458 | context.usedSubdomains = [];
459 | }
460 | if (sub.length !== 0) {
461 | const s = sub[0];
462 | url.set('hostname', s + '.' + url.hostname);
463 | context.usedSubdomains.push(s);
464 | }
465 | } catch (e) {
466 | debug(e);
467 | console.log(e);
468 | return false;
469 | }
470 | return url;
471 | }
472 | };
473 | return util;
474 | }
--------------------------------------------------------------------------------
/proto/url-store/url-store_pb.js:
--------------------------------------------------------------------------------
1 | // source: proto/url-store/url-store.proto
2 | /**
3 | * @fileoverview
4 | * @enhanceable
5 | * @suppress {messageConventions} JS Compiler reports an error if a variable or
6 | * field starts with 'MSG_' and isn't a translatable message.
7 | * @public
8 | */
9 | // GENERATED CODE -- DO NOT EDIT!
10 | /* eslint-disable */
11 | // @ts-nocheck
12 |
13 | var jspb = require('google-protobuf');
14 | var goog = jspb;
15 | var proto = {};
16 |
17 | goog.exportSymbol('webtor.url_store.CheckReply', null, proto);
18 | goog.exportSymbol('webtor.url_store.CheckRequest', null, proto);
19 | goog.exportSymbol('webtor.url_store.PushReply', null, proto);
20 | goog.exportSymbol('webtor.url_store.PushRequest', null, proto);
21 | /**
22 | * Generated by JsPbCodeGenerator.
23 | * @param {Array=} opt_data Optional initial data array, typically from a
24 | * server response, or constructed directly in Javascript. The array is used
25 | * in place and becomes part of the constructed object. It is not cloned.
26 | * If no data is provided, the constructed object will be empty, but still
27 | * valid.
28 | * @extends {jspb.Message}
29 | * @constructor
30 | */
31 | proto.webtor.url_store.PushReply = function(opt_data) {
32 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
33 | };
34 | goog.inherits(proto.webtor.url_store.PushReply, jspb.Message);
35 | if (goog.DEBUG && !COMPILED) {
36 | /**
37 | * @public
38 | * @override
39 | */
40 | proto.webtor.url_store.PushReply.displayName = 'proto.webtor.url_store.PushReply';
41 | }
42 | /**
43 | * Generated by JsPbCodeGenerator.
44 | * @param {Array=} opt_data Optional initial data array, typically from a
45 | * server response, or constructed directly in Javascript. The array is used
46 | * in place and becomes part of the constructed object. It is not cloned.
47 | * If no data is provided, the constructed object will be empty, but still
48 | * valid.
49 | * @extends {jspb.Message}
50 | * @constructor
51 | */
52 | proto.webtor.url_store.PushRequest = function(opt_data) {
53 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
54 | };
55 | goog.inherits(proto.webtor.url_store.PushRequest, jspb.Message);
56 | if (goog.DEBUG && !COMPILED) {
57 | /**
58 | * @public
59 | * @override
60 | */
61 | proto.webtor.url_store.PushRequest.displayName = 'proto.webtor.url_store.PushRequest';
62 | }
63 | /**
64 | * Generated by JsPbCodeGenerator.
65 | * @param {Array=} opt_data Optional initial data array, typically from a
66 | * server response, or constructed directly in Javascript. The array is used
67 | * in place and becomes part of the constructed object. It is not cloned.
68 | * If no data is provided, the constructed object will be empty, but still
69 | * valid.
70 | * @extends {jspb.Message}
71 | * @constructor
72 | */
73 | proto.webtor.url_store.CheckRequest = function(opt_data) {
74 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
75 | };
76 | goog.inherits(proto.webtor.url_store.CheckRequest, jspb.Message);
77 | if (goog.DEBUG && !COMPILED) {
78 | /**
79 | * @public
80 | * @override
81 | */
82 | proto.webtor.url_store.CheckRequest.displayName = 'proto.webtor.url_store.CheckRequest';
83 | }
84 | /**
85 | * Generated by JsPbCodeGenerator.
86 | * @param {Array=} opt_data Optional initial data array, typically from a
87 | * server response, or constructed directly in Javascript. The array is used
88 | * in place and becomes part of the constructed object. It is not cloned.
89 | * If no data is provided, the constructed object will be empty, but still
90 | * valid.
91 | * @extends {jspb.Message}
92 | * @constructor
93 | */
94 | proto.webtor.url_store.CheckReply = function(opt_data) {
95 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
96 | };
97 | goog.inherits(proto.webtor.url_store.CheckReply, jspb.Message);
98 | if (goog.DEBUG && !COMPILED) {
99 | /**
100 | * @public
101 | * @override
102 | */
103 | proto.webtor.url_store.CheckReply.displayName = 'proto.webtor.url_store.CheckReply';
104 | }
105 |
106 |
107 |
108 | if (jspb.Message.GENERATE_TO_OBJECT) {
109 | /**
110 | * Creates an object representation of this proto.
111 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
112 | * Optional fields that are not set will be set to undefined.
113 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
114 | * For the list of reserved names please see:
115 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
116 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
117 | * JSPB instance for transitional soy proto support:
118 | * http://goto/soy-param-migration
119 | * @return {!Object}
120 | */
121 | proto.webtor.url_store.PushReply.prototype.toObject = function(opt_includeInstance) {
122 | return proto.webtor.url_store.PushReply.toObject(opt_includeInstance, this);
123 | };
124 |
125 |
126 | /**
127 | * Static version of the {@see toObject} method.
128 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
129 | * the JSPB instance for transitional soy proto support:
130 | * http://goto/soy-param-migration
131 | * @param {!proto.webtor.url_store.PushReply} msg The msg instance to transform.
132 | * @return {!Object}
133 | * @suppress {unusedLocalVariables} f is only used for nested messages
134 | */
135 | proto.webtor.url_store.PushReply.toObject = function(includeInstance, msg) {
136 | var f, obj = {
137 | hash: jspb.Message.getFieldWithDefault(msg, 1, "")
138 | };
139 |
140 | if (includeInstance) {
141 | obj.$jspbMessageInstance = msg;
142 | }
143 | return obj;
144 | };
145 | }
146 |
147 |
148 | /**
149 | * Deserializes binary data (in protobuf wire format).
150 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
151 | * @return {!proto.webtor.url_store.PushReply}
152 | */
153 | proto.webtor.url_store.PushReply.deserializeBinary = function(bytes) {
154 | var reader = new jspb.BinaryReader(bytes);
155 | var msg = new proto.webtor.url_store.PushReply;
156 | return proto.webtor.url_store.PushReply.deserializeBinaryFromReader(msg, reader);
157 | };
158 |
159 |
160 | /**
161 | * Deserializes binary data (in protobuf wire format) from the
162 | * given reader into the given message object.
163 | * @param {!proto.webtor.url_store.PushReply} msg The message object to deserialize into.
164 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
165 | * @return {!proto.webtor.url_store.PushReply}
166 | */
167 | proto.webtor.url_store.PushReply.deserializeBinaryFromReader = function(msg, reader) {
168 | while (reader.nextField()) {
169 | if (reader.isEndGroup()) {
170 | break;
171 | }
172 | var field = reader.getFieldNumber();
173 | switch (field) {
174 | case 1:
175 | var value = /** @type {string} */ (reader.readString());
176 | msg.setHash(value);
177 | break;
178 | default:
179 | reader.skipField();
180 | break;
181 | }
182 | }
183 | return msg;
184 | };
185 |
186 |
187 | /**
188 | * Serializes the message to binary data (in protobuf wire format).
189 | * @return {!Uint8Array}
190 | */
191 | proto.webtor.url_store.PushReply.prototype.serializeBinary = function() {
192 | var writer = new jspb.BinaryWriter();
193 | proto.webtor.url_store.PushReply.serializeBinaryToWriter(this, writer);
194 | return writer.getResultBuffer();
195 | };
196 |
197 |
198 | /**
199 | * Serializes the given message to binary data (in protobuf wire
200 | * format), writing to the given BinaryWriter.
201 | * @param {!proto.webtor.url_store.PushReply} message
202 | * @param {!jspb.BinaryWriter} writer
203 | * @suppress {unusedLocalVariables} f is only used for nested messages
204 | */
205 | proto.webtor.url_store.PushReply.serializeBinaryToWriter = function(message, writer) {
206 | var f = undefined;
207 | f = message.getHash();
208 | if (f.length > 0) {
209 | writer.writeString(
210 | 1,
211 | f
212 | );
213 | }
214 | };
215 |
216 |
217 | /**
218 | * optional string hash = 1;
219 | * @return {string}
220 | */
221 | proto.webtor.url_store.PushReply.prototype.getHash = function() {
222 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
223 | };
224 |
225 |
226 | /**
227 | * @param {string} value
228 | * @return {!proto.webtor.url_store.PushReply} returns this
229 | */
230 | proto.webtor.url_store.PushReply.prototype.setHash = function(value) {
231 | return jspb.Message.setProto3StringField(this, 1, value);
232 | };
233 |
234 |
235 |
236 |
237 |
238 | if (jspb.Message.GENERATE_TO_OBJECT) {
239 | /**
240 | * Creates an object representation of this proto.
241 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
242 | * Optional fields that are not set will be set to undefined.
243 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
244 | * For the list of reserved names please see:
245 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
246 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
247 | * JSPB instance for transitional soy proto support:
248 | * http://goto/soy-param-migration
249 | * @return {!Object}
250 | */
251 | proto.webtor.url_store.PushRequest.prototype.toObject = function(opt_includeInstance) {
252 | return proto.webtor.url_store.PushRequest.toObject(opt_includeInstance, this);
253 | };
254 |
255 |
256 | /**
257 | * Static version of the {@see toObject} method.
258 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
259 | * the JSPB instance for transitional soy proto support:
260 | * http://goto/soy-param-migration
261 | * @param {!proto.webtor.url_store.PushRequest} msg The msg instance to transform.
262 | * @return {!Object}
263 | * @suppress {unusedLocalVariables} f is only used for nested messages
264 | */
265 | proto.webtor.url_store.PushRequest.toObject = function(includeInstance, msg) {
266 | var f, obj = {
267 | url: jspb.Message.getFieldWithDefault(msg, 1, "")
268 | };
269 |
270 | if (includeInstance) {
271 | obj.$jspbMessageInstance = msg;
272 | }
273 | return obj;
274 | };
275 | }
276 |
277 |
278 | /**
279 | * Deserializes binary data (in protobuf wire format).
280 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
281 | * @return {!proto.webtor.url_store.PushRequest}
282 | */
283 | proto.webtor.url_store.PushRequest.deserializeBinary = function(bytes) {
284 | var reader = new jspb.BinaryReader(bytes);
285 | var msg = new proto.webtor.url_store.PushRequest;
286 | return proto.webtor.url_store.PushRequest.deserializeBinaryFromReader(msg, reader);
287 | };
288 |
289 |
290 | /**
291 | * Deserializes binary data (in protobuf wire format) from the
292 | * given reader into the given message object.
293 | * @param {!proto.webtor.url_store.PushRequest} msg The message object to deserialize into.
294 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
295 | * @return {!proto.webtor.url_store.PushRequest}
296 | */
297 | proto.webtor.url_store.PushRequest.deserializeBinaryFromReader = function(msg, reader) {
298 | while (reader.nextField()) {
299 | if (reader.isEndGroup()) {
300 | break;
301 | }
302 | var field = reader.getFieldNumber();
303 | switch (field) {
304 | case 1:
305 | var value = /** @type {string} */ (reader.readString());
306 | msg.setUrl(value);
307 | break;
308 | default:
309 | reader.skipField();
310 | break;
311 | }
312 | }
313 | return msg;
314 | };
315 |
316 |
317 | /**
318 | * Serializes the message to binary data (in protobuf wire format).
319 | * @return {!Uint8Array}
320 | */
321 | proto.webtor.url_store.PushRequest.prototype.serializeBinary = function() {
322 | var writer = new jspb.BinaryWriter();
323 | proto.webtor.url_store.PushRequest.serializeBinaryToWriter(this, writer);
324 | return writer.getResultBuffer();
325 | };
326 |
327 |
328 | /**
329 | * Serializes the given message to binary data (in protobuf wire
330 | * format), writing to the given BinaryWriter.
331 | * @param {!proto.webtor.url_store.PushRequest} message
332 | * @param {!jspb.BinaryWriter} writer
333 | * @suppress {unusedLocalVariables} f is only used for nested messages
334 | */
335 | proto.webtor.url_store.PushRequest.serializeBinaryToWriter = function(message, writer) {
336 | var f = undefined;
337 | f = message.getUrl();
338 | if (f.length > 0) {
339 | writer.writeString(
340 | 1,
341 | f
342 | );
343 | }
344 | };
345 |
346 |
347 | /**
348 | * optional string url = 1;
349 | * @return {string}
350 | */
351 | proto.webtor.url_store.PushRequest.prototype.getUrl = function() {
352 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
353 | };
354 |
355 |
356 | /**
357 | * @param {string} value
358 | * @return {!proto.webtor.url_store.PushRequest} returns this
359 | */
360 | proto.webtor.url_store.PushRequest.prototype.setUrl = function(value) {
361 | return jspb.Message.setProto3StringField(this, 1, value);
362 | };
363 |
364 |
365 |
366 |
367 |
368 | if (jspb.Message.GENERATE_TO_OBJECT) {
369 | /**
370 | * Creates an object representation of this proto.
371 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
372 | * Optional fields that are not set will be set to undefined.
373 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
374 | * For the list of reserved names please see:
375 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
376 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
377 | * JSPB instance for transitional soy proto support:
378 | * http://goto/soy-param-migration
379 | * @return {!Object}
380 | */
381 | proto.webtor.url_store.CheckRequest.prototype.toObject = function(opt_includeInstance) {
382 | return proto.webtor.url_store.CheckRequest.toObject(opt_includeInstance, this);
383 | };
384 |
385 |
386 | /**
387 | * Static version of the {@see toObject} method.
388 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
389 | * the JSPB instance for transitional soy proto support:
390 | * http://goto/soy-param-migration
391 | * @param {!proto.webtor.url_store.CheckRequest} msg The msg instance to transform.
392 | * @return {!Object}
393 | * @suppress {unusedLocalVariables} f is only used for nested messages
394 | */
395 | proto.webtor.url_store.CheckRequest.toObject = function(includeInstance, msg) {
396 | var f, obj = {
397 | hash: jspb.Message.getFieldWithDefault(msg, 1, "")
398 | };
399 |
400 | if (includeInstance) {
401 | obj.$jspbMessageInstance = msg;
402 | }
403 | return obj;
404 | };
405 | }
406 |
407 |
408 | /**
409 | * Deserializes binary data (in protobuf wire format).
410 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
411 | * @return {!proto.webtor.url_store.CheckRequest}
412 | */
413 | proto.webtor.url_store.CheckRequest.deserializeBinary = function(bytes) {
414 | var reader = new jspb.BinaryReader(bytes);
415 | var msg = new proto.webtor.url_store.CheckRequest;
416 | return proto.webtor.url_store.CheckRequest.deserializeBinaryFromReader(msg, reader);
417 | };
418 |
419 |
420 | /**
421 | * Deserializes binary data (in protobuf wire format) from the
422 | * given reader into the given message object.
423 | * @param {!proto.webtor.url_store.CheckRequest} msg The message object to deserialize into.
424 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
425 | * @return {!proto.webtor.url_store.CheckRequest}
426 | */
427 | proto.webtor.url_store.CheckRequest.deserializeBinaryFromReader = function(msg, reader) {
428 | while (reader.nextField()) {
429 | if (reader.isEndGroup()) {
430 | break;
431 | }
432 | var field = reader.getFieldNumber();
433 | switch (field) {
434 | case 1:
435 | var value = /** @type {string} */ (reader.readString());
436 | msg.setHash(value);
437 | break;
438 | default:
439 | reader.skipField();
440 | break;
441 | }
442 | }
443 | return msg;
444 | };
445 |
446 |
447 | /**
448 | * Serializes the message to binary data (in protobuf wire format).
449 | * @return {!Uint8Array}
450 | */
451 | proto.webtor.url_store.CheckRequest.prototype.serializeBinary = function() {
452 | var writer = new jspb.BinaryWriter();
453 | proto.webtor.url_store.CheckRequest.serializeBinaryToWriter(this, writer);
454 | return writer.getResultBuffer();
455 | };
456 |
457 |
458 | /**
459 | * Serializes the given message to binary data (in protobuf wire
460 | * format), writing to the given BinaryWriter.
461 | * @param {!proto.webtor.url_store.CheckRequest} message
462 | * @param {!jspb.BinaryWriter} writer
463 | * @suppress {unusedLocalVariables} f is only used for nested messages
464 | */
465 | proto.webtor.url_store.CheckRequest.serializeBinaryToWriter = function(message, writer) {
466 | var f = undefined;
467 | f = message.getHash();
468 | if (f.length > 0) {
469 | writer.writeString(
470 | 1,
471 | f
472 | );
473 | }
474 | };
475 |
476 |
477 | /**
478 | * optional string hash = 1;
479 | * @return {string}
480 | */
481 | proto.webtor.url_store.CheckRequest.prototype.getHash = function() {
482 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
483 | };
484 |
485 |
486 | /**
487 | * @param {string} value
488 | * @return {!proto.webtor.url_store.CheckRequest} returns this
489 | */
490 | proto.webtor.url_store.CheckRequest.prototype.setHash = function(value) {
491 | return jspb.Message.setProto3StringField(this, 1, value);
492 | };
493 |
494 |
495 |
496 |
497 |
498 | if (jspb.Message.GENERATE_TO_OBJECT) {
499 | /**
500 | * Creates an object representation of this proto.
501 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
502 | * Optional fields that are not set will be set to undefined.
503 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
504 | * For the list of reserved names please see:
505 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
506 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
507 | * JSPB instance for transitional soy proto support:
508 | * http://goto/soy-param-migration
509 | * @return {!Object}
510 | */
511 | proto.webtor.url_store.CheckReply.prototype.toObject = function(opt_includeInstance) {
512 | return proto.webtor.url_store.CheckReply.toObject(opt_includeInstance, this);
513 | };
514 |
515 |
516 | /**
517 | * Static version of the {@see toObject} method.
518 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
519 | * the JSPB instance for transitional soy proto support:
520 | * http://goto/soy-param-migration
521 | * @param {!proto.webtor.url_store.CheckReply} msg The msg instance to transform.
522 | * @return {!Object}
523 | * @suppress {unusedLocalVariables} f is only used for nested messages
524 | */
525 | proto.webtor.url_store.CheckReply.toObject = function(includeInstance, msg) {
526 | var f, obj = {
527 | exists: jspb.Message.getBooleanFieldWithDefault(msg, 1, false)
528 | };
529 |
530 | if (includeInstance) {
531 | obj.$jspbMessageInstance = msg;
532 | }
533 | return obj;
534 | };
535 | }
536 |
537 |
538 | /**
539 | * Deserializes binary data (in protobuf wire format).
540 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
541 | * @return {!proto.webtor.url_store.CheckReply}
542 | */
543 | proto.webtor.url_store.CheckReply.deserializeBinary = function(bytes) {
544 | var reader = new jspb.BinaryReader(bytes);
545 | var msg = new proto.webtor.url_store.CheckReply;
546 | return proto.webtor.url_store.CheckReply.deserializeBinaryFromReader(msg, reader);
547 | };
548 |
549 |
550 | /**
551 | * Deserializes binary data (in protobuf wire format) from the
552 | * given reader into the given message object.
553 | * @param {!proto.webtor.url_store.CheckReply} msg The message object to deserialize into.
554 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
555 | * @return {!proto.webtor.url_store.CheckReply}
556 | */
557 | proto.webtor.url_store.CheckReply.deserializeBinaryFromReader = function(msg, reader) {
558 | while (reader.nextField()) {
559 | if (reader.isEndGroup()) {
560 | break;
561 | }
562 | var field = reader.getFieldNumber();
563 | switch (field) {
564 | case 1:
565 | var value = /** @type {boolean} */ (reader.readBool());
566 | msg.setExists(value);
567 | break;
568 | default:
569 | reader.skipField();
570 | break;
571 | }
572 | }
573 | return msg;
574 | };
575 |
576 |
577 | /**
578 | * Serializes the message to binary data (in protobuf wire format).
579 | * @return {!Uint8Array}
580 | */
581 | proto.webtor.url_store.CheckReply.prototype.serializeBinary = function() {
582 | var writer = new jspb.BinaryWriter();
583 | proto.webtor.url_store.CheckReply.serializeBinaryToWriter(this, writer);
584 | return writer.getResultBuffer();
585 | };
586 |
587 |
588 | /**
589 | * Serializes the given message to binary data (in protobuf wire
590 | * format), writing to the given BinaryWriter.
591 | * @param {!proto.webtor.url_store.CheckReply} message
592 | * @param {!jspb.BinaryWriter} writer
593 | * @suppress {unusedLocalVariables} f is only used for nested messages
594 | */
595 | proto.webtor.url_store.CheckReply.serializeBinaryToWriter = function(message, writer) {
596 | var f = undefined;
597 | f = message.getExists();
598 | if (f) {
599 | writer.writeBool(
600 | 1,
601 | f
602 | );
603 | }
604 | };
605 |
606 |
607 | /**
608 | * optional bool exists = 1;
609 | * @return {boolean}
610 | */
611 | proto.webtor.url_store.CheckReply.prototype.getExists = function() {
612 | return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));
613 | };
614 |
615 |
616 | /**
617 | * @param {boolean} value
618 | * @return {!proto.webtor.url_store.CheckReply} returns this
619 | */
620 | proto.webtor.url_store.CheckReply.prototype.setExists = function(value) {
621 | return jspb.Message.setProto3BooleanField(this, 1, value);
622 | };
623 |
624 |
625 | goog.object.extend(exports, proto);
626 |
--------------------------------------------------------------------------------
/proto/abuse-store/abuse-store_pb.js:
--------------------------------------------------------------------------------
1 | // source: proto/abuse-store/abuse-store.proto
2 | /**
3 | * @fileoverview
4 | * @enhanceable
5 | * @suppress {messageConventions} JS Compiler reports an error if a variable or
6 | * field starts with 'MSG_' and isn't a translatable message.
7 | * @public
8 | */
9 | // GENERATED CODE -- DO NOT EDIT!
10 | /* eslint-disable */
11 | // @ts-nocheck
12 |
13 | var jspb = require('google-protobuf');
14 | var goog = jspb;
15 | var proto = {};
16 |
17 | goog.exportSymbol('CheckReply', null, proto);
18 | goog.exportSymbol('CheckRequest', null, proto);
19 | goog.exportSymbol('PushReply', null, proto);
20 | goog.exportSymbol('PushRequest', null, proto);
21 | goog.exportSymbol('PushRequest.Cause', null, proto);
22 | goog.exportSymbol('PushRequest.Source', null, proto);
23 | /**
24 | * Generated by JsPbCodeGenerator.
25 | * @param {Array=} opt_data Optional initial data array, typically from a
26 | * server response, or constructed directly in Javascript. The array is used
27 | * in place and becomes part of the constructed object. It is not cloned.
28 | * If no data is provided, the constructed object will be empty, but still
29 | * valid.
30 | * @extends {jspb.Message}
31 | * @constructor
32 | */
33 | proto.PushReply = function(opt_data) {
34 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
35 | };
36 | goog.inherits(proto.PushReply, jspb.Message);
37 | if (goog.DEBUG && !COMPILED) {
38 | /**
39 | * @public
40 | * @override
41 | */
42 | proto.PushReply.displayName = 'proto.PushReply';
43 | }
44 | /**
45 | * Generated by JsPbCodeGenerator.
46 | * @param {Array=} opt_data Optional initial data array, typically from a
47 | * server response, or constructed directly in Javascript. The array is used
48 | * in place and becomes part of the constructed object. It is not cloned.
49 | * If no data is provided, the constructed object will be empty, but still
50 | * valid.
51 | * @extends {jspb.Message}
52 | * @constructor
53 | */
54 | proto.PushRequest = function(opt_data) {
55 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
56 | };
57 | goog.inherits(proto.PushRequest, jspb.Message);
58 | if (goog.DEBUG && !COMPILED) {
59 | /**
60 | * @public
61 | * @override
62 | */
63 | proto.PushRequest.displayName = 'proto.PushRequest';
64 | }
65 | /**
66 | * Generated by JsPbCodeGenerator.
67 | * @param {Array=} opt_data Optional initial data array, typically from a
68 | * server response, or constructed directly in Javascript. The array is used
69 | * in place and becomes part of the constructed object. It is not cloned.
70 | * If no data is provided, the constructed object will be empty, but still
71 | * valid.
72 | * @extends {jspb.Message}
73 | * @constructor
74 | */
75 | proto.CheckRequest = function(opt_data) {
76 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
77 | };
78 | goog.inherits(proto.CheckRequest, jspb.Message);
79 | if (goog.DEBUG && !COMPILED) {
80 | /**
81 | * @public
82 | * @override
83 | */
84 | proto.CheckRequest.displayName = 'proto.CheckRequest';
85 | }
86 | /**
87 | * Generated by JsPbCodeGenerator.
88 | * @param {Array=} opt_data Optional initial data array, typically from a
89 | * server response, or constructed directly in Javascript. The array is used
90 | * in place and becomes part of the constructed object. It is not cloned.
91 | * If no data is provided, the constructed object will be empty, but still
92 | * valid.
93 | * @extends {jspb.Message}
94 | * @constructor
95 | */
96 | proto.CheckReply = function(opt_data) {
97 | jspb.Message.initialize(this, opt_data, 0, -1, null, null);
98 | };
99 | goog.inherits(proto.CheckReply, jspb.Message);
100 | if (goog.DEBUG && !COMPILED) {
101 | /**
102 | * @public
103 | * @override
104 | */
105 | proto.CheckReply.displayName = 'proto.CheckReply';
106 | }
107 |
108 |
109 |
110 | if (jspb.Message.GENERATE_TO_OBJECT) {
111 | /**
112 | * Creates an object representation of this proto.
113 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
114 | * Optional fields that are not set will be set to undefined.
115 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
116 | * For the list of reserved names please see:
117 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
118 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
119 | * JSPB instance for transitional soy proto support:
120 | * http://goto/soy-param-migration
121 | * @return {!Object}
122 | */
123 | proto.PushReply.prototype.toObject = function(opt_includeInstance) {
124 | return proto.PushReply.toObject(opt_includeInstance, this);
125 | };
126 |
127 |
128 | /**
129 | * Static version of the {@see toObject} method.
130 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
131 | * the JSPB instance for transitional soy proto support:
132 | * http://goto/soy-param-migration
133 | * @param {!proto.PushReply} msg The msg instance to transform.
134 | * @return {!Object}
135 | * @suppress {unusedLocalVariables} f is only used for nested messages
136 | */
137 | proto.PushReply.toObject = function(includeInstance, msg) {
138 | var f, obj = {
139 |
140 | };
141 |
142 | if (includeInstance) {
143 | obj.$jspbMessageInstance = msg;
144 | }
145 | return obj;
146 | };
147 | }
148 |
149 |
150 | /**
151 | * Deserializes binary data (in protobuf wire format).
152 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
153 | * @return {!proto.PushReply}
154 | */
155 | proto.PushReply.deserializeBinary = function(bytes) {
156 | var reader = new jspb.BinaryReader(bytes);
157 | var msg = new proto.PushReply;
158 | return proto.PushReply.deserializeBinaryFromReader(msg, reader);
159 | };
160 |
161 |
162 | /**
163 | * Deserializes binary data (in protobuf wire format) from the
164 | * given reader into the given message object.
165 | * @param {!proto.PushReply} msg The message object to deserialize into.
166 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
167 | * @return {!proto.PushReply}
168 | */
169 | proto.PushReply.deserializeBinaryFromReader = function(msg, reader) {
170 | while (reader.nextField()) {
171 | if (reader.isEndGroup()) {
172 | break;
173 | }
174 | var field = reader.getFieldNumber();
175 | switch (field) {
176 | default:
177 | reader.skipField();
178 | break;
179 | }
180 | }
181 | return msg;
182 | };
183 |
184 |
185 | /**
186 | * Serializes the message to binary data (in protobuf wire format).
187 | * @return {!Uint8Array}
188 | */
189 | proto.PushReply.prototype.serializeBinary = function() {
190 | var writer = new jspb.BinaryWriter();
191 | proto.PushReply.serializeBinaryToWriter(this, writer);
192 | return writer.getResultBuffer();
193 | };
194 |
195 |
196 | /**
197 | * Serializes the given message to binary data (in protobuf wire
198 | * format), writing to the given BinaryWriter.
199 | * @param {!proto.PushReply} message
200 | * @param {!jspb.BinaryWriter} writer
201 | * @suppress {unusedLocalVariables} f is only used for nested messages
202 | */
203 | proto.PushReply.serializeBinaryToWriter = function(message, writer) {
204 | var f = undefined;
205 | };
206 |
207 |
208 |
209 |
210 |
211 | if (jspb.Message.GENERATE_TO_OBJECT) {
212 | /**
213 | * Creates an object representation of this proto.
214 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
215 | * Optional fields that are not set will be set to undefined.
216 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
217 | * For the list of reserved names please see:
218 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
219 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
220 | * JSPB instance for transitional soy proto support:
221 | * http://goto/soy-param-migration
222 | * @return {!Object}
223 | */
224 | proto.PushRequest.prototype.toObject = function(opt_includeInstance) {
225 | return proto.PushRequest.toObject(opt_includeInstance, this);
226 | };
227 |
228 |
229 | /**
230 | * Static version of the {@see toObject} method.
231 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
232 | * the JSPB instance for transitional soy proto support:
233 | * http://goto/soy-param-migration
234 | * @param {!proto.PushRequest} msg The msg instance to transform.
235 | * @return {!Object}
236 | * @suppress {unusedLocalVariables} f is only used for nested messages
237 | */
238 | proto.PushRequest.toObject = function(includeInstance, msg) {
239 | var f, obj = {
240 | noticeId: jspb.Message.getFieldWithDefault(msg, 1, ""),
241 | infohash: jspb.Message.getFieldWithDefault(msg, 2, ""),
242 | filename: jspb.Message.getFieldWithDefault(msg, 3, ""),
243 | work: jspb.Message.getFieldWithDefault(msg, 4, ""),
244 | startedAt: jspb.Message.getFieldWithDefault(msg, 5, 0),
245 | email: jspb.Message.getFieldWithDefault(msg, 6, ""),
246 | description: jspb.Message.getFieldWithDefault(msg, 7, ""),
247 | subject: jspb.Message.getFieldWithDefault(msg, 8, ""),
248 | cause: jspb.Message.getFieldWithDefault(msg, 9, 0),
249 | source: jspb.Message.getFieldWithDefault(msg, 10, 0)
250 | };
251 |
252 | if (includeInstance) {
253 | obj.$jspbMessageInstance = msg;
254 | }
255 | return obj;
256 | };
257 | }
258 |
259 |
260 | /**
261 | * Deserializes binary data (in protobuf wire format).
262 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
263 | * @return {!proto.PushRequest}
264 | */
265 | proto.PushRequest.deserializeBinary = function(bytes) {
266 | var reader = new jspb.BinaryReader(bytes);
267 | var msg = new proto.PushRequest;
268 | return proto.PushRequest.deserializeBinaryFromReader(msg, reader);
269 | };
270 |
271 |
272 | /**
273 | * Deserializes binary data (in protobuf wire format) from the
274 | * given reader into the given message object.
275 | * @param {!proto.PushRequest} msg The message object to deserialize into.
276 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
277 | * @return {!proto.PushRequest}
278 | */
279 | proto.PushRequest.deserializeBinaryFromReader = function(msg, reader) {
280 | while (reader.nextField()) {
281 | if (reader.isEndGroup()) {
282 | break;
283 | }
284 | var field = reader.getFieldNumber();
285 | switch (field) {
286 | case 1:
287 | var value = /** @type {string} */ (reader.readString());
288 | msg.setNoticeId(value);
289 | break;
290 | case 2:
291 | var value = /** @type {string} */ (reader.readString());
292 | msg.setInfohash(value);
293 | break;
294 | case 3:
295 | var value = /** @type {string} */ (reader.readString());
296 | msg.setFilename(value);
297 | break;
298 | case 4:
299 | var value = /** @type {string} */ (reader.readString());
300 | msg.setWork(value);
301 | break;
302 | case 5:
303 | var value = /** @type {number} */ (reader.readInt64());
304 | msg.setStartedAt(value);
305 | break;
306 | case 6:
307 | var value = /** @type {string} */ (reader.readString());
308 | msg.setEmail(value);
309 | break;
310 | case 7:
311 | var value = /** @type {string} */ (reader.readString());
312 | msg.setDescription(value);
313 | break;
314 | case 8:
315 | var value = /** @type {string} */ (reader.readString());
316 | msg.setSubject(value);
317 | break;
318 | case 9:
319 | var value = /** @type {!proto.PushRequest.Cause} */ (reader.readEnum());
320 | msg.setCause(value);
321 | break;
322 | case 10:
323 | var value = /** @type {!proto.PushRequest.Source} */ (reader.readEnum());
324 | msg.setSource(value);
325 | break;
326 | default:
327 | reader.skipField();
328 | break;
329 | }
330 | }
331 | return msg;
332 | };
333 |
334 |
335 | /**
336 | * Serializes the message to binary data (in protobuf wire format).
337 | * @return {!Uint8Array}
338 | */
339 | proto.PushRequest.prototype.serializeBinary = function() {
340 | var writer = new jspb.BinaryWriter();
341 | proto.PushRequest.serializeBinaryToWriter(this, writer);
342 | return writer.getResultBuffer();
343 | };
344 |
345 |
346 | /**
347 | * Serializes the given message to binary data (in protobuf wire
348 | * format), writing to the given BinaryWriter.
349 | * @param {!proto.PushRequest} message
350 | * @param {!jspb.BinaryWriter} writer
351 | * @suppress {unusedLocalVariables} f is only used for nested messages
352 | */
353 | proto.PushRequest.serializeBinaryToWriter = function(message, writer) {
354 | var f = undefined;
355 | f = message.getNoticeId();
356 | if (f.length > 0) {
357 | writer.writeString(
358 | 1,
359 | f
360 | );
361 | }
362 | f = message.getInfohash();
363 | if (f.length > 0) {
364 | writer.writeString(
365 | 2,
366 | f
367 | );
368 | }
369 | f = message.getFilename();
370 | if (f.length > 0) {
371 | writer.writeString(
372 | 3,
373 | f
374 | );
375 | }
376 | f = message.getWork();
377 | if (f.length > 0) {
378 | writer.writeString(
379 | 4,
380 | f
381 | );
382 | }
383 | f = message.getStartedAt();
384 | if (f !== 0) {
385 | writer.writeInt64(
386 | 5,
387 | f
388 | );
389 | }
390 | f = message.getEmail();
391 | if (f.length > 0) {
392 | writer.writeString(
393 | 6,
394 | f
395 | );
396 | }
397 | f = message.getDescription();
398 | if (f.length > 0) {
399 | writer.writeString(
400 | 7,
401 | f
402 | );
403 | }
404 | f = message.getSubject();
405 | if (f.length > 0) {
406 | writer.writeString(
407 | 8,
408 | f
409 | );
410 | }
411 | f = message.getCause();
412 | if (f !== 0.0) {
413 | writer.writeEnum(
414 | 9,
415 | f
416 | );
417 | }
418 | f = message.getSource();
419 | if (f !== 0.0) {
420 | writer.writeEnum(
421 | 10,
422 | f
423 | );
424 | }
425 | };
426 |
427 |
428 | /**
429 | * @enum {number}
430 | */
431 | proto.PushRequest.Cause = {
432 | ILLEGAL_CONTENT: 0,
433 | MALWARE: 1,
434 | APP_ERROR: 2,
435 | QUESTION: 3
436 | };
437 |
438 | /**
439 | * @enum {number}
440 | */
441 | proto.PushRequest.Source = {
442 | MAIL: 0,
443 | FORM: 1
444 | };
445 |
446 | /**
447 | * optional string notice_id = 1;
448 | * @return {string}
449 | */
450 | proto.PushRequest.prototype.getNoticeId = function() {
451 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
452 | };
453 |
454 |
455 | /**
456 | * @param {string} value
457 | * @return {!proto.PushRequest} returns this
458 | */
459 | proto.PushRequest.prototype.setNoticeId = function(value) {
460 | return jspb.Message.setProto3StringField(this, 1, value);
461 | };
462 |
463 |
464 | /**
465 | * optional string infohash = 2;
466 | * @return {string}
467 | */
468 | proto.PushRequest.prototype.getInfohash = function() {
469 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
470 | };
471 |
472 |
473 | /**
474 | * @param {string} value
475 | * @return {!proto.PushRequest} returns this
476 | */
477 | proto.PushRequest.prototype.setInfohash = function(value) {
478 | return jspb.Message.setProto3StringField(this, 2, value);
479 | };
480 |
481 |
482 | /**
483 | * optional string filename = 3;
484 | * @return {string}
485 | */
486 | proto.PushRequest.prototype.getFilename = function() {
487 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
488 | };
489 |
490 |
491 | /**
492 | * @param {string} value
493 | * @return {!proto.PushRequest} returns this
494 | */
495 | proto.PushRequest.prototype.setFilename = function(value) {
496 | return jspb.Message.setProto3StringField(this, 3, value);
497 | };
498 |
499 |
500 | /**
501 | * optional string work = 4;
502 | * @return {string}
503 | */
504 | proto.PushRequest.prototype.getWork = function() {
505 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, ""));
506 | };
507 |
508 |
509 | /**
510 | * @param {string} value
511 | * @return {!proto.PushRequest} returns this
512 | */
513 | proto.PushRequest.prototype.setWork = function(value) {
514 | return jspb.Message.setProto3StringField(this, 4, value);
515 | };
516 |
517 |
518 | /**
519 | * optional int64 started_at = 5;
520 | * @return {number}
521 | */
522 | proto.PushRequest.prototype.getStartedAt = function() {
523 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0));
524 | };
525 |
526 |
527 | /**
528 | * @param {number} value
529 | * @return {!proto.PushRequest} returns this
530 | */
531 | proto.PushRequest.prototype.setStartedAt = function(value) {
532 | return jspb.Message.setProto3IntField(this, 5, value);
533 | };
534 |
535 |
536 | /**
537 | * optional string email = 6;
538 | * @return {string}
539 | */
540 | proto.PushRequest.prototype.getEmail = function() {
541 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, ""));
542 | };
543 |
544 |
545 | /**
546 | * @param {string} value
547 | * @return {!proto.PushRequest} returns this
548 | */
549 | proto.PushRequest.prototype.setEmail = function(value) {
550 | return jspb.Message.setProto3StringField(this, 6, value);
551 | };
552 |
553 |
554 | /**
555 | * optional string description = 7;
556 | * @return {string}
557 | */
558 | proto.PushRequest.prototype.getDescription = function() {
559 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 7, ""));
560 | };
561 |
562 |
563 | /**
564 | * @param {string} value
565 | * @return {!proto.PushRequest} returns this
566 | */
567 | proto.PushRequest.prototype.setDescription = function(value) {
568 | return jspb.Message.setProto3StringField(this, 7, value);
569 | };
570 |
571 |
572 | /**
573 | * optional string subject = 8;
574 | * @return {string}
575 | */
576 | proto.PushRequest.prototype.getSubject = function() {
577 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, ""));
578 | };
579 |
580 |
581 | /**
582 | * @param {string} value
583 | * @return {!proto.PushRequest} returns this
584 | */
585 | proto.PushRequest.prototype.setSubject = function(value) {
586 | return jspb.Message.setProto3StringField(this, 8, value);
587 | };
588 |
589 |
590 | /**
591 | * optional Cause cause = 9;
592 | * @return {!proto.PushRequest.Cause}
593 | */
594 | proto.PushRequest.prototype.getCause = function() {
595 | return /** @type {!proto.PushRequest.Cause} */ (jspb.Message.getFieldWithDefault(this, 9, 0));
596 | };
597 |
598 |
599 | /**
600 | * @param {!proto.PushRequest.Cause} value
601 | * @return {!proto.PushRequest} returns this
602 | */
603 | proto.PushRequest.prototype.setCause = function(value) {
604 | return jspb.Message.setProto3EnumField(this, 9, value);
605 | };
606 |
607 |
608 | /**
609 | * optional Source source = 10;
610 | * @return {!proto.PushRequest.Source}
611 | */
612 | proto.PushRequest.prototype.getSource = function() {
613 | return /** @type {!proto.PushRequest.Source} */ (jspb.Message.getFieldWithDefault(this, 10, 0));
614 | };
615 |
616 |
617 | /**
618 | * @param {!proto.PushRequest.Source} value
619 | * @return {!proto.PushRequest} returns this
620 | */
621 | proto.PushRequest.prototype.setSource = function(value) {
622 | return jspb.Message.setProto3EnumField(this, 10, value);
623 | };
624 |
625 |
626 |
627 |
628 |
629 | if (jspb.Message.GENERATE_TO_OBJECT) {
630 | /**
631 | * Creates an object representation of this proto.
632 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
633 | * Optional fields that are not set will be set to undefined.
634 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
635 | * For the list of reserved names please see:
636 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
637 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
638 | * JSPB instance for transitional soy proto support:
639 | * http://goto/soy-param-migration
640 | * @return {!Object}
641 | */
642 | proto.CheckRequest.prototype.toObject = function(opt_includeInstance) {
643 | return proto.CheckRequest.toObject(opt_includeInstance, this);
644 | };
645 |
646 |
647 | /**
648 | * Static version of the {@see toObject} method.
649 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
650 | * the JSPB instance for transitional soy proto support:
651 | * http://goto/soy-param-migration
652 | * @param {!proto.CheckRequest} msg The msg instance to transform.
653 | * @return {!Object}
654 | * @suppress {unusedLocalVariables} f is only used for nested messages
655 | */
656 | proto.CheckRequest.toObject = function(includeInstance, msg) {
657 | var f, obj = {
658 | infohash: jspb.Message.getFieldWithDefault(msg, 1, "")
659 | };
660 |
661 | if (includeInstance) {
662 | obj.$jspbMessageInstance = msg;
663 | }
664 | return obj;
665 | };
666 | }
667 |
668 |
669 | /**
670 | * Deserializes binary data (in protobuf wire format).
671 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
672 | * @return {!proto.CheckRequest}
673 | */
674 | proto.CheckRequest.deserializeBinary = function(bytes) {
675 | var reader = new jspb.BinaryReader(bytes);
676 | var msg = new proto.CheckRequest;
677 | return proto.CheckRequest.deserializeBinaryFromReader(msg, reader);
678 | };
679 |
680 |
681 | /**
682 | * Deserializes binary data (in protobuf wire format) from the
683 | * given reader into the given message object.
684 | * @param {!proto.CheckRequest} msg The message object to deserialize into.
685 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
686 | * @return {!proto.CheckRequest}
687 | */
688 | proto.CheckRequest.deserializeBinaryFromReader = function(msg, reader) {
689 | while (reader.nextField()) {
690 | if (reader.isEndGroup()) {
691 | break;
692 | }
693 | var field = reader.getFieldNumber();
694 | switch (field) {
695 | case 1:
696 | var value = /** @type {string} */ (reader.readString());
697 | msg.setInfohash(value);
698 | break;
699 | default:
700 | reader.skipField();
701 | break;
702 | }
703 | }
704 | return msg;
705 | };
706 |
707 |
708 | /**
709 | * Serializes the message to binary data (in protobuf wire format).
710 | * @return {!Uint8Array}
711 | */
712 | proto.CheckRequest.prototype.serializeBinary = function() {
713 | var writer = new jspb.BinaryWriter();
714 | proto.CheckRequest.serializeBinaryToWriter(this, writer);
715 | return writer.getResultBuffer();
716 | };
717 |
718 |
719 | /**
720 | * Serializes the given message to binary data (in protobuf wire
721 | * format), writing to the given BinaryWriter.
722 | * @param {!proto.CheckRequest} message
723 | * @param {!jspb.BinaryWriter} writer
724 | * @suppress {unusedLocalVariables} f is only used for nested messages
725 | */
726 | proto.CheckRequest.serializeBinaryToWriter = function(message, writer) {
727 | var f = undefined;
728 | f = message.getInfohash();
729 | if (f.length > 0) {
730 | writer.writeString(
731 | 1,
732 | f
733 | );
734 | }
735 | };
736 |
737 |
738 | /**
739 | * optional string infohash = 1;
740 | * @return {string}
741 | */
742 | proto.CheckRequest.prototype.getInfohash = function() {
743 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
744 | };
745 |
746 |
747 | /**
748 | * @param {string} value
749 | * @return {!proto.CheckRequest} returns this
750 | */
751 | proto.CheckRequest.prototype.setInfohash = function(value) {
752 | return jspb.Message.setProto3StringField(this, 1, value);
753 | };
754 |
755 |
756 |
757 |
758 |
759 | if (jspb.Message.GENERATE_TO_OBJECT) {
760 | /**
761 | * Creates an object representation of this proto.
762 | * Field names that are reserved in JavaScript and will be renamed to pb_name.
763 | * Optional fields that are not set will be set to undefined.
764 | * To access a reserved field use, foo.pb_, eg, foo.pb_default.
765 | * For the list of reserved names please see:
766 | * net/proto2/compiler/js/internal/generator.cc#kKeyword.
767 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the
768 | * JSPB instance for transitional soy proto support:
769 | * http://goto/soy-param-migration
770 | * @return {!Object}
771 | */
772 | proto.CheckReply.prototype.toObject = function(opt_includeInstance) {
773 | return proto.CheckReply.toObject(opt_includeInstance, this);
774 | };
775 |
776 |
777 | /**
778 | * Static version of the {@see toObject} method.
779 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include
780 | * the JSPB instance for transitional soy proto support:
781 | * http://goto/soy-param-migration
782 | * @param {!proto.CheckReply} msg The msg instance to transform.
783 | * @return {!Object}
784 | * @suppress {unusedLocalVariables} f is only used for nested messages
785 | */
786 | proto.CheckReply.toObject = function(includeInstance, msg) {
787 | var f, obj = {
788 | exists: jspb.Message.getBooleanFieldWithDefault(msg, 1, false)
789 | };
790 |
791 | if (includeInstance) {
792 | obj.$jspbMessageInstance = msg;
793 | }
794 | return obj;
795 | };
796 | }
797 |
798 |
799 | /**
800 | * Deserializes binary data (in protobuf wire format).
801 | * @param {jspb.ByteSource} bytes The bytes to deserialize.
802 | * @return {!proto.CheckReply}
803 | */
804 | proto.CheckReply.deserializeBinary = function(bytes) {
805 | var reader = new jspb.BinaryReader(bytes);
806 | var msg = new proto.CheckReply;
807 | return proto.CheckReply.deserializeBinaryFromReader(msg, reader);
808 | };
809 |
810 |
811 | /**
812 | * Deserializes binary data (in protobuf wire format) from the
813 | * given reader into the given message object.
814 | * @param {!proto.CheckReply} msg The message object to deserialize into.
815 | * @param {!jspb.BinaryReader} reader The BinaryReader to use.
816 | * @return {!proto.CheckReply}
817 | */
818 | proto.CheckReply.deserializeBinaryFromReader = function(msg, reader) {
819 | while (reader.nextField()) {
820 | if (reader.isEndGroup()) {
821 | break;
822 | }
823 | var field = reader.getFieldNumber();
824 | switch (field) {
825 | case 1:
826 | var value = /** @type {boolean} */ (reader.readBool());
827 | msg.setExists(value);
828 | break;
829 | default:
830 | reader.skipField();
831 | break;
832 | }
833 | }
834 | return msg;
835 | };
836 |
837 |
838 | /**
839 | * Serializes the message to binary data (in protobuf wire format).
840 | * @return {!Uint8Array}
841 | */
842 | proto.CheckReply.prototype.serializeBinary = function() {
843 | var writer = new jspb.BinaryWriter();
844 | proto.CheckReply.serializeBinaryToWriter(this, writer);
845 | return writer.getResultBuffer();
846 | };
847 |
848 |
849 | /**
850 | * Serializes the given message to binary data (in protobuf wire
851 | * format), writing to the given BinaryWriter.
852 | * @param {!proto.CheckReply} message
853 | * @param {!jspb.BinaryWriter} writer
854 | * @suppress {unusedLocalVariables} f is only used for nested messages
855 | */
856 | proto.CheckReply.serializeBinaryToWriter = function(message, writer) {
857 | var f = undefined;
858 | f = message.getExists();
859 | if (f) {
860 | writer.writeBool(
861 | 1,
862 | f
863 | );
864 | }
865 | };
866 |
867 |
868 | /**
869 | * optional bool exists = 1;
870 | * @return {boolean}
871 | */
872 | proto.CheckReply.prototype.getExists = function() {
873 | return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));
874 | };
875 |
876 |
877 | /**
878 | * @param {boolean} value
879 | * @return {!proto.CheckReply} returns this
880 | */
881 | proto.CheckReply.prototype.setExists = function(value) {
882 | return jspb.Message.setProto3BooleanField(this, 1, value);
883 | };
884 |
885 |
886 | goog.object.extend(exports, proto);
887 |
--------------------------------------------------------------------------------