@nekosuneprojects/nekosunevrtools 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,126 @@
1
+ const axios = require("axios");
2
+ const { presets, providers } = require("./providers");
3
+
4
+ class DownloaderClient {
5
+ constructor(options = {}) {
6
+ this.timeoutMs = options.timeoutMs || 120000;
7
+ this.apiKey = options.apiKey || null;
8
+ this.baseUrl = resolveBaseUrl(options.baseUrl, options.preset || "nekosune");
9
+ this.provider = providers.compatible(this.baseUrl);
10
+ }
11
+
12
+ useBaseUrl(baseUrl) {
13
+ this.baseUrl = resolveBaseUrl(baseUrl);
14
+ this.provider = providers.compatible(this.baseUrl);
15
+ return this;
16
+ }
17
+
18
+ usePreset(name) {
19
+ this.baseUrl = resolveBaseUrl(null, name);
20
+ this.provider = providers.compatible(this.baseUrl);
21
+ return this;
22
+ }
23
+
24
+ async createMp3Job(link, options = {}) {
25
+ return this.provider.createMp3Job({
26
+ http: this.createHttp(options),
27
+ apiKey: options.apiKey || this.apiKey,
28
+ link,
29
+ uploadDest: options.uploadDest || "cdn"
30
+ });
31
+ }
32
+
33
+ async createMp4Job(link, options = {}) {
34
+ return this.provider.createMp4Job({
35
+ http: this.createHttp(options),
36
+ apiKey: options.apiKey || this.apiKey,
37
+ link,
38
+ uploadDest: options.uploadDest || "cdn"
39
+ });
40
+ }
41
+
42
+ async getJob(jobId, options = {}) {
43
+ return this.provider.getJob({
44
+ http: this.createHttp(options),
45
+ apiKey: options.apiKey || this.apiKey,
46
+ jobId
47
+ });
48
+ }
49
+
50
+ async waitForJob(jobId, options = {}) {
51
+ const intervalMs = Math.max(500, options.intervalMs || 2000);
52
+ const timeoutMs = Math.max(intervalMs, options.timeoutMs || 300000);
53
+ const started = Date.now();
54
+
55
+ while (true) {
56
+ const state = await this.getJob(jobId, options);
57
+ if (typeof options.onProgress === "function") {
58
+ options.onProgress(state);
59
+ }
60
+ if (state && state.status === "done") {
61
+ return state;
62
+ }
63
+ if (state && (state.status === "error" || state.status === "failed")) {
64
+ throw new Error(state.message || "Downloader job failed.");
65
+ }
66
+ if (Date.now() - started > timeoutMs) {
67
+ throw new Error("Downloader job wait timed out.");
68
+ }
69
+ await sleep(intervalMs);
70
+ }
71
+ }
72
+
73
+ async getInfo(url, options = {}) {
74
+ return this.provider.getInfo({
75
+ http: this.createHttp(options),
76
+ url,
77
+ flat: Boolean(options.flat || options.flatPlaylist),
78
+ fields: options.fields || "basic",
79
+ cache: typeof options.cache === "number" ? options.cache : 1
80
+ });
81
+ }
82
+
83
+ async searchYouTube(query, options = {}) {
84
+ return this.provider.searchYouTube({
85
+ http: this.createHttp(options),
86
+ query,
87
+ limit: typeof options.limit === "number" ? options.limit : 5
88
+ });
89
+ }
90
+
91
+ getStreamUrl(url) {
92
+ return this.provider.getStreamUrl({ url });
93
+ }
94
+
95
+ async stream(url, options = {}) {
96
+ return this.provider.stream({
97
+ http: this.createHttp(options),
98
+ url,
99
+ responseType: options.responseType || "stream"
100
+ });
101
+ }
102
+
103
+ createHttp(options = {}) {
104
+ return axios.create({ timeout: options.timeoutMs || this.timeoutMs });
105
+ }
106
+ }
107
+
108
+ function resolveBaseUrl(baseUrl, preset) {
109
+ if (baseUrl) {
110
+ return String(baseUrl).replace(/\/+$/, "");
111
+ }
112
+ if (preset && presets[preset]) {
113
+ return presets[preset];
114
+ }
115
+ throw new Error(`Unknown downloader preset "${preset}". Available: ${Object.keys(presets).join(", ")}`);
116
+ }
117
+
118
+ function sleep(ms) {
119
+ return new Promise((resolve) => setTimeout(resolve, ms));
120
+ }
121
+
122
+ module.exports = {
123
+ DownloaderClient,
124
+ presets,
125
+ providers
126
+ };
@@ -0,0 +1,127 @@
1
+ function createDownloaderProvider(baseUrl) {
2
+ const normalizedBaseUrl = String(baseUrl || "").replace(/\/+$/, "");
3
+ if (!normalizedBaseUrl) {
4
+ throw new Error("Missing downloader baseUrl.");
5
+ }
6
+
7
+ async function createMp3Job(context) {
8
+ return createJob(context, "mp3");
9
+ }
10
+
11
+ async function createMp4Job(context) {
12
+ return createJob(context, "mp4");
13
+ }
14
+
15
+ async function createJob(context, mode) {
16
+ const { apiKey, http, link, uploadDest } = context;
17
+ assertApiKey(apiKey);
18
+ if (!link) {
19
+ throw new Error(`Missing "link" for ${mode} job.`);
20
+ }
21
+
22
+ const response = await http.post(`${normalizedBaseUrl}/api/${mode}/jobs`, {
23
+ link,
24
+ upload_dest: uploadDest || "cdn"
25
+ }, {
26
+ headers: buildAuthHeaders(apiKey)
27
+ });
28
+
29
+ const body = response.data || {};
30
+ if (!body.job_id) {
31
+ throw new Error(`Downloader ${mode} job did not return job_id.`);
32
+ }
33
+
34
+ return {
35
+ provider: "downloader-compatible",
36
+ jobId: body.job_id,
37
+ raw: body
38
+ };
39
+ }
40
+
41
+ async function getJob(context) {
42
+ const { apiKey, http, jobId } = context;
43
+ assertApiKey(apiKey);
44
+ if (!jobId) {
45
+ throw new Error('Missing "jobId".');
46
+ }
47
+
48
+ const response = await http.get(`${normalizedBaseUrl}/api/jobs/${encodeURIComponent(jobId)}`, {
49
+ headers: buildAuthHeaders(apiKey)
50
+ });
51
+ return response.data || {};
52
+ }
53
+
54
+ async function getInfo(context) {
55
+ const { http, url, flat, fields, cache } = context;
56
+ if (!url) {
57
+ throw new Error('Missing "url" for info endpoint.');
58
+ }
59
+ const response = await http.get(`${normalizedBaseUrl}/api/info`, {
60
+ params: {
61
+ url,
62
+ flat: flat ? 1 : undefined,
63
+ fields: fields || undefined,
64
+ cache: typeof cache === "number" ? cache : undefined
65
+ }
66
+ });
67
+ return response.data || {};
68
+ }
69
+
70
+ async function searchYouTube(context) {
71
+ const { http, query, limit } = context;
72
+ if (!query) {
73
+ throw new Error('Missing "query" for youtube search.');
74
+ }
75
+ const response = await http.get(`${normalizedBaseUrl}/api/search/youtube`, {
76
+ params: {
77
+ q: query,
78
+ limit: typeof limit === "number" ? limit : undefined
79
+ }
80
+ });
81
+ return response.data || {};
82
+ }
83
+
84
+ function getStreamUrl(context) {
85
+ const { url } = context;
86
+ if (!url) {
87
+ throw new Error('Missing "url" for stream endpoint.');
88
+ }
89
+ return `${normalizedBaseUrl}/api/stream?url=${encodeURIComponent(url)}`;
90
+ }
91
+
92
+ async function stream(context) {
93
+ const { http, url, responseType } = context;
94
+ const streamUrl = getStreamUrl({ url });
95
+ const response = await http.get(streamUrl, {
96
+ responseType: responseType || "stream"
97
+ });
98
+ return response;
99
+ }
100
+
101
+ return {
102
+ createMp3Job,
103
+ createMp4Job,
104
+ getJob,
105
+ getInfo,
106
+ searchYouTube,
107
+ getStreamUrl,
108
+ stream
109
+ };
110
+ }
111
+
112
+ function assertApiKey(apiKey) {
113
+ if (!apiKey) {
114
+ throw new Error('Missing downloader apiKey. Pass "apiKey" in client options or call options.');
115
+ }
116
+ }
117
+
118
+ function buildAuthHeaders(apiKey) {
119
+ return {
120
+ "x-api-key": apiKey,
121
+ Authorization: `Bearer ${apiKey}`
122
+ };
123
+ }
124
+
125
+ module.exports = {
126
+ createDownloaderProvider
127
+ };
@@ -0,0 +1,15 @@
1
+ const { createDownloaderProvider } = require("./provider/compatible");
2
+
3
+ const presets = {
4
+ nekosune: "https://dl.nekosunevr.co.uk",
5
+ ballisticok: "https://dl.ballisticok.xyz"
6
+ };
7
+
8
+ const providers = {
9
+ compatible: createDownloaderProvider
10
+ };
11
+
12
+ module.exports = {
13
+ presets,
14
+ providers
15
+ };
@@ -0,0 +1,162 @@
1
+ const axios = require("axios");
2
+ const { presets, providers } = require("./providers");
3
+
4
+ class GamesClient {
5
+ constructor(options = {}) {
6
+ this.timeoutMs = options.timeoutMs || 60000;
7
+ this.apiKey = options.apiKey || null;
8
+ this.baseUrl = resolveBaseUrl(options.baseUrl, options.preset || "nekosune");
9
+ this.provider = providers.nekosune(this.baseUrl);
10
+ }
11
+
12
+ useBaseUrl(baseUrl) {
13
+ this.baseUrl = resolveBaseUrl(baseUrl);
14
+ this.provider = providers.nekosune(this.baseUrl);
15
+ return this;
16
+ }
17
+
18
+ usePreset(name) {
19
+ this.baseUrl = resolveBaseUrl(null, name);
20
+ this.provider = providers.nekosune(this.baseUrl);
21
+ return this;
22
+ }
23
+
24
+ getClashOfClansClan(clanTag, options = {}) {
25
+ return this.provider.getClashOfClansClan({
26
+ http: this.createHttp(options),
27
+ apiKey: options.apiKey || this.apiKey,
28
+ clanTag
29
+ });
30
+ }
31
+
32
+ getClashOfClansPlayer(playerTag, options = {}) {
33
+ return this.provider.getClashOfClansPlayer({
34
+ http: this.createHttp(options),
35
+ apiKey: options.apiKey || this.apiKey,
36
+ playerTag
37
+ });
38
+ }
39
+
40
+ getDivision2Player(username, platform = "psn", options = {}) {
41
+ return this.provider.getDivision2Player({
42
+ http: this.createHttp(options),
43
+ apiKey: options.apiKey || this.apiKey,
44
+ username,
45
+ platform
46
+ });
47
+ }
48
+
49
+ getFortnitePlayer(username, timeWindow = "lifetime", options = {}) {
50
+ return this.provider.getFortnitePlayer({
51
+ http: this.createHttp(options),
52
+ apiKey: options.apiKey || this.apiKey,
53
+ username,
54
+ timeWindow
55
+ });
56
+ }
57
+
58
+ getFortniteCreatorCode(creatorCode, options = {}) {
59
+ return this.provider.getFortniteCreatorCode({
60
+ http: this.createHttp(options),
61
+ apiKey: options.apiKey || this.apiKey,
62
+ creatorCode
63
+ });
64
+ }
65
+
66
+ getFortniteItemShop(options = {}) {
67
+ return this.provider.getFortniteItemShop({
68
+ http: this.createHttp(options),
69
+ apiKey: options.apiKey || this.apiKey
70
+ });
71
+ }
72
+
73
+ getWynncraftProfile(username, options = {}) {
74
+ return this.provider.getWynncraftProfile({
75
+ http: this.createHttp(options),
76
+ apiKey: options.apiKey || this.apiKey,
77
+ username
78
+ });
79
+ }
80
+
81
+ getHypixelProfile(username, options = {}) {
82
+ return this.provider.getHypixelProfile({
83
+ http: this.createHttp(options),
84
+ apiKey: options.apiKey || this.apiKey,
85
+ username
86
+ });
87
+ }
88
+
89
+ getRocketLeaguePlayer(username, platform = "psn", options = {}) {
90
+ return this.provider.getRocketLeaguePlayer({
91
+ http: this.createHttp(options),
92
+ apiKey: options.apiKey || this.apiKey,
93
+ username,
94
+ platform
95
+ });
96
+ }
97
+
98
+ getApexLegendsPlayer(username, platform = "psn", options = {}) {
99
+ return this.provider.getApexLegendsPlayer({
100
+ http: this.createHttp(options),
101
+ apiKey: options.apiKey || this.apiKey,
102
+ username,
103
+ platform
104
+ });
105
+ }
106
+
107
+ getBattlefield1Player(username, platform = "psn", options = {}) {
108
+ return this.provider.getBattlefield1Player({
109
+ http: this.createHttp(options),
110
+ apiKey: options.apiKey || this.apiKey,
111
+ username,
112
+ platform
113
+ });
114
+ }
115
+
116
+ getBattlefield5Player(username, platform = "psn", options = {}) {
117
+ return this.provider.getBattlefield5Player({
118
+ http: this.createHttp(options),
119
+ apiKey: options.apiKey || this.apiKey,
120
+ username,
121
+ platform
122
+ });
123
+ }
124
+
125
+ getBattlefield2042Player(username, platform = "ea", options = {}) {
126
+ return this.provider.getBattlefield2042Player({
127
+ http: this.createHttp(options),
128
+ apiKey: options.apiKey || this.apiKey,
129
+ username,
130
+ platform
131
+ });
132
+ }
133
+
134
+ getBattlefield6Player(username, platform = "psn", options = {}) {
135
+ return this.provider.getBattlefield6Player({
136
+ http: this.createHttp(options),
137
+ apiKey: options.apiKey || this.apiKey,
138
+ username,
139
+ platform
140
+ });
141
+ }
142
+
143
+ createHttp(options = {}) {
144
+ return axios.create({ timeout: options.timeoutMs || this.timeoutMs });
145
+ }
146
+ }
147
+
148
+ function resolveBaseUrl(baseUrl, preset) {
149
+ if (baseUrl) {
150
+ return String(baseUrl).replace(/\/+$/, "");
151
+ }
152
+ if (preset && presets[preset]) {
153
+ return presets[preset];
154
+ }
155
+ throw new Error(`Unknown games preset "${preset}". Available: ${Object.keys(presets).join(", ")}`);
156
+ }
157
+
158
+ module.exports = {
159
+ GamesClient,
160
+ presets,
161
+ providers
162
+ };