nekostream 2026.2.8 → 2026.2.10
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.
- package/dist/index.js +1 -6
- package/dist/scrapers/auth-service.js +56 -76
- package/dist/ui.js +16 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -576,12 +576,7 @@ async function checkUpdate() {
|
|
|
576
576
|
const latestVersion = data.version;
|
|
577
577
|
if (latestVersion && latestVersion !== currentVersion) {
|
|
578
578
|
(0, ui_1.clearScreen)();
|
|
579
|
-
|
|
580
|
-
console.log(chalk_1.default.yellow('│ │'));
|
|
581
|
-
console.log(chalk_1.default.yellow(`│ NEKOSTREAM ĐÃ CÓ CẬP NHẬT MỚI ! ${chalk_1.default.red(currentVersion)} → ${chalk_1.default.green(latestVersion)} │`));
|
|
582
|
-
console.log(chalk_1.default.yellow('│ Vui lòng cập nhật ứng dụng CLI để tiếp tục sử dụng ứng dụng. │'));
|
|
583
|
-
console.log(chalk_1.default.yellow('│ │'));
|
|
584
|
-
console.log(chalk_1.default.yellow('╰─────────────────────────────────────────────────────────────╯\n'));
|
|
579
|
+
(0, ui_1.printUpdateNotice)(currentVersion, latestVersion, NPM_PACKAGE_NAME);
|
|
585
580
|
const { update } = await (0, prompts_wrapper_1.default)({
|
|
586
581
|
type: 'confirm',
|
|
587
582
|
name: 'update',
|
|
@@ -120,6 +120,13 @@ async function getAdblocker() {
|
|
|
120
120
|
* Call applyAdBlockingToPage(page) after creating each page for network blocking.
|
|
121
121
|
*/
|
|
122
122
|
async function applyAdBlocking(context) {
|
|
123
|
+
await context.route('**/*', (route) => {
|
|
124
|
+
const url = route.request().url().toLowerCase();
|
|
125
|
+
if (/win88|yo88|i9bet|sunwin|fb88|vsbet|five88|hit\.club|gemwin|789bet|7zwin|rikvip|rik\.|nohu|nổ-hũ|casino|doubleclick|googlesyndication|googleadservices|adservice|exoclick|trafficjunky|popads|adcash|propellerads|adsterra|mgid|outbrain|taboola/.test(url)) {
|
|
126
|
+
return route.abort();
|
|
127
|
+
}
|
|
128
|
+
return route.continue();
|
|
129
|
+
});
|
|
123
130
|
// CSS + JS pop-up blocking at context level (runs on every page before load)
|
|
124
131
|
await context.addInitScript(() => {
|
|
125
132
|
window.open = () => null;
|
|
@@ -128,52 +135,61 @@ async function applyAdBlocking(context) {
|
|
|
128
135
|
window.prompt = () => null;
|
|
129
136
|
const hideAds = () => {
|
|
130
137
|
const style = document.createElement('style');
|
|
131
|
-
style.textContent = `
|
|
132
|
-
a[href*="win88"], a[href*="yo88"], a[href*="i9bet"],
|
|
133
|
-
a[href*="sunwin"], a[href*="vsbet"], a[href*="five88"],
|
|
134
|
-
a[href*="hit.club"], a[href*="gemwin"], a[href*="789bet"],
|
|
135
|
-
|
|
136
|
-
img[src*="
|
|
137
|
-
[
|
|
138
|
-
[
|
|
139
|
-
[
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
138
|
+
style.textContent = `
|
|
139
|
+
a[href*="win88"], a[href*="yo88"], a[href*="i9bet"],
|
|
140
|
+
a[href*="sunwin"], a[href*="vsbet"], a[href*="five88"],
|
|
141
|
+
a[href*="hit.club"], a[href*="gemwin"], a[href*="789bet"],
|
|
142
|
+
a[href*="7zwin"], a[href*="rikvip"], a[href*="casino"],
|
|
143
|
+
img[src*="win88"], img[src*="yo88"], img[src*="i9bet"],
|
|
144
|
+
img[src*="sunwin"], img[src*="gemwin"],
|
|
145
|
+
img[src*="vsbet"], img[src*="five88"], img[src*="hit.club"],
|
|
146
|
+
img[src*="7zwin"], img[src*="rikvip"], img[src*="casino"],
|
|
147
|
+
[class*="quang-cao"], [id*="quang-cao"],
|
|
148
|
+
[class*="advert"], [id*="advert"], [class*="banner-ad"], [id*="banner-ad"],
|
|
149
|
+
[class*="popup-ad"], [class*="ad-overlay"],
|
|
150
|
+
[class*="sticky-ad"], [class*="fixed-ad"], [class*="float-ad"],
|
|
151
|
+
div.header-ads-pc, div[class*="header-ads"], div[id*="header-ads"] {
|
|
152
|
+
display: none !important;
|
|
153
|
+
visibility: hidden !important;
|
|
154
|
+
pointer-events: none !important;
|
|
155
|
+
}
|
|
147
156
|
`;
|
|
148
157
|
document.head?.appendChild(style);
|
|
149
158
|
};
|
|
159
|
+
const adPattern = /win88|yo88|i9bet|sunwin|fb88|vsbet|five88|hit\.club|gemwin|789bet|7zwin|rikvip|rik\.|nohu|nổ\s*hũ|casino|worldcup|uy\s*lực/i;
|
|
160
|
+
const removeAdNode = (node) => {
|
|
161
|
+
const container = node.closest('a, iframe, [class*="banner"], [id*="banner"], [class*="ads"], [id*="ads"], [class*="ad-"], [id*="ad-"]');
|
|
162
|
+
(container || node).remove();
|
|
163
|
+
};
|
|
164
|
+
const cleanupAds = () => {
|
|
165
|
+
try {
|
|
166
|
+
const candidates = document.querySelectorAll('a[href], img[src], iframe[src], [style*="position: fixed"], [style*="z-index"]');
|
|
167
|
+
for (const el of Array.from(candidates)) {
|
|
168
|
+
const marker = `${el.getAttribute('href') || ''} ${el.getAttribute('src') || ''} ${el.getAttribute('alt') || ''} ${el.getAttribute('title') || ''} ${el.textContent || ''}`;
|
|
169
|
+
if (adPattern.test(marker))
|
|
170
|
+
removeAdNode(el);
|
|
171
|
+
}
|
|
172
|
+
for (const el of Array.from(document.querySelectorAll('div, section, aside'))) {
|
|
173
|
+
const html = el.outerHTML.slice(0, 2000);
|
|
174
|
+
const rect = el.getBoundingClientRect();
|
|
175
|
+
if (adPattern.test(html) && (rect.width > 250 || rect.height > 80))
|
|
176
|
+
el.remove();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch { }
|
|
180
|
+
};
|
|
150
181
|
if (document.readyState === 'loading') {
|
|
151
|
-
document.addEventListener('DOMContentLoaded',
|
|
182
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
183
|
+
hideAds();
|
|
184
|
+
cleanupAds();
|
|
185
|
+
});
|
|
152
186
|
}
|
|
153
187
|
else {
|
|
154
188
|
hideAds();
|
|
189
|
+
cleanupAds();
|
|
155
190
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
setInterval(() => {
|
|
159
|
-
try {
|
|
160
|
-
const elements = document.querySelectorAll('div.MnBr.EcBgA, div.announcement, div a img, section.Wdgt, aside div ul, footer.Footer, div.header-ads-pc, ol.breadcrumb, aside.widget-area, header.Header.MnBrCn.BgA.HdOp1, [class*="quang-cao"], [id*="quang-cao"], [class*="popup-ad"], [class*="ad-overlay"], [class*="sticky-ad"], [class*="fixed-ad"], [class*="float-ad"]');
|
|
161
|
-
for (const el of Array.from(elements)) {
|
|
162
|
-
el.remove();
|
|
163
|
-
}
|
|
164
|
-
// Also check all links and images for ad keywords
|
|
165
|
-
const allElements = document.querySelectorAll('a, img');
|
|
166
|
-
for (const el of Array.from(allElements)) {
|
|
167
|
-
const html = (el.outerHTML || '').toLowerCase();
|
|
168
|
-
if (/win88|yo88|i9bet|sunwin|vsbet|five88|hit\.club|gemwin|789bet/.test(html)) {
|
|
169
|
-
el.remove();
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
catch (e) { }
|
|
174
|
-
}, 50);
|
|
175
|
-
};
|
|
176
|
-
startObserver();
|
|
191
|
+
new MutationObserver(cleanupAds).observe(document.documentElement, { childList: true, subtree: true });
|
|
192
|
+
setInterval(cleanupAds, 500);
|
|
177
193
|
});
|
|
178
194
|
}
|
|
179
195
|
/**
|
|
@@ -186,16 +202,6 @@ async function applyAdBlockingToPage(page) {
|
|
|
186
202
|
if (blocker) {
|
|
187
203
|
await blocker.enableBlockingInPage(page);
|
|
188
204
|
}
|
|
189
|
-
else {
|
|
190
|
-
// Fallback: manual domain blocking
|
|
191
|
-
await page.route('**/*', (route) => {
|
|
192
|
-
const url = route.request().url().toLowerCase();
|
|
193
|
-
if (/win88|yo88|i9bet|sunwin|fb88|vsbet|five88|hit\.club|gemwin|789bet|doubleclick|googlesyndication|exoclick|trafficjunky|popads|adcash|propellerads/.test(url)) {
|
|
194
|
-
return route.abort();
|
|
195
|
-
}
|
|
196
|
-
return route.continue();
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
205
|
}
|
|
200
206
|
function getAuthStatus(provider) {
|
|
201
207
|
const session = (0, storage_1.loadAuthSession)(provider);
|
|
@@ -240,37 +246,11 @@ async function loginAnimeVietsubInteractive() {
|
|
|
240
246
|
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
|
|
241
247
|
globalThis.chrome = { runtime: {} };
|
|
242
248
|
});
|
|
243
|
-
|
|
244
|
-
// await applyAdBlocking(context)
|
|
249
|
+
await applyAdBlocking(context);
|
|
245
250
|
const page = await context.newPage();
|
|
246
|
-
|
|
251
|
+
await applyAdBlockingToPage(page);
|
|
247
252
|
try {
|
|
248
253
|
await page.goto(AVS_LOGIN_URL, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
249
|
-
// Force inject CSS bypassed for AnimeVietsub to avoid triggering adblocker detection
|
|
250
|
-
/*
|
|
251
|
-
await page.addStyleTag({
|
|
252
|
-
content: `
|
|
253
|
-
a[href*="win88"], a[href*="yo88"], a[href*="i9bet"],
|
|
254
|
-
a[href*="sunwin"], a[href*="vsbet"], a[href*="five88"],
|
|
255
|
-
a[href*="hit.club"], a[href*="gemwin"], a[href*="789bet"],
|
|
256
|
-
img[src*="win88"], img[src*="yo88"], img[src*="i9bet"],
|
|
257
|
-
img[src*="sunwin"], img[src*="gemwin"],
|
|
258
|
-
[class*="quang-cao"], [id*="quang-cao"],
|
|
259
|
-
[class*="popup-ad"], [class*="ad-overlay"],
|
|
260
|
-
[class*="sticky-ad"], [class*="fixed-ad"], [class*="float-ad"],
|
|
261
|
-
div.MnBr.EcBgA, div.announcement, div a img, section.Wdgt,
|
|
262
|
-
aside div ul, footer.Footer, div.header-ads-pc, ol.breadcrumb,
|
|
263
|
-
aside.widget-area, header.Header.MnBrCn.BgA.HdOp1 {
|
|
264
|
-
display: none !important;
|
|
265
|
-
visibility: hidden !important;
|
|
266
|
-
pointer-events: none !important;
|
|
267
|
-
opacity: 0 !important;
|
|
268
|
-
width: 0 !important;
|
|
269
|
-
height: 0 !important;
|
|
270
|
-
}
|
|
271
|
-
`
|
|
272
|
-
}).catch(() => {})
|
|
273
|
-
*/
|
|
274
254
|
// Wait for successful login (redirect away from login page)
|
|
275
255
|
await page.waitForFunction(() => !location.href.includes('/login') && !location.href.includes('/dang-nhap'), { timeout: 180000, polling: 1000 });
|
|
276
256
|
// Extra settle time for cookies to be written
|
package/dist/ui.js
CHANGED
|
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.clearScreen = clearScreen;
|
|
40
40
|
exports.printBanner = printBanner;
|
|
41
|
+
exports.printUpdateNotice = printUpdateNotice;
|
|
41
42
|
exports.printStatusStrip = printStatusStrip;
|
|
42
43
|
exports.drawAnimeCard = drawAnimeCard;
|
|
43
44
|
exports.drawAnimeInfoCard = drawAnimeInfoCard;
|
|
@@ -132,6 +133,21 @@ function printBanner(title, subtitle) {
|
|
|
132
133
|
console.log(borderLine(width, theme_1.glyphs.bottomLeft, theme_1.glyphs.bottomRight));
|
|
133
134
|
console.log('');
|
|
134
135
|
}
|
|
136
|
+
function printUpdateNotice(currentVersion, latestVersion, packageName) {
|
|
137
|
+
const width = (0, text_1.terminalWidth)(86, 62);
|
|
138
|
+
const innerWidth = width - 4;
|
|
139
|
+
const title = `${theme_1.uiText.warning('Cập nhật mới')} ${theme_1.uiText.danger(currentVersion)} ${theme_1.uiText.subtle('->')} ${theme_1.uiText.success(latestVersion)}`;
|
|
140
|
+
const command = `npm i -g ${packageName}@latest`;
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log(borderLine(width, theme_1.glyphs.topLeft, theme_1.glyphs.topRight, true));
|
|
143
|
+
console.log(boxedLine(`${theme_1.uiText.brand('NekoStream')} ${theme_1.uiText.subtle(theme_1.glyphs.dot)} ${title}`, width, true));
|
|
144
|
+
console.log(borderLine(width, theme_1.glyphs.teeLeft, theme_1.glyphs.teeRight));
|
|
145
|
+
for (const line of (0, text_1.wrapText)('Vui lòng cập nhật CLI để tiếp tục sử dụng ứng dụng.', innerWidth)) {
|
|
146
|
+
console.log(boxedLine(theme_1.uiText.value(line), width));
|
|
147
|
+
}
|
|
148
|
+
console.log(boxedLine(`${theme_1.uiText.label('Lệnh')} ${theme_1.uiText.focus(command)}`, width));
|
|
149
|
+
console.log(`${borderLine(width, theme_1.glyphs.bottomLeft, theme_1.glyphs.bottomRight)}\n`);
|
|
150
|
+
}
|
|
135
151
|
function printStatusStrip(items) {
|
|
136
152
|
const width = (0, text_1.terminalWidth)(92, 58);
|
|
137
153
|
const innerWidth = width - 4;
|