Chore: maintainance
Some checks are pending
Build / Build (push) Waiting to run
Build / Diff output (push) Blocked by required conditions
Build / Deploy to Cloudflare Pages (push) Blocked by required conditions
Build / Deploy to GitHub and GitLab (push) Blocked by required conditions

This commit is contained in:
SukkaW
2025-02-07 17:52:36 +08:00
parent 6a7f7cc5e8
commit d354c5e988
252 changed files with 21086 additions and 124 deletions

View File

@@ -0,0 +1,46 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const appendArrayInPlace=require('../../_virtual/append-array-in-place.cjs');var hasRequiredAppendArrayInPlace;
function requireAppendArrayInPlace () {
if (hasRequiredAppendArrayInPlace) return appendArrayInPlace.__exports;
hasRequiredAppendArrayInPlace = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
appendArrayInPlace: function() {
return appendArrayInPlace;
},
appendArrayInPlaceCurried: function() {
return appendArrayInPlaceCurried;
}
});
const MAX_BLOCK_SIZE = 65535; // max parameter array size for use in Webkit
function appendArrayInPlace(dest, source) {
let offset = 0;
let itemsLeft = source.length;
if (itemsLeft <= MAX_BLOCK_SIZE) {
// eslint-disable-next-line prefer-spread -- performance
dest.push.apply(dest, source);
} else {
while(itemsLeft > 0){
const pushCount = itemsLeft > MAX_BLOCK_SIZE ? MAX_BLOCK_SIZE : itemsLeft;
const subSource = source.slice(offset, offset + pushCount);
// eslint-disable-next-line prefer-spread -- performance
dest.push.apply(dest, subSource);
itemsLeft -= pushCount;
offset += pushCount;
}
}
return dest;
}
const appendArrayInPlaceCurried = (dest)=>(source)=>appendArrayInPlace(dest, source);
} (appendArrayInPlace.__exports));
return appendArrayInPlace.__exports;
}exports.__require=requireAppendArrayInPlace;

View File

@@ -0,0 +1,134 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const cacheFilesystem=require('../../_virtual/cache-filesystem.cjs'),require$$0=require('better-sqlite3'),require$$1$1=require('node:os'),require$$0$2=require('node:path'),require$$1=require('node:fs'),require$$0$1=require('picocolors'),require$$3=require('foxts/fast-string-array-join'),require$$6=require('node:perf_hooks');var hasRequiredCacheFilesystem;
function requireCacheFilesystem () {
if (hasRequiredCacheFilesystem) return cacheFilesystem.__exports;
hasRequiredCacheFilesystem = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
Cache: function() {
return Cache;
},
deserializeArray: function() {
return deserializeArray;
},
serializeArray: function() {
return serializeArray;
}
});
const _bettersqlite3 = /*#__PURE__*/ _interop_require_default(require$$0);
const _nodeos = /*#__PURE__*/ _interop_require_default(require$$1$1);
const _nodepath = /*#__PURE__*/ _interop_require_default(require$$0$2);
const _nodefs = require$$1;
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0$1);
const _faststringarrayjoin = require$$3;
const _nodeperf_hooks = require$$6;
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class Cache {
db;
/** Time before deletion */ tbd = 60 * 1000;
/** SQLite file path */ cachePath;
/** Table name */ tableName;
type;
statement;
constructor({ cachePath = _nodepath.default.join(_nodeos.default.tmpdir() || '/tmp', 'hdc'), tbd, tableName = 'cache', type } = {}){
const start = _nodeperf_hooks.performance.now();
this.cachePath = cachePath;
(0, _nodefs.mkdirSync)(this.cachePath, {
recursive: true
});
if (tbd != null) this.tbd = tbd;
this.tableName = tableName;
if (type) {
this.type = type;
} else {
// @ts-expect-error -- fallback type
this.type = 'string';
}
const db = (0, _bettersqlite3.default)(_nodepath.default.join(this.cachePath, 'cache.db'));
db.pragma('journal_mode = WAL');
db.pragma('synchronous = normal');
db.pragma('temp_store = memory');
db.pragma('optimize');
db.prepare(`CREATE TABLE IF NOT EXISTS ${this.tableName} (key TEXT PRIMARY KEY, value ${this.type === 'string' ? 'TEXT' : 'BLOB'}, ttl REAL NOT NULL);`).run();
db.prepare(`CREATE INDEX IF NOT EXISTS cache_ttl ON ${this.tableName} (ttl);`).run();
/** cache stmt */ this.statement = {
updateTtl: db.prepare(`UPDATE ${this.tableName} SET ttl = ? WHERE key = ?;`),
del: db.prepare(`DELETE FROM ${this.tableName} WHERE key = ?`),
insert: db.prepare(`INSERT INTO ${this.tableName} (key, value, ttl) VALUES ($key, $value, $valid) ON CONFLICT(key) DO UPDATE SET value = $value, ttl = $valid`),
get: db.prepare(`SELECT ttl, value FROM ${this.tableName} WHERE key = ? LIMIT 1`)
};
const date = new Date();
// perform purge on startup
// ttl + tbd < now => ttl < now - tbd
const now = date.getTime() - this.tbd;
db.prepare(`DELETE FROM ${this.tableName} WHERE ttl < ?`).run(now);
this.db = db;
const dateString = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
const lastVaccum = this.get('__LAST_VACUUM');
if (lastVaccum === undefined || lastVaccum !== dateString && date.getUTCDay() === 6) {
console.log(_picocolors.default.magenta('[cache] vacuuming'));
this.set('__LAST_VACUUM', dateString, 10 * 365 * 60 * 60 * 24 * 1000);
this.db.exec('VACUUM;');
}
const end = _nodeperf_hooks.performance.now();
console.log(`${_picocolors.default.gray(`[${(end - start).toFixed(3)}ns]`)} cache initialized from ${this.tableName} @ ${this.cachePath}`);
}
set(key, value, ttl = 60 * 1000) {
const valid = Date.now() + ttl;
this.statement.insert.run({
$key: key,
key,
$value: value,
value,
$valid: valid,
valid
});
}
get(key) {
const rv = this.statement.get.get(key);
if (!rv) return null;
if (rv.ttl < Date.now()) {
this.del(key);
return null;
}
if (rv.value == null) {
this.del(key);
return null;
}
return rv.value;
}
updateTtl(key, ttl) {
this.statement.updateTtl.run(Date.now() + ttl, key);
}
del(key) {
this.statement.del.run(key);
}
destroy() {
this.db.close();
}
deleteTable(tableName) {
this.db.exec(`DROP TABLE IF EXISTS ${tableName};`);
}
}
// process.on('exit', () => {
// fsFetchCache.destroy();
// });
const separator = '\u0000';
const serializeArray = (arr)=>(0, _faststringarrayjoin.fastStringArrayJoin)(arr, separator);
const deserializeArray = (str)=>str.split(separator);
} (cacheFilesystem.__exports));
return cacheFilesystem.__exports;
}exports.__require=requireCacheFilesystem;

View File

@@ -0,0 +1,114 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const createFile=require('../../_virtual/create-file.cjs'),require$$0=require('foxts/async-write-to-stream'),require$$3=require('foxts/fast-string-array-join'),require$$1=require('node:fs'),require$$0$1=require('picocolors'),fetchTextByLine=require('./fetch-text-by-line.cjs'),misc=require('./misc.cjs');var hasRequiredCreateFile;
function requireCreateFile () {
if (hasRequiredCreateFile) return createFile.__exports;
hasRequiredCreateFile = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
compareAndWriteFile: function() {
return compareAndWriteFile;
},
fileEqual: function() {
return fileEqual;
}
});
const _asyncwritetostream = require$$0;
const _faststringarrayjoin = require$$3;
const _nodefs = /*#__PURE__*/ _interop_require_default(require$$1);
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0$1);
const _fetchtextbyline = /*@__PURE__*/ fetchTextByLine.__require();
const _misc = /*@__PURE__*/ misc.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
async function fileEqual(linesA, source) {
if (linesA.length === 0) {
return false;
}
const linesABound = linesA.length - 1;
let index = -1;
for await (const lineB of source){
index++;
if (index > linesABound) {
return index === linesA.length && lineB.length === 0;
}
const lineA = linesA[index];
if (lineA.length === 0) {
if (lineB.length === 0) {
continue;
}
// lineA is empty but lineB is not
return false;
}
// now lineA can not be empty
if (lineB.length === 0) {
// lineB is empty but lineA is not
return false;
}
// now both lines can not be empty
const firstCharA = lineA.charCodeAt(0);
const firstCharB = lineB.charCodeAt(0);
if (firstCharA !== firstCharB) {
return false;
}
// now firstCharA is equal to firstCharB, we only need to check the first char
if (firstCharA === 35 /* # */ ) {
continue;
}
// adguard conf
if (firstCharA === 33 /* ! */ ) {
continue;
}
if (firstCharA === 47 /* / */ && lineA[1] === '/' && lineB[1] === '/' && lineA[3] === '#' && lineB[3] === '#') {
continue;
}
if (lineA !== lineB) {
return false;
}
}
// The file becomes larger
return !(index < linesABound);
}
async function compareAndWriteFile(span, linesA, filePath) {
const linesALen = linesA.length;
const isEqual = await span.traceChildAsync(`compare ${filePath}`, async ()=>{
if (_nodefs.default.existsSync(filePath)) {
return fileEqual(linesA, (0, _fetchtextbyline.readFileByLine)(filePath));
}
console.log(`${filePath} does not exists, writing...`);
return false;
});
if (isEqual) {
console.log(_picocolors.default.gray(_picocolors.default.dim(`same content, bail out writing: ${filePath}`)));
return;
}
await span.traceChildAsync(`writing ${filePath}`, async ()=>{
// The default highwater mark is normally 16384,
// So we make sure direct write to file if the content is
// most likely less than 500 lines
if (linesALen < 500) {
return (0, _misc.writeFile)(filePath, (0, _faststringarrayjoin.fastStringArrayJoin)(linesA, '\n') + '\n');
}
const writeStream = _nodefs.default.createWriteStream(filePath);
for(let i = 0; i < linesALen; i++){
const p = (0, _asyncwritetostream.asyncWriteToStream)(writeStream, linesA[i] + '\n');
// eslint-disable-next-line no-await-in-loop -- stream high water mark
if (p) await p;
}
writeStream.end();
});
}
} (createFile.__exports));
return createFile.__exports;
}exports.__require=requireCreateFile;

View File

@@ -0,0 +1,81 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const fetchAssets=require('../../_virtual/fetch-assets.cjs'),require$$0=require('picocolors'),fetchRetry=require('./fetch-retry.cjs'),require$$2=require('foxts/wait'),require$$6=require('foxts/guard'),textLineTransformStream=require('./text-line-transform-stream.cjs'),processLine=require('./process-line.cjs');var hasRequiredFetchAssets;
function requireFetchAssets () {
if (hasRequiredFetchAssets) return fetchAssets.__exports;
hasRequiredFetchAssets = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
CustomAbortError: function() {
return CustomAbortError;
},
fetchAssets: function() {
return fetchAssets;
}
});
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0);
const _fetchretry = /*@__PURE__*/ fetchRetry.__require();
const _wait = require$$2;
const _guard = require$$6;
const _textlinetransformstream = /*@__PURE__*/ textLineTransformStream.__require();
const _processline = /*@__PURE__*/ processLine.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class CustomAbortError extends Error {
name = 'AbortError';
digest = 'AbortError';
}
const reusedCustomAbortError = new CustomAbortError();
async function fetchAssets(url, fallbackUrls, processLine = false) {
const controller = new AbortController();
const createFetchFallbackPromise = async (url, index)=>{
if (index >= 0) {
// Most assets can be downloaded within 250ms. To avoid wasting bandwidth, we will wait for 500ms before downloading from the fallback URL.
try {
await (0, _wait.waitWithAbort)(50 + (index + 1) * 100, controller.signal);
} catch {
console.log(_picocolors.default.gray('[fetch cancelled early]'), _picocolors.default.gray(url));
throw reusedCustomAbortError;
}
}
if (controller.signal.aborted) {
console.log(_picocolors.default.gray('[fetch cancelled]'), _picocolors.default.gray(url));
throw reusedCustomAbortError;
}
const res = await (0, _fetchretry.$$fetch)(url, {
signal: controller.signal,
..._fetchretry.defaultRequestInit
});
let stream = (0, _guard.nullthrow)(res.body).pipeThrough(new TextDecoderStream()).pipeThrough(new _textlinetransformstream.TextLineStream());
if (processLine) {
stream = stream.pipeThrough(new _processline.ProcessLineStream());
}
const arr = await Array.fromAsync(stream);
if (arr.length < 1) {
throw new _fetchretry.ResponseError(res, url, 'empty response w/o 304');
}
controller.abort();
return arr;
};
if (!fallbackUrls || fallbackUrls.length === 0) {
return createFetchFallbackPromise(url, -1);
}
return Promise.any([
createFetchFallbackPromise(url, -1),
...fallbackUrls.map(createFetchFallbackPromise)
]);
}
} (fetchAssets.__exports));
return fetchAssets.__exports;
}exports.__require=requireFetchAssets;

View File

@@ -0,0 +1,235 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const fetchRetry=require('../../_virtual/fetch-retry.cjs'),require$$0$1=require('picocolors'),require$$1=require('undici'),require$$2=require('undici-cache-store-better-sqlite3'),require$$1$2=require('node:util'),require$$0=require('node:path'),require$$1$1=require('node:fs'),dir=require('../constants/dir.cjs');var hasRequiredFetchRetry;
function requireFetchRetry () {
if (hasRequiredFetchRetry) return fetchRetry.__exports;
hasRequiredFetchRetry = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
$$fetch: function() {
return $$fetch;
},
ResponseError: function() {
return ResponseError;
},
defaultRequestInit: function() {
return defaultRequestInit;
},
requestWithLog: function() {
return requestWithLog;
}
});
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0$1);
const _undici = /*#__PURE__*/ _interop_require_wildcard(require$$1);
const _undicicachestorebettersqlite3 = require$$2;
const _nodeutil = require$$1$2;
const _nodepath = /*#__PURE__*/ _interop_require_default(require$$0);
const _nodefs = /*#__PURE__*/ _interop_require_default(require$$1$1);
const _dir = /*@__PURE__*/ dir.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
if (!_nodefs.default.existsSync(_dir.CACHE_DIR)) {
_nodefs.default.mkdirSync(_dir.CACHE_DIR, {
recursive: true
});
}
const agent = new _undici.Agent({
allowH2: true
});
(0, _undici.setGlobalDispatcher)(agent.compose(_undici.interceptors.dns({
// disable IPv6
dualStack: false,
affinity: 4
}), _undici.interceptors.retry({
maxRetries: 5,
minTimeout: 500,
maxTimeout: 10 * 1000,
// TODO: this part of code is only for allow more errors to be retried by default
// This should be removed once https://github.com/nodejs/undici/issues/3728 is implemented
retry (err, { state, opts }, cb) {
const errorCode = 'code' in err ? err.code : undefined;
// Any code that is not a Undici's originated and allowed to retry
if (errorCode === 'ERR_UNESCAPED_CHARACTERS' || err.message === 'Request path contains unescaped characters' || err.name === 'AbortError') {
return cb(err);
}
const statusCode = 'statusCode' in err && typeof err.statusCode === 'number' ? err.statusCode : null;
// bail out if the status code matches one of the following
if (statusCode != null && (statusCode === 401 // Unauthorized, should check credentials instead of retrying
|| statusCode === 403 // Forbidden, should check permissions instead of retrying
|| statusCode === 404 // Not Found, should check URL instead of retrying
|| statusCode === 405 // Method Not Allowed, should check method instead of retrying
)) {
return cb(err);
}
// if (errorCode === 'UND_ERR_REQ_RETRY') {
// return cb(err);
// }
const { maxRetries = 5, minTimeout = 500, maxTimeout = 10 * 1000, timeoutFactor = 2, methods = [
'GET',
'HEAD',
'OPTIONS',
'PUT',
'DELETE',
'TRACE'
] } = opts.retryOptions || {};
// If we reached the max number of retries
if (state.counter > maxRetries) {
return cb(err);
}
// If a set of method are provided and the current method is not in the list
if (Array.isArray(methods) && !methods.includes(opts.method)) {
return cb(err);
}
const headers = 'headers' in err && typeof err.headers === 'object' ? err.headers : undefined;
const retryAfterHeader = headers?.['retry-after'];
let retryAfter = -1;
if (retryAfterHeader) {
retryAfter = Number(retryAfterHeader);
retryAfter = Number.isNaN(retryAfter) ? calculateRetryAfterHeader(retryAfterHeader) : retryAfter * 1e3; // Retry-After is in seconds
}
const retryTimeout = retryAfter > 0 ? Math.min(retryAfter, maxTimeout) : Math.min(minTimeout * timeoutFactor ** (state.counter - 1), maxTimeout);
console.log('[fetch retry]', 'schedule retry', {
statusCode,
retryTimeout,
errorCode,
url: opts.origin
});
// eslint-disable-next-line sukka/prefer-timer-id -- won't leak
setTimeout(()=>cb(null), retryTimeout);
}
}), _undici.interceptors.redirect({
maxRedirections: 5
}), _undici.interceptors.cache({
store: new _undicicachestorebettersqlite3.BetterSqlite3CacheStore({
location: _nodepath.default.join(_dir.CACHE_DIR, 'undici-better-sqlite3-cache-store.db'),
maxEntrySize: 1024 * 1024 * 100 // 100 MiB
})
})));
function calculateRetryAfterHeader(retryAfter) {
const current = Date.now();
return new Date(retryAfter).getTime() - current;
}
class ResponseError extends Error {
res;
url;
code;
statusCode;
constructor(res, url, ...args){
const statusCode = 'statusCode' in res ? res.statusCode : res.status;
super('HTTP ' + statusCode + ' ' + args.map((_)=>(0, _nodeutil.inspect)(_)).join(' ')), this.res = res, this.url = url;
if ('captureStackTrace' in Error) {
Error.captureStackTrace(this, ResponseError);
}
// eslint-disable-next-line sukka/unicorn/custom-error-definition -- deliberatly use previous name
this.name = this.constructor.name;
this.res = res;
this.code = statusCode;
this.statusCode = statusCode;
}
}
const defaultRequestInit = {
headers: {
'User-Agent': 'curl/8.9.1 (https://github.com/SukkaW/Surge)'
}
};
async function $$fetch(url, init) {
try {
const res = await _undici.default.fetch(url, init);
if (res.status >= 400) {
throw new ResponseError(res, url);
}
if (!(res.status >= 200 && res.status <= 299) && res.status !== 304) {
throw new ResponseError(res, url);
}
return res;
} catch (err) {
if (typeof err === 'object' && err !== null && 'name' in err) {
if (err.name === 'AbortError' || 'digest' in err && err.digest === 'AbortError') {
console.log(_picocolors.default.gray('[fetch abort]'), url);
}
} else {
console.log(_picocolors.default.gray('[fetch fail]'), url, {
name: err.name
}, err);
}
throw err;
}
}
async function requestWithLog(url, opt) {
try {
const res = await _undici.default.request(url, opt);
if (res.statusCode >= 400) {
throw new ResponseError(res, url);
}
if (!(res.statusCode >= 200 && res.statusCode <= 299) && res.statusCode !== 304) {
throw new ResponseError(res, url);
}
return res;
} catch (err) {
if (typeof err === 'object' && err !== null && 'name' in err) {
if (err.name === 'AbortError' || 'digest' in err && err.digest === 'AbortError') {
console.log(_picocolors.default.gray('[fetch abort]'), url);
}
} else {
console.log(_picocolors.default.gray('[fetch fail]'), url, {
name: err.name
}, err);
}
throw err;
}
}
} (fetchRetry.__exports));
return fetchRetry.__exports;
}exports.__require=requireFetchRetry;

View File

@@ -0,0 +1,79 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const fetchTextByLine=require('../../_virtual/fetch-text-by-line.cjs'),require$$1=require('node:fs'),require$$1$1=require('node:readline'),textLineTransformStream=require('./text-line-transform-stream.cjs'),require$$0=require('node:stream/web'),processLine=require('./process-line.cjs'),fetchRetry=require('./fetch-retry.cjs'),require$$6=require('foxts/guard');var hasRequiredFetchTextByLine;
function requireFetchTextByLine () {
if (hasRequiredFetchTextByLine) return fetchTextByLine.__exports;
hasRequiredFetchTextByLine = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createReadlineInterfaceFromResponse: function() {
return createReadlineInterfaceFromResponse;
},
fetchRemoteTextByLine: function() {
return fetchRemoteTextByLine;
},
readFileByLine: function() {
return readFileByLine;
},
readFileIntoProcessedArray: function() {
return readFileIntoProcessedArray;
}
});
const _nodefs = /*#__PURE__*/ _interop_require_default(require$$1);
const _nodereadline = /*#__PURE__*/ _interop_require_default(require$$1$1);
const _textlinetransformstream = /*@__PURE__*/ textLineTransformStream.__require();
const _web = require$$0;
const _processline = /*@__PURE__*/ processLine.__require();
const _fetchretry = /*@__PURE__*/ fetchRetry.__require();
const _guard = require$$6;
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function readFileByLine(file) {
return _nodereadline.default.createInterface({
input: _nodefs.default.createReadStream(file /* , { encoding: 'utf-8' } */ ),
crlfDelay: Infinity
});
}
const createReadlineInterfaceFromResponse = (resp, processLine = false)=>{
(0, _guard.invariant)(resp.body, 'Failed to fetch remote text');
if ('bodyUsed' in resp && resp.bodyUsed) {
throw new Error('Body has already been consumed.');
}
let webStream;
if ('pipeThrough' in resp.body) {
webStream = resp.body;
} else {
throw new TypeError('Invalid response body!');
}
const resultStream = webStream.pipeThrough(new _web.TextDecoderStream()).pipeThrough(new _textlinetransformstream.TextLineStream());
if (processLine) {
return resultStream.pipeThrough(new _processline.ProcessLineStream());
}
return resultStream;
};
function fetchRemoteTextByLine(url, processLine = false) {
return (0, _fetchretry.$$fetch)(url).then((resp)=>createReadlineInterfaceFromResponse(resp, processLine));
}
async function readFileIntoProcessedArray(file/* | FileHandle */ ) {
const results = [];
for await (const line of readFileByLine(file)){
if ((0, _processline.processLine)(line)) {
results.push(line);
}
}
return results;
}
} (fetchTextByLine.__exports));
return fetchTextByLine.__exports;
}exports.__require=requireFetchTextByLine;

View File

@@ -0,0 +1,89 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const fsMemo=require('../../_virtual/fs-memo.cjs'),require$$0$1=require('node:path'),require$$11=require('ci-info'),require$$0=require('picocolors'),cacheFilesystem=require('./cache-filesystem.cjs'),require$$4=require('foxts/serialized-memo'),dir=require('../constants/dir.cjs');var hasRequiredFsMemo;
function requireFsMemo () {
if (hasRequiredFsMemo) return fsMemo.__exports;
hasRequiredFsMemo = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
cache: function() {
return cache;
},
cachedOnlyFail: function() {
return cachedOnlyFail;
}
});
const _nodepath = /*#__PURE__*/ _interop_require_default(require$$0$1);
const _ciinfo = require$$11;
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0);
const _cachefilesystem = /*@__PURE__*/ cacheFilesystem.__require();
const _serializedmemo = require$$4;
const _dir = /*@__PURE__*/ dir.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const fsMemoCache = new _cachefilesystem.Cache({
cachePath: _nodepath.default.join(_dir.ROOT_DIR, '.cache'),
tableName: 'fs_memo_cache'
});
const fsMemoCacheProvider = {
has (key) {
return fsMemoCache.get(key) !== null;
},
delete () {
// noop
},
get (key) {
return fsMemoCache.get(key) ?? undefined;
},
set (key, value, ttl) {
fsMemoCache.set(key, value, ttl);
},
updateTtl (key, ttl) {
fsMemoCache.updateTtl(key, ttl);
}
};
const TTL = _ciinfo.isCI ? 1.5 * 86400 * 1000 : 7 * 86400 * 1000;
const cache = (0, _serializedmemo.createMemoize)(fsMemoCacheProvider, {
defaultTtl: TTL,
onCacheMiss (key, { humanReadableName, isUseCachedIfFail }) {
const cacheName = _picocolors.default.gray(humanReadableName);
if (isUseCachedIfFail) {
console.log(_picocolors.default.red('[fail] and no cache, throwing'), cacheName);
} else {
console.log(_picocolors.default.yellow('[cache] miss'), cacheName);
}
},
onCacheUpdate (key, { humanReadableName, isUseCachedIfFail }) {
const cacheName = _picocolors.default.gray(humanReadableName);
if (isUseCachedIfFail) {
console.log(_picocolors.default.gray('[cache] update'), cacheName);
}
},
onCacheHit (key, { humanReadableName, isUseCachedIfFail }) {
const cacheName = _picocolors.default.gray(humanReadableName);
if (isUseCachedIfFail) {
console.log(_picocolors.default.yellow('[fail] try cache'), cacheName);
} else {
console.log(_picocolors.default.green('[cache] hit'), cacheName);
}
}
});
const cachedOnlyFail = (0, _serializedmemo.createMemoize)(fsMemoCacheProvider, {
defaultTtl: TTL,
onlyUseCachedIfFail: true
}); // export const cache = createCache(false);
// export const cachedOnlyFail = createCache(true);
} (fsMemo.__exports));
return fsMemo.__exports;
}exports.__require=requireFsMemo;

View File

@@ -0,0 +1,376 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const getPhishingDomains=require('../../_virtual/get-phishing-domains.cjs'),hosts=require('./parse-filter/hosts.cjs'),domainlists=require('./parse-filter/domainlists.cjs'),require$$5=require('tldts-experimental'),index=require('../trace/index.cjs'),appendArrayInPlace=require('./append-array-in-place.cjs'),rejectDataSource=require('../constants/reject-data-source.cjs'),looseTldtsOpt=require('../constants/loose-tldts-opt.cjs'),require$$0=require('picocolors'),require$$3=require('foxts/retrie'),cacheFilesystem=require('./cache-filesystem.cjs'),fsMemo=require('./fs-memo.cjs'),require$$11=require('ci-info');var hasRequiredGetPhishingDomains;
function requireGetPhishingDomains () {
if (hasRequiredGetPhishingDomains) return getPhishingDomains.__module.exports;
hasRequiredGetPhishingDomains = 1;
(function (module, exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
calcDomainAbuseScore: function() {
return calcDomainAbuseScore;
},
getPhishingDomains: function() {
return getPhishingDomains;
}
});
const _hosts = /*@__PURE__*/ hosts.__require();
const _domainlists = /*@__PURE__*/ domainlists.__require();
const _tldtsexperimental = /*#__PURE__*/ _interop_require_wildcard(require$$5);
const _trace = /*@__PURE__*/ index.__require();
const _appendarrayinplace = /*@__PURE__*/ appendArrayInPlace.__require();
const _rejectdatasource = /*@__PURE__*/ rejectDataSource.__require();
const _loosetldtsopt = /*@__PURE__*/ looseTldtsOpt.__require();
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0);
const _retrie = require$$3;
const _cachefilesystem = /*@__PURE__*/ cacheFilesystem.__require();
const _fsmemo = /*@__PURE__*/ fsMemo.__require();
const _ciinfo = require$$11;
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
const BLACK_TLD = new Set([
'accountant',
'art',
'autos',
'bar',
'beauty',
'bid',
'bio',
'biz',
'bond',
'business',
'buzz',
'cc',
'cf',
'cfd',
'click',
'cloud',
'club',
'cn',
'codes',
'co.uk',
'co.in',
'com.br',
'com.cn',
'com.pl',
'com.vn',
'cool',
'cricket',
'cyou',
'date',
'design',
'digital',
'download',
'faith',
'fit',
'fun',
'ga',
'gd',
'gives',
'gq',
'group',
'host',
'icu',
'id',
'info',
'ink',
'lat',
'life',
'live',
'link',
'loan',
'lol',
'ltd',
'me',
'men',
'ml',
'mobi',
'mom',
'monster',
'net.pl',
'one',
'online',
'party',
'pro',
'pl',
'pw',
'racing',
'rest',
'review',
'rf.gd',
'sa.com',
'sbs',
'science',
'shop',
'site',
'skin',
'space',
'store',
'stream',
'su',
'surf',
'tech',
'tk',
'tokyo',
'top',
'trade',
'vip',
'vn',
'webcam',
'website',
'win',
'xyz',
'za.com'
]);
const WHITELIST_MAIN_DOMAINS = new Set([
// 'w3s.link', // ipfs gateway
// 'dweb.link', // ipfs gateway
// 'nftstorage.link', // ipfs gateway
'fleek.cool',
'flk-ipfs.xyz',
'business.site',
'page.link',
// 'notion.site',
// 'vercel.app',
'gitbook.io',
'zendesk.com',
'ipfs.eth.aragon.network',
'wordpress.com'
]);
const leathalKeywords = (0, _retrie.createRetrieKeywordFilter)([
'vinted-',
'inpost-pl',
'vlnted-'
]);
const sensitiveKeywords = (0, _retrie.createRetrieKeywordFilter)([
'.amazon-',
'-amazon',
'fb-com',
'facebook-com',
'-facebook',
'facebook-',
'focebaak',
'.facebook.',
'metamask',
'www.apple',
'-coinbase',
'coinbase-',
'booking-com',
'booking.com-',
'booking-eu',
'vinted-',
'inpost-pl',
'login.microsoft',
'login-microsoft',
'microsoftonline',
'google.com-',
'minecraft',
'staemco',
'oferta'
]);
const lowKeywords = (0, _retrie.createRetrieKeywordFilter)([
'transactions-',
'payment',
'wallet',
'-transactions',
'-faceb',
'.faceb',
'facebook',
'virus-',
'icloud-',
'apple-',
'-roblox',
'-co-jp',
'customer.',
'customer-',
'.www-',
'.www.',
'.www2',
'instagram',
'microsof',
'passwordreset',
'.google-',
'recover',
'banking'
]);
const processPhihsingDomains = (0, _fsmemo.cache)(function processPhihsingDomains(domainArr) {
const domainCountMap = new Map();
const domainScoreMap = {};
let line = '';
let tld = '';
let apexDomain = '';
let subdomain = '';
// const set = new Set<string>();
// let duplicateCount = 0;
for(let i = 0, len = domainArr.length; i < len; i++){
line = domainArr[i];
// if (set.has(line)) {
// duplicateCount++;
// } else {
// set.add(line);
// }
const parsed = _tldtsexperimental.parse(line, _loosetldtsopt.loosTldOptWithPrivateDomains);
if (parsed.isPrivate) {
continue;
}
tld = parsed.publicSuffix;
apexDomain = parsed.domain;
if (!tld) {
console.log(_picocolors.default.yellow('[phishing domains] E0001'), 'missing tld', {
line,
tld
});
continue;
}
if (!apexDomain) {
console.log(_picocolors.default.yellow('[phishing domains] E0002'), 'missing domain', {
line,
apexDomain
});
continue;
}
domainCountMap.set(apexDomain, domainCountMap.has(apexDomain) ? domainCountMap.get(apexDomain) + 1 : 1);
if (!(apexDomain in domainScoreMap)) {
domainScoreMap[apexDomain] = 0;
if (BLACK_TLD.has(tld)) {
domainScoreMap[apexDomain] += 3;
} else if (tld.length > 6) {
domainScoreMap[apexDomain] += 2;
}
if (apexDomain.length >= 18) {
domainScoreMap[apexDomain] += 0.5;
}
}
subdomain = parsed.subdomain;
if (subdomain && !WHITELIST_MAIN_DOMAINS.has(apexDomain)) {
domainScoreMap[apexDomain] += calcDomainAbuseScore(subdomain, line);
}
}
domainCountMap.forEach((count, apexDomain)=>{
if (// !WHITELIST_MAIN_DOMAINS.has(apexDomain)
domainScoreMap[apexDomain] >= 24 || domainScoreMap[apexDomain] >= 16 && count >= 7 || domainScoreMap[apexDomain] >= 13 && count >= 11 || domainScoreMap[apexDomain] >= 5 && count >= 14 || domainScoreMap[apexDomain] >= 3 && count >= 21 || domainScoreMap[apexDomain] >= 1 && count >= 60) {
domainArr.push('.' + apexDomain);
}
});
// console.log({
// score: domainScoreMap['awicksin.com'],
// count: domainCountMap.get('awicksin.com')
// });
// console.log({ duplicateCount, domainArrLen: domainArr.length });
return domainArr;
}, {
serializer: _cachefilesystem.serializeArray,
deserializer: _cachefilesystem.deserializeArray,
temporaryBypass: !_ciinfo.isCI || _rejectdatasource.DEBUG_DOMAIN_TO_FIND !== null
});
const downloads = [
..._rejectdatasource.PHISHING_DOMAIN_LISTS_EXTRA.map((entry)=>(0, _domainlists.processDomainListsWithPreload)(...entry)),
..._rejectdatasource.PHISHING_HOSTS_EXTRA.map((entry)=>(0, _hosts.processHostsWithPreload)(...entry))
];
function getPhishingDomains(parentSpan) {
return parentSpan.traceChild('get phishing domains').traceAsyncFn(async (span)=>{
const domainArr = await span.traceChildAsync('download/parse/merge phishing domains', async (curSpan)=>{
const domainArr = [];
const domainGroups = await Promise.all(downloads.map((task)=>task(curSpan)));
domainGroups.forEach((0, _appendarrayinplace.appendArrayInPlaceCurried)(domainArr));
return domainArr;
});
return span.traceChildAsync('process phishing domain set', ()=>processPhihsingDomains(domainArr));
});
}
function calcDomainAbuseScore(subdomain, fullDomain = subdomain) {
if (leathalKeywords(fullDomain)) {
return 100;
}
let weight = 0;
const hitLowKeywords = lowKeywords(fullDomain);
const sensitiveKeywordsHit = sensitiveKeywords(fullDomain);
if (sensitiveKeywordsHit) {
weight += 10;
if (hitLowKeywords) {
weight += 6;
}
} else if (hitLowKeywords) {
weight += 1.7;
}
const subdomainLength = subdomain.length;
if (subdomainLength > 6) {
weight += 0.015;
if (subdomainLength > 13) {
weight += 0.2;
if (subdomainLength > 20) {
weight += 1;
if (subdomainLength > 30) {
weight += 5;
if (subdomainLength > 40) {
weight += 10;
}
}
}
if (subdomain.indexOf('.', 1) > 1) {
weight += 1;
}
}
}
return weight;
}
if (require.main === module) {
getPhishingDomains(_trace.dummySpan).catch(console.error).finally(()=>{
_trace.dummySpan.stop();
(0, _trace.printTraceResult)(_trace.dummySpan.traceResult);
});
}
} (getPhishingDomains.__module, getPhishingDomains.__module.exports));
return getPhishingDomains.__module.exports;
}exports.__require=requireGetPhishingDomains;

View File

@@ -0,0 +1,396 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const isDomainAlive=require('../../_virtual/is-domain-alive.cjs'),require$$5=require('tldts-experimental'),looseTldtsOpt=require('../constants/loose-tldts-opt.cjs'),require$$0=require('picocolors'),require$$3$1=require('dns2'),require$$4=require('async-retry'),require$$5$1=require('whoiser'),require$$3=require('foxts/retrie'),require$$1=require('node:process');var hasRequiredIsDomainAlive;
function requireIsDomainAlive () {
if (hasRequiredIsDomainAlive) return isDomainAlive.__exports;
hasRequiredIsDomainAlive = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
isDomainAlive: function() {
return isDomainAlive;
},
keyedAsyncMutexWithQueue: function() {
return keyedAsyncMutexWithQueue;
},
noWhois: function() {
return noWhois;
}
});
const _tldtsexperimental = /*#__PURE__*/ _interop_require_default(require$$5);
const _loosetldtsopt = /*@__PURE__*/ looseTldtsOpt.__require();
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0);
const _dns2 = /*#__PURE__*/ _interop_require_default(require$$3$1);
const _asyncretry = /*#__PURE__*/ _interop_require_default(require$$4);
const _whoiser = /*#__PURE__*/ _interop_require_wildcard(require$$5$1);
const _retrie = require$$3;
const _nodeprocess = /*#__PURE__*/ _interop_require_default(require$$1);
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
const mutex = new Map();
function keyedAsyncMutexWithQueue(key, fn) {
if (mutex.has(key)) {
return mutex.get(key);
}
const promise = fn();
mutex.set(key, promise);
return promise;
}
class DnsError extends Error {
message;
server;
name;
constructor(message, server){
super(message), this.message = message, this.server = server, this.name = 'DnsError';
}
}
const dohServers = [
'8.8.8.8',
'8.8.4.4',
'1.0.0.1',
'1.1.1.1',
'162.159.36.1',
'162.159.46.1',
'101.101.101.101',
'185.222.222.222',
'45.11.45.11',
'dns10.quad9.net',
'doh.sandbox.opendns.com',
'unfiltered.adguard-dns.com',
// '0ms.dev', // Proxy Cloudflare
// '76.76.2.0', // ControlD unfiltered, path not /dns-query
// '76.76.10.0', // ControlD unfiltered, path not /dns-query
// 'dns.bebasid.com', // BebasID, path not /dns-query but /unfiltered
// '193.110.81.0', // dns0.eu
// '185.253.5.0', // dns0.eu
// 'zero.dns0.eu',
'dns.nextdns.io',
'anycast.dns.nextdns.io',
'wikimedia-dns.org',
// 'ordns.he.net',
// 'dns.mullvad.net',
'basic.rethinkdns.com',
'198.54.117.10' // NameCheap DNS, supports DoT, DoH, UDP53
].map((dns)=>[
dns,
_dns2.default.DOHClient({
dns,
http: false
})
]);
const domesticDohServers = [
'223.5.5.5',
'223.6.6.6',
'120.53.53.53',
'1.12.12.12'
].map((dns)=>[
dns,
_dns2.default.DOHClient({
dns,
http: false
})
]);
function createResolve(server) {
return async (...args)=>{
try {
return await (0, _asyncretry.default)(async ()=>{
const [dohServer, dohClient] = server[Math.floor(Math.random() * server.length)];
try {
return {
...await dohClient(...args),
dns: dohServer
};
} catch (e) {
// console.error(e);
throw new DnsError(e.message, dohServer);
}
}, {
retries: 5
});
} catch (e) {
console.log('[doh error]', ...args, e);
throw e;
}
};
}
const resolve = createResolve(dohServers);
const domesticResolve = createResolve(domesticDohServers);
async function getWhois(domain) {
return (0, _asyncretry.default)(()=>_whoiser.domain(domain, {
raw: true
}), {
retries: 5
});
}
const domainAliveMap = new Map();
function onDomainAlive(domain) {
domainAliveMap.set(domain, true);
return [
domain,
true
];
}
function onDomainDead(domain) {
domainAliveMap.set(domain, false);
return [
domain,
false
];
}
async function isDomainAlive(domain, isSuffix) {
if (domainAliveMap.has(domain)) {
return [
domain,
domainAliveMap.get(domain)
];
}
const apexDomain = _tldtsexperimental.default.getDomain(domain, _loosetldtsopt.looseTldtsOpt);
if (!apexDomain) {
console.log(_picocolors.default.gray('[domain invalid]'), _picocolors.default.gray('no apex domain'), {
domain
});
return onDomainAlive(domain);
}
const apexDomainAlive = await keyedAsyncMutexWithQueue(apexDomain, ()=>isApexDomainAlive(apexDomain));
if (isSuffix) {
return apexDomainAlive;
}
if (!apexDomainAlive[1]) {
return apexDomainAlive;
}
const $domain = domain[0] === '.' ? domain.slice(1) : domain;
const aDns = [];
const aaaaDns = [];
// test 2 times before make sure record is empty
for(let i = 0; i < 2; i++){
// eslint-disable-next-line no-await-in-loop -- sequential
const aRecords = await resolve($domain, 'A');
if (aRecords.answers.length > 0) {
return onDomainAlive(domain);
}
aDns.push(aRecords.dns);
}
for(let i = 0; i < 2; i++){
// eslint-disable-next-line no-await-in-loop -- sequential
const aaaaRecords = await resolve($domain, 'AAAA');
if (aaaaRecords.answers.length > 0) {
return onDomainAlive(domain);
}
aaaaDns.push(aaaaRecords.dns);
}
// only then, let's test once with domesticDohServers
const aRecords = await domesticResolve($domain, 'A');
if (aRecords.answers.length > 0) {
return onDomainAlive(domain);
}
aDns.push(aRecords.dns);
const aaaaRecords = await domesticResolve($domain, 'AAAA');
if (aaaaRecords.answers.length > 0) {
return onDomainAlive(domain);
}
aaaaDns.push(aaaaRecords.dns);
console.log(_picocolors.default.red('[domain dead]'), 'no A/AAAA records', {
domain,
a: aDns,
aaaa: aaaaDns
});
return onDomainDead($domain);
}
const apexDomainNsResolvePromiseMap = new Map();
async function isApexDomainAlive(apexDomain) {
if (domainAliveMap.has(apexDomain)) {
return [
apexDomain,
domainAliveMap.get(apexDomain)
];
}
let resp;
if (apexDomainNsResolvePromiseMap.has(apexDomain)) {
resp = await apexDomainNsResolvePromiseMap.get(apexDomain);
} else {
const promise = resolve(apexDomain, 'NS');
apexDomainNsResolvePromiseMap.set(apexDomain, promise);
resp = await promise;
}
if (resp.answers.length > 0) {
return onDomainAlive(apexDomain);
}
let whois;
try {
whois = await getWhois(apexDomain);
} catch (e) {
console.log(_picocolors.default.red('[whois error]'), {
domain: apexDomain
}, e);
return onDomainAlive(apexDomain);
}
if (_nodeprocess.default.env.DEBUG) {
console.log(JSON.stringify(whois, null, 2));
}
const whoisError = noWhois(whois);
if (!whoisError) {
console.log(_picocolors.default.gray('[domain alive]'), _picocolors.default.gray('whois found'), {
domain: apexDomain
});
return onDomainAlive(apexDomain);
}
console.log(_picocolors.default.red('[domain dead]'), 'whois not found', {
domain: apexDomain,
err: whoisError
});
return onDomainDead(apexDomain);
}
// TODO: this is a workaround for https://github.com/LayeredStudio/whoiser/issues/117
const whoisNotFoundKeywordTest = (0, _retrie.createRetrieKeywordFilter)([
'no match for',
'does not exist',
'not found',
'no found',
'no entries',
'no data found',
'is available for registration',
'currently available for application',
'no matching record',
'no information available about domain name',
'not been registered',
'no match!!',
'status: available',
' is free',
'no object found',
'nothing found',
'status: free',
'pendingdelete',
' has been blocked by '
]);
function noWhois(whois) {
let empty = true;
for(const key in whois){
if (Object.hasOwn(whois, key)) {
empty = false;
// if (key === 'error') {
// // if (
// // (typeof whois.error === 'string' && whois.error)
// // || (Array.isArray(whois.error) && whois.error.length > 0)
// // ) {
// // console.error(whois);
// // return true;
// // }
// continue;
// }
// if (key === 'text') {
// if (Array.isArray(whois.text)) {
// for (const value of whois.text) {
// if (whoisNotFoundKeywordTest(value.toLowerCase())) {
// return value;
// }
// }
// }
// continue;
// }
// if (key === 'Name Server') {
// // if (Array.isArray(whois[key]) && whois[key].length === 0) {
// // return false;
// // }
// continue;
// }
// if (key === 'Domain Status') {
// if (Array.isArray(whois[key])) {
// for (const status of whois[key]) {
// if (status === 'free' || status === 'AVAILABLE') {
// return key + ': ' + status;
// }
// if (whoisNotFoundKeywordTest(status.toLowerCase())) {
// return key + ': ' + status;
// }
// }
// }
// continue;
// }
// if (typeof whois[key] === 'string' && whois[key]) {
// if (whoisNotFoundKeywordTest(whois[key].toLowerCase())) {
// return key + ': ' + whois[key];
// }
// continue;
// }
if (key === '__raw' && typeof whois.__raw === 'string') {
const lines = whois.__raw.trim().toLowerCase().replaceAll(/[\t ]+/g, ' ').split(/\r?\n/);
if (_nodeprocess.default.env.DEBUG) {
console.log({
lines
});
}
for (const line of lines){
if (whoisNotFoundKeywordTest(line)) {
return line;
}
}
continue;
}
if (typeof whois[key] === 'object' && !Array.isArray(whois[key])) {
const tmp = noWhois(whois[key]);
if (tmp) {
return tmp;
}
continue;
}
}
}
if (empty) {
return 'whois is empty';
}
return null;
}
} (isDomainAlive.__exports));
return isDomainAlive.__exports;
}exports.__require=requireIsDomainAlive;

View File

@@ -0,0 +1,35 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const memoPromise=require('../../_virtual/memo-promise.cjs');var hasRequiredMemoPromise;
function requireMemoPromise () {
if (hasRequiredMemoPromise) return memoPromise.__exports;
hasRequiredMemoPromise = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "createMemoizedPromise", {
enumerable: true,
get: function() {
return createMemoizedPromise;
}
});
const notError = Symbol('notError');
function createMemoizedPromise(fn, /** whether to create promise immediately or only create after first access */ preload = true) {
let error = notError;
let promise = preload ? fn().catch((e)=>{
// Here we record the error so that we can throw it later when the function is called
error = e;
// Here we make sure the Promise still returns the never type
throw e;
}) : null;
return ()=>{
if (error !== notError) {
return Promise.reject(error);
}
promise ??= fn();
return promise;
};
}
} (memoPromise.__exports));
return memoPromise.__exports;
}exports.__require=requireMemoPromise;

122
Dist/Build/lib/misc.cjs Normal file
View File

@@ -0,0 +1,122 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const misc=require('../../_virtual/misc.cjs'),require$$0=require('node:path'),require$$1=require('node:fs'),require$$2=require('node:fs/promises');var hasRequiredMisc;
function requireMisc () {
if (hasRequiredMisc) return misc.__exports;
hasRequiredMisc = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
fastIpVersion: function() {
return fastIpVersion;
},
fastStringCompare: function() {
return fastStringCompare;
},
isDirectoryEmptySync: function() {
return isDirectoryEmptySync;
},
mkdirp: function() {
return mkdirp;
},
notSupported: function() {
return notSupported;
},
removeFiles: function() {
return removeFiles;
},
withBannerArray: function() {
return withBannerArray;
},
withIdentityContent: function() {
return withIdentityContent;
},
writeFile: function() {
return writeFile;
}
});
const _nodepath = require$$0;
const _nodefs = /*#__PURE__*/ _interop_require_default(require$$1);
const _promises = /*#__PURE__*/ _interop_require_default(require$$2);
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function fastStringCompare(a, b) {
const lenA = a.length;
const lenB = b.length;
const minLen = lenA < lenB ? lenA : lenB;
for(let i = 0; i < minLen; ++i){
const ca = a.charCodeAt(i);
const cb = b.charCodeAt(i);
if (ca > cb) return 1;
if (ca < cb) return -1;
}
if (lenA === lenB) {
return 0;
}
return lenA > lenB ? 1 : -1;
}
function mkdirp(dir) {
if (_nodefs.default.existsSync(dir)) {
return;
}
return _promises.default.mkdir(dir, {
recursive: true
});
}
const writeFile = async (destination, input, dir = (0, _nodepath.dirname)(destination))=>{
const p = mkdirp(dir);
if (p) {
await p;
}
return _promises.default.writeFile(destination, input, {
encoding: 'utf-8'
});
};
const removeFiles = async (files)=>Promise.all(files.map((file)=>_promises.default.rm(file, {
force: true
})));
function withBannerArray(title, description, date, content) {
return [
'#########################################',
`# ${title}`,
`# Last Updated: ${date.toISOString()}`,
`# Size: ${content.length}`,
...description.map((line)=>line ? `# ${line}` : '#'),
'#########################################',
...content,
'################## EOF ##################'
];
}
function notSupported(name) {
return (...args)=>{
console.error(`${name}: not supported.`, args);
throw new Error(`${name}: not implemented.`);
};
}
function withIdentityContent(title, description, date, content) {
return content;
}
function isDirectoryEmptySync(path) {
const directoryHandle = _nodefs.default.opendirSync(path);
try {
return directoryHandle.readSync() === null;
} finally{
directoryHandle.closeSync();
}
}
function fastIpVersion(ip) {
return ip.includes(':') ? 6 : ip.includes('.') ? 4 : 0;
}
} (misc.__exports));
return misc.__exports;
}exports.__require=requireMisc;

View File

@@ -0,0 +1,79 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const normalizeDomain=require('../../_virtual/normalize-domain.cjs'),require$$0=require('tldts'),looseTldtsOpt=require('../constants/loose-tldts-opt.cjs'),require$$2=require('foxts/is-probably-ip');var hasRequiredNormalizeDomain;
function requireNormalizeDomain () {
if (hasRequiredNormalizeDomain) return normalizeDomain.__exports;
hasRequiredNormalizeDomain = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
fastNormalizeDomain: function() {
return fastNormalizeDomain;
},
fastNormalizeDomainWithoutWww: function() {
return fastNormalizeDomainWithoutWww;
},
normalizeDomain: function() {
return normalizeDomain;
}
});
const _tldts = /*#__PURE__*/ _interop_require_default(require$$0);
const _loosetldtsopt = /*@__PURE__*/ looseTldtsOpt.__require();
const _isprobablyip = require$$2;
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function fastNormalizeDomainWithoutWww(domain, parsed = null) {
// We don't want tldts to call its own "extractHostname" on ip, bail out ip first.
// Now ip has been bailed out, we can safely set normalizeTldtsOpt.detectIp to false.
if ((0, _isprobablyip.isProbablyIpv4)(domain) || (0, _isprobablyip.isProbablyIpv6)(domain)) {
return null;
}
parsed ??= _tldts.default.parse(domain, _loosetldtsopt.normalizeTldtsOpt);
// Private invalid domain (things like .tor, .dn42, etc)
if (!parsed.isIcann && !parsed.isPrivate) return null;
if (parsed.subdomain) {
if (parsed.subdomain === 'www') {
return parsed.domain;
}
if (parsed.subdomain.startsWith('www.')) {
return parsed.subdomain.slice(4) + '.' + parsed.domain;
}
}
return parsed.hostname;
}
function fastNormalizeDomain(domain, parsed = null) {
// We don't want tldts to call its own "extractHostname" on ip, bail out ip first.
// Now ip has been bailed out, we can safely set normalizeTldtsOpt.detectIp to false.
if ((0, _isprobablyip.isProbablyIpv4)(domain) || (0, _isprobablyip.isProbablyIpv6)(domain)) {
return null;
}
parsed ??= _tldts.default.parse(domain, _loosetldtsopt.normalizeTldtsOpt);
// Private invalid domain (things like .tor, .dn42, etc)
if (!parsed.isIcann && !parsed.isPrivate) return null;
return parsed.hostname;
}
function normalizeDomain(domain, parsed = null) {
if (domain.length === 0) return null;
if ((0, _isprobablyip.isProbablyIpv4)(domain) || (0, _isprobablyip.isProbablyIpv6)(domain)) {
return null;
}
parsed ??= _tldts.default.parse(domain, _loosetldtsopt.normalizeTldtsOpt);
// Private invalid domain (things like .tor, .dn42, etc)
if (!parsed.isIcann && !parsed.isPrivate) return null;
// const h = parsed.hostname;
// if (h === null) return null;
return parsed.hostname;
}
} (normalizeDomain.__exports));
return normalizeDomain.__exports;
}exports.__require=requireNormalizeDomain;

View File

@@ -0,0 +1,44 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const parseDnsmasq=require('../../_virtual/parse-dnsmasq.cjs'),fetchTextByLine=require('./fetch-text-by-line.cjs'),normalizeDomain=require('./normalize-domain.cjs');var hasRequiredParseDnsmasq;
function requireParseDnsmasq () {
if (hasRequiredParseDnsmasq) return parseDnsmasq.__exports;
hasRequiredParseDnsmasq = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
extractDomainsFromFelixDnsmasq: function() {
return extractDomainsFromFelixDnsmasq;
},
parseFelixDnsmasqFromResp: function() {
return parseFelixDnsmasqFromResp;
}
});
const _fetchtextbyline = /*@__PURE__*/ fetchTextByLine.__require();
const _normalizedomain = /*@__PURE__*/ normalizeDomain.__require();
function extractDomainsFromFelixDnsmasq(line) {
if (line.startsWith('server=/') && line.endsWith('/114.114.114.114')) {
return line.slice(8, -16);
}
return null;
}
async function parseFelixDnsmasqFromResp(resp) {
const results = [];
for await (const line of (0, _fetchtextbyline.createReadlineInterfaceFromResponse)(resp, true)){
const domain = extractDomainsFromFelixDnsmasq(line);
if (domain && (0, _normalizedomain.fastNormalizeDomain)(domain)) {
results.push(domain);
}
}
return results;
}
} (parseDnsmasq.__exports));
return parseDnsmasq.__exports;
}exports.__require=requireParseDnsmasq;

View File

@@ -0,0 +1,71 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const domainlists=require('../../../_virtual/domainlists.cjs'),normalizeDomain=require('../normalize-domain.cjs'),processLine=require('../process-line.cjs'),shared=require('./shared.cjs'),fetchAssets=require('../fetch-assets.cjs');var hasRequiredDomainlists;
function requireDomainlists () {
if (hasRequiredDomainlists) return domainlists.__exports;
hasRequiredDomainlists = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
processDomainLists: function() {
return processDomainLists;
},
processDomainListsWithPreload: function() {
return processDomainListsWithPreload;
}
});
const _normalizedomain = /*@__PURE__*/ normalizeDomain.__require();
const _processline = /*@__PURE__*/ processLine.__require();
const _shared = /*@__PURE__*/ shared.__require();
const _fetchassets = /*@__PURE__*/ fetchAssets.__require();
function domainListLineCb(l, set, meta, normalizeDomain = _normalizedomain.fastNormalizeDomain) {
const line = (0, _processline.processLine)(l);
if (!line) return;
const domain = normalizeDomain(line);
if (!domain) return;
(0, _shared.onBlackFound)(domain, meta);
set.push(domain);
}
function domainListLineCbIncludeAllSubdomain(line, set, meta, normalizeDomain = _normalizedomain.fastNormalizeDomain) {
const domain = normalizeDomain(line);
if (!domain) return;
(0, _shared.onBlackFound)(domain, meta);
set.push('.' + domain);
}
function processDomainLists(span, domainListsUrl, mirrors, includeAllSubDomain = false) {
const lineCb = includeAllSubDomain ? domainListLineCbIncludeAllSubdomain : domainListLineCb;
return span.traceChildAsync(`process domainlist: ${domainListsUrl}`, async (span)=>{
const filterRules = await span.traceChildAsync('download', ()=>(0, _fetchassets.fetchAssets)(domainListsUrl, mirrors, true));
const domainSets = [];
span.traceChildSync('parse domain list', ()=>{
for(let i = 0, len = filterRules.length; i < len; i++){
lineCb(filterRules[i], domainSets, domainListsUrl, _normalizedomain.fastNormalizeDomainWithoutWww);
}
});
return domainSets;
});
}
function processDomainListsWithPreload(domainListsUrl, mirrors, includeAllSubDomain = false) {
const downloadPromise = (0, _fetchassets.fetchAssets)(domainListsUrl, mirrors, true);
const lineCb = includeAllSubDomain ? domainListLineCbIncludeAllSubdomain : domainListLineCb;
return (span)=>span.traceChildAsync(`process domainlist: ${domainListsUrl}`, async (span)=>{
const filterRules = await span.traceChildPromise('download', downloadPromise);
const domainSets = [];
span.traceChildSync('parse domain list', ()=>{
for(let i = 0, len = filterRules.length; i < len; i++){
lineCb(filterRules[i], domainSets, domainListsUrl, _normalizedomain.fastNormalizeDomainWithoutWww);
}
});
return domainSets;
});
}
} (domainlists.__exports));
return domainlists.__exports;
}exports.__require=requireDomainlists;

View File

@@ -0,0 +1,372 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const filters=require('../../../_virtual/filters.cjs'),require$$0=require('picocolors'),fetchAssets=require('../fetch-assets.cjs'),shared=require('./shared.cjs'),require$$3=require('foxts/retrie'),looseTldtsOpt=require('../../constants/loose-tldts-opt.cjs'),require$$5=require('tldts-experimental'),require$$6=require('@ghostery/adblocker'),normalizeDomain=require('../normalize-domain.cjs');var hasRequiredFilters;
function requireFilters () {
if (hasRequiredFilters) return filters.__exports;
hasRequiredFilters = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
parse: function() {
return parse;
},
processFilterRulesWithPreload: function() {
return processFilterRulesWithPreload;
}
});
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0);
const _fetchassets = /*@__PURE__*/ fetchAssets.__require();
const _shared = /*@__PURE__*/ shared.__require();
const _retrie = require$$3;
const _loosetldtsopt = /*@__PURE__*/ looseTldtsOpt.__require();
const _tldtsexperimental = /*#__PURE__*/ _interop_require_default(require$$5);
const _adblocker = require$$6;
const _normalizedomain = /*@__PURE__*/ normalizeDomain.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function processFilterRulesWithPreload(filterRulesUrl, fallbackUrls, includeThirdParty = false) {
const downloadPromise = (0, _fetchassets.fetchAssets)(filterRulesUrl, fallbackUrls);
return (span)=>span.traceChildAsync(`process filter rules: ${filterRulesUrl}`, async (span)=>{
const filterRules = await span.traceChildPromise('download', downloadPromise);
const whiteDomains = new Set();
const whiteDomainSuffixes = new Set();
const blackDomains = new Set();
const blackDomainSuffixes = new Set();
const warningMessages = [];
const MUTABLE_PARSE_LINE_RESULT = [
'',
2000
];
/**
* @param {string} line
*/ const lineCb = (line)=>{
const result = parse(line, MUTABLE_PARSE_LINE_RESULT, includeThirdParty);
const flag = result[1];
if (flag === 2000) {
throw new Error(`Didn't parse line: ${line}`);
}
if (flag === 1000) {
return;
}
const hostname = result[0];
if (flag === 0 || flag === -1) {
(0, _shared.onWhiteFound)(hostname, filterRulesUrl);
} else {
(0, _shared.onBlackFound)(hostname, filterRulesUrl);
}
switch(flag){
case 0:
whiteDomainSuffixes.add(hostname);
break;
case -1:
whiteDomains.add(hostname);
break;
case 2:
blackDomainSuffixes.add(hostname);
break;
case 1:
blackDomains.add(hostname);
break;
case 10:
warningMessages.push(hostname);
break;
}
};
span.traceChild('parse adguard filter').traceSyncFn(()=>{
for(let i = 0, len = filterRules.length; i < len; i++){
lineCb(filterRules[i]);
}
});
for(let i = 0, len = warningMessages.length; i < len; i++){
console.warn(_picocolors.default.yellow(warningMessages[i]), _picocolors.default.gray(_picocolors.default.underline(filterRulesUrl)));
}
console.log(_picocolors.default.gray('[process filter]'), _picocolors.default.gray(filterRulesUrl), _picocolors.default.gray(`white: ${whiteDomains.size + whiteDomainSuffixes.size}`), _picocolors.default.gray(`black: ${blackDomains.size + blackDomainSuffixes.size}`));
return {
whiteDomains: Array.from(whiteDomains),
whiteDomainSuffixes: Array.from(whiteDomainSuffixes),
blackDomains: Array.from(blackDomains),
blackDomainSuffixes: Array.from(blackDomainSuffixes)
};
});
}
// many filter that has modifiers can not work on Surge/Clash because browser context is required
// we can early bail out those rules
const kwfilter = (0, _retrie.createRetrieKeywordFilter)([
'!',
'?',
'*',
'[',
'(',
']',
')',
',',
'#',
'%',
'&',
'=',
'~',
// special modifier
'$popup',
'$removeparam',
'$redirect',
'$popunder',
'$cname',
'$frame',
'$domain',
'$from',
'$to',
'$csp',
'$replace',
'$urlskip',
// some bad syntax
'^popup'
]);
function parse($line, result, includeThirdParty) {
if (// doesn't include
!$line.includes('.') // rule with out dot can not be a domain
|| kwfilter($line)) {
result[1] = 1000;
return result;
}
const line = $line.trim();
if (line.length === 0) {
result[1] = 1000;
return result;
}
const firstCharCode = line.charCodeAt(0);
const lastCharCode = line.charCodeAt(line.length - 1);
if (firstCharCode === 47 // 47 `/`
|| lastCharCode === 46 // 46 `.`, line.endsWith('.')
|| lastCharCode === 45 // 45 `-`, line.endsWith('-')
|| lastCharCode === 95 // 95 `_`, line.endsWith('_')
) {
result[1] = 1000;
return result;
}
if ((line.includes('/') || line.includes(':')) && !line.includes('://')) {
result[1] = 1000;
return result;
}
const filter = _adblocker.NetworkFilter.parse(line);
if (filter) {
if (// filter.isCosmeticFilter() // always false
// filter.isNetworkFilter() // always true
filter.isElemHide() || filter.isGenericHide() || filter.isSpecificHide() || filter.isRedirect() || filter.isRedirectRule() || filter.hasDomains() || filter.isCSP() // must not be csp rule
|| !filter.fromHttp() && !filter.fromHttps()) {
// not supported type
result[1] = 1000;
return result;
}
if (!filter.fromAny() && !filter.fromDocument() // $document, $doc
) {
result[1] = 1000;
return result;
}
if (filter.hostname // filter.hasHostname() // must have
&& filter.isPlain() // isPlain() === !isRegex()
&& !filter.isFullRegex()) {
const hostname = (0, _normalizedomain.fastNormalizeDomainWithoutWww)(filter.hostname);
if (!hostname) {
result[1] = 1000;
return result;
}
// |: filter.isHostnameAnchor(),
// |: filter.isLeftAnchor(),
// |https://: !filter.isHostnameAnchor() && (filter.fromHttps() || filter.fromHttp())
const isIncludeAllSubDomain = filter.isHostnameAnchor();
if (filter.isException() || filter.isBadFilter()) {
result[0] = hostname;
result[1] = isIncludeAllSubDomain ? 0 : -1;
return result;
}
const _1p = filter.firstParty();
const _3p = filter.thirdParty();
if (_1p) {
if (_3p) {
result[0] = hostname;
result[1] = isIncludeAllSubDomain ? 2 : 1;
return result;
}
result[1] = 1000;
return result;
}
if (_3p) {
if (includeThirdParty) {
result[0] = hostname;
result[1] = isIncludeAllSubDomain ? 2 : 1;
return result;
}
result[1] = 1000;
return result;
}
}
}
/**
* From now on, we are mostly facing non-standard domain rules (some are regex like)
*
* We can still salvage some of them by removing modifiers
*/ let sliceStart = 0;
let sliceEnd = 0;
// After NetworkFilter.parse, it means the line can not be parsed by cliqz NetworkFilter
// We now need to "salvage" the line as much as possible
let white = false;
let includeAllSubDomain = false;
if (firstCharCode === 64 // 64 `@`
&& line.charCodeAt(1) === 64 // 64 `@`
) {
sliceStart += 2;
white = true;
includeAllSubDomain = true;
}
/**
* Some "malformed" regex-based filters can not be parsed by NetworkFilter
* "$genericblock`" is also not supported by NetworkFilter, see:
* https://github.com/ghostery/adblocker/blob/62caf7786ba10ef03beffecd8cd4eec111bcd5ec/packages/adblocker/test/parsing.test.ts#L950
*
* `@@||cmechina.net^$genericblock`
* `@@|ftp.bmp.ovh^|`
* `@@|adsterra.com^|`
* `@@.atlassian.net$document`
* `@@||ad.alimama.com^$genericblock`
*/ switch(line.charCodeAt(sliceStart)){
case 124:
/** | */ // line.startsWith('@@|') || line.startsWith('|')
sliceStart += 1;
includeAllSubDomain = false;
if (line[sliceStart] === '|') {
sliceStart += 1;
includeAllSubDomain = true;
}
break;
case 46:
{
/**
* `.ay.delivery^`
* `.m.bookben.com^`
* `.wap.x4399.com^`
*/ sliceStart += 1;
includeAllSubDomain = true;
break;
}
}
switch(line.charCodeAt(sliceStart)){
case 58:
{
/**
* `@@://googleadservices.com^|`
* `@@://www.googleadservices.com^|`
* `://mine.torrent.pw^`
* `://say.ac^`
*/ if (line[sliceStart + 1] === '/' && line[sliceStart + 2] === '/') {
includeAllSubDomain = false;
sliceStart += 3;
}
break;
}
case 104:
{
/** |http://x.o2.pl^ */ if (line.startsWith('http://', sliceStart)) {
includeAllSubDomain = false;
sliceStart += 7;
} else if (line.startsWith('https://', sliceStart)) {
includeAllSubDomain = false;
sliceStart += 8;
}
break;
}
}
const indexOfDollar = line.indexOf('$', sliceStart);
if (indexOfDollar > -1) {
sliceEnd = indexOfDollar - line.length;
}
/*
* We skip third-party and frame rules, as Surge / Clash can't handle them
*
* `.sharecounter.$third-party`
* `.bbelements.com^$third-party`
* `://o0e.ru^$third-party`
* `.1.1.1.l80.js^$third-party`
*/ if (!includeThirdParty && (line.includes('third-party', indexOfDollar + 1) || line.includes('3p', indexOfDollar + 1))) {
result[1] = 1000;
return result;
}
if (line.includes('badfilter', indexOfDollar + 1)) {
white = true;
}
if (line.includes('all', indexOfDollar + 1)) {
includeAllSubDomain = true;
}
/**
* `_vmind.qqvideo.tc.qq.com^`
* `arketing.indianadunes.com^`
* `charlestownwyllie.oaklawnnonantum.com^`
* `-telemetry.officeapps.live.com^`
* `-tracker.biliapi.net`
* `-logging.nextmedia.com`
* `_social_tracking.js^`
*/ if (line.charCodeAt(line.length + sliceEnd - 1) === 94) {
/** line.endsWith('^') */ sliceEnd -= 1;
} else if (line.charCodeAt(line.length + sliceEnd - 1) === 124) {
/** line.endsWith('|') */ sliceEnd -= 1;
if (line.charCodeAt(line.length + sliceEnd - 1) === 94) {
/** line.endsWith('^|') */ sliceEnd -= 1;
}
} else if (line.charCodeAt(line.length + sliceEnd - 1) === 46) {
/** line.endsWith('.') */ sliceEnd -= 1;
}
const sliced = sliceStart > 0 || sliceEnd < 0 ? line.slice(sliceStart, sliceEnd === 0 ? undefined : sliceEnd) : line;
if (sliced.length === 0 || sliced.includes('/')) {
result[1] = 1000;
return result;
}
if (sliced.charCodeAt(0) === 45 /* - */ ) {
// line.startsWith('-') is not a valid domain
result[1] = 10;
result[0] = `[parse-filter E0001] (${white ? 'white' : 'black'}) invalid domain: ${JSON.stringify({
line,
sliced,
sliceStart,
sliceEnd
})}`;
return result;
}
const suffix = _tldtsexperimental.default.getPublicSuffix(sliced, _loosetldtsopt.looseTldtsOpt);
if (!suffix) {
// This exclude domain-like resource like `_social_tracking.js^`
result[1] = 1000;
return result;
}
const domain = (0, _normalizedomain.fastNormalizeDomainWithoutWww)(sliced);
if (domain && domain === sliced) {
result[0] = domain;
if (white) {
result[1] = includeAllSubDomain ? 0 : -1;
} else {
result[1] = includeAllSubDomain ? 2 : 1;
}
return result;
}
result[0] = `[parse-filter E0010] (${white ? 'white' : 'black'}) invalid domain: ${JSON.stringify({
line,
domain,
suffix,
sliced,
sliceStart,
sliceEnd
})}`;
result[1] = 10;
return result;
}
} (filters.__exports));
return filters.__exports;
}exports.__require=requireFilters;

View File

@@ -0,0 +1,66 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const hosts=require('../../../_virtual/hosts.cjs'),fetchAssets=require('../fetch-assets.cjs'),normalizeDomain=require('../normalize-domain.cjs'),shared=require('./shared.cjs');var hasRequiredHosts;
function requireHosts () {
if (hasRequiredHosts) return hosts.__exports;
hasRequiredHosts = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
processHosts: function() {
return processHosts;
},
processHostsWithPreload: function() {
return processHostsWithPreload;
}
});
const _fetchassets = /*@__PURE__*/ fetchAssets.__require();
const _normalizedomain = /*@__PURE__*/ normalizeDomain.__require();
const _shared = /*@__PURE__*/ shared.__require();
function hostsLineCb(line, set, includeAllSubDomain, meta) {
const _domain = line.split(/\s/)[1]?.trim();
if (!_domain) {
return;
}
const domain = (0, _normalizedomain.fastNormalizeDomainWithoutWww)(_domain);
if (!domain) {
return;
}
(0, _shared.onBlackFound)(domain, meta);
set.push(includeAllSubDomain ? `.${domain}` : domain);
}
function processHosts(span, hostsUrl, mirrors, includeAllSubDomain = false) {
return span.traceChildAsync(`process hosts: ${hostsUrl}`, async (span)=>{
const filterRules = await span.traceChild('download').traceAsyncFn(()=>(0, _fetchassets.fetchAssets)(hostsUrl, mirrors, true));
const domainSets = [];
span.traceChild('parse hosts').traceSyncFn(()=>{
for(let i = 0, len = filterRules.length; i < len; i++){
hostsLineCb(filterRules[i], domainSets, includeAllSubDomain, hostsUrl);
}
});
return domainSets;
});
}
function processHostsWithPreload(hostsUrl, mirrors, includeAllSubDomain = false) {
const downloadPromise = (0, _fetchassets.fetchAssets)(hostsUrl, mirrors, true);
return (span)=>span.traceChildAsync(`process hosts: ${hostsUrl}`, async (span)=>{
const filterRules = await span.traceChild('download').tracePromise(downloadPromise);
const domainSets = [];
span.traceChild('parse hosts').traceSyncFn(()=>{
for(let i = 0, len = filterRules.length; i < len; i++){
hostsLineCb(filterRules[i], domainSets, includeAllSubDomain, hostsUrl);
}
});
return domainSets;
});
}
} (hosts.__exports));
return hosts.__exports;
}exports.__require=requireHosts;

View File

@@ -0,0 +1,52 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const shared=require('../../../_virtual/shared.cjs'),require$$0=require('picocolors'),rejectDataSource=require('../../constants/reject-data-source.cjs'),require$$2=require('foxts/noop');var hasRequiredShared;
function requireShared () {
if (hasRequiredShared) return shared.__exports;
hasRequiredShared = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
foundDebugDomain: function() {
return foundDebugDomain;
},
onBlackFound: function() {
return onBlackFound;
},
onWhiteFound: function() {
return onWhiteFound;
}
});
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0);
const _rejectdatasource = /*@__PURE__*/ rejectDataSource.__require();
const _noop = require$$2;
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const foundDebugDomain = {
value: false
};
const onBlackFound = _rejectdatasource.DEBUG_DOMAIN_TO_FIND ? (line, meta)=>{
if (line.includes(_rejectdatasource.DEBUG_DOMAIN_TO_FIND)) {
console.warn(_picocolors.default.red(meta), '(black)', line.replaceAll(_rejectdatasource.DEBUG_DOMAIN_TO_FIND, _picocolors.default.bold(_rejectdatasource.DEBUG_DOMAIN_TO_FIND)));
foundDebugDomain.value = true;
}
} : _noop.noop;
const onWhiteFound = _rejectdatasource.DEBUG_DOMAIN_TO_FIND ? (line, meta)=>{
if (line.includes(_rejectdatasource.DEBUG_DOMAIN_TO_FIND)) {
console.warn(_picocolors.default.red(meta), '(white)', line.replaceAll(_rejectdatasource.DEBUG_DOMAIN_TO_FIND, _picocolors.default.bold(_rejectdatasource.DEBUG_DOMAIN_TO_FIND)));
foundDebugDomain.value = true;
}
} : _noop.noop;
} (shared.__exports));
return shared.__exports;
}exports.__require=requireShared;

View File

@@ -0,0 +1,79 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const processLine=require('../../_virtual/process-line.cjs'),require$$0=require('node:stream/web');var hasRequiredProcessLine;
function requireProcessLine () {
if (hasRequiredProcessLine) return processLine.__exports;
hasRequiredProcessLine = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
ProcessLineStream: function() {
return ProcessLineStream;
},
processLine: function() {
return processLine;
}
});
const _web = require$$0;
function processLine(line) {
const trimmed = line.trim();
if (trimmed.length === 0) {
return null;
}
const line_0 = trimmed.charCodeAt(0);
if (// line_0 === 32 /** [space] */
// || line_0 === 13 /** \r */
// || line_0 === 10 /** \n */
line_0 === 33 /** ! */ || line_0 === 47 /** / */ && trimmed.charCodeAt(1) === 47 /** / */ ) {
return null;
}
if (line_0 === 35 /** # */ ) {
if (trimmed.charCodeAt(1) !== 35 /** # */ ) {
// # Comment
return null;
}
if (trimmed.charCodeAt(2) === 35 /** # */ && trimmed.charCodeAt(3) === 35) {
// ################## EOF ##################
return null;
}
/**
* AdGuard Filter can be:
*
* ##.class
* ##tag.class
* ###id
*/ }
return trimmed;
}
class ProcessLineStream extends _web.TransformStream {
// private __buf = '';
constructor(){
super({
transform (l, controller) {
const line = processLine(l);
if (line) {
controller.enqueue(line);
}
}
});
}
} // export class ProcessLineNodeStream extends Transform {
// _transform(chunk: string, encoding: BufferEncoding, callback: TransformCallback) {
// // Convert chunk to string and then to uppercase
// const upperCased = chunk.toUpperCase();
// // Push transformed data to readable side
// this.push(upperCased);
// // Call callback when done
// callback();
// }
// }
} (processLine.__exports));
return processLine.__exports;
}exports.__require=requireProcessLine;

View File

@@ -0,0 +1,469 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const base=require('../../../_virtual/base.cjs'),trie=require('../trie.cjs'),require$$6=require('foxts/guard'),require$$2=require('fast-cidr-tools'),require$$3=require('foxts/retrie'),require$$0=require('node:path'),surge=require('../writing-strategy/surge.cjs');var hasRequiredBase;
function requireBase () {
if (hasRequiredBase) return base.__exports;
hasRequiredBase = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "FileOutput", {
enumerable: true,
get: function() {
return FileOutput;
}
});
const _trie = /*@__PURE__*/ trie.__require();
const _guard = require$$6;
const _fastcidrtools = require$$2;
const _retrie = require$$3;
const _nodepath = /*#__PURE__*/ _interop_require_default(require$$0);
const _surge = /*@__PURE__*/ surge.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class FileOutput {
id;
strategies;
domainTrie;
domainKeywords;
domainWildcard;
userAgent;
processName;
processPath;
urlRegex;
ipcidr;
ipcidrNoResolve;
ipasn;
ipasnNoResolve;
ipcidr6;
ipcidr6NoResolve;
geoip;
groipNoResolve;
sourceIpOrCidr;
sourcePort;
destPort;
otherRules;
pendingPromise;
whitelistDomain;
span;
constructor($span, id){
this.id = id;
this.strategies = [];
this.domainTrie = new _trie.HostnameSmolTrie(null);
this.domainKeywords = new Set();
this.domainWildcard = new Set();
this.userAgent = new Set();
this.processName = new Set();
this.processPath = new Set();
this.urlRegex = new Set();
this.ipcidr = new Set();
this.ipcidrNoResolve = new Set();
this.ipasn = new Set();
this.ipasnNoResolve = new Set();
this.ipcidr6 = new Set();
this.ipcidr6NoResolve = new Set();
this.geoip = new Set();
this.groipNoResolve = new Set();
this.sourceIpOrCidr = new Set();
this.sourcePort = new Set();
this.destPort = new Set();
this.otherRules = [];
this.pendingPromise = null;
this.whitelistDomain = (domain)=>{
this.domainTrie.whitelist(domain);
return this;
};
this.title = null;
this.description = null;
this.date = new Date();
this.strategiesWritten = false;
this.span = $span.traceChild('RuleOutput#' + id);
}
title;
withTitle(title) {
this.title = title;
return this;
}
withStrategies(strategies) {
this.strategies = strategies;
return this;
}
withExtraStrategies(strategy) {
if (strategy) {
this.strategies.push(strategy);
}
}
description;
withDescription(description) {
this.description = description;
return this;
}
date;
withDate(date) {
this.date = date;
return this;
}
addDomain(domain) {
this.domainTrie.add(domain);
return this;
}
bulkAddDomain(domains) {
let d;
for(let i = 0, len = domains.length; i < len; i++){
d = domains[i];
if (d !== null) {
this.domainTrie.add(d, false, null, 0);
}
}
return this;
}
addDomainSuffix(domain, lineFromDot = domain[0] === '.') {
this.domainTrie.add(domain, true, lineFromDot ? 1 : 0);
return this;
}
bulkAddDomainSuffix(domains) {
for(let i = 0, len = domains.length; i < len; i++){
this.addDomainSuffix(domains[i]);
}
return this;
}
addDomainKeyword(keyword) {
this.domainKeywords.add(keyword);
return this;
}
addIPASN(asn) {
this.ipasn.add(asn);
return this;
}
bulkAddIPASN(asns) {
for(let i = 0, len = asns.length; i < len; i++){
this.ipasn.add(asns[i]);
}
return this;
}
async addFromDomainsetPromise(source) {
for await (const line of source){
if (line[0] === '.') {
this.addDomainSuffix(line, true);
} else {
this.domainTrie.add(line, false, null, 0);
}
}
}
addFromDomainset(source) {
if (this.pendingPromise) {
if ('then' in source) {
this.pendingPromise = this.pendingPromise.then(()=>source).then((src)=>this.addFromDomainsetPromise(src));
return this;
}
this.pendingPromise = this.pendingPromise.then(()=>this.addFromDomainsetPromise(source));
return this;
}
if ('then' in source) {
this.pendingPromise = source.then((src)=>this.addFromDomainsetPromise(src));
return this;
}
this.pendingPromise = this.addFromDomainsetPromise(source);
return this;
}
async addFromRulesetPromise(source) {
for await (const line of source){
const splitted = line.split(',');
const type = splitted[0];
const value = splitted[1];
const arg = splitted[2];
switch(type){
case 'DOMAIN':
this.domainTrie.add(value, false, null, 0);
break;
case 'DOMAIN-SUFFIX':
this.addDomainSuffix(value, false);
break;
case 'DOMAIN-KEYWORD':
this.addDomainKeyword(value);
break;
case 'DOMAIN-WILDCARD':
this.domainWildcard.add(value);
break;
case 'USER-AGENT':
this.userAgent.add(value);
break;
case 'PROCESS-NAME':
if (value.includes('/') || value.includes('\\')) {
this.processPath.add(value);
} else {
this.processName.add(value);
}
break;
case 'URL-REGEX':
{
const [, ...rest] = splitted;
this.urlRegex.add(rest.join(','));
break;
}
case 'IP-CIDR':
(arg === 'no-resolve' ? this.ipcidrNoResolve : this.ipcidr).add(value);
break;
case 'IP-CIDR6':
(arg === 'no-resolve' ? this.ipcidr6NoResolve : this.ipcidr6).add(value);
break;
case 'IP-ASN':
(arg === 'no-resolve' ? this.ipasnNoResolve : this.ipasn).add(value);
break;
case 'GEOIP':
(arg === 'no-resolve' ? this.groipNoResolve : this.geoip).add(value);
break;
case 'SRC-IP':
this.sourceIpOrCidr.add(value);
break;
case 'SRC-PORT':
this.sourcePort.add(value);
break;
case 'DEST-PORT':
this.destPort.add(value);
break;
default:
this.otherRules.push(line);
break;
}
}
}
addFromRuleset(source) {
if (this.pendingPromise) {
if ('then' in source) {
this.pendingPromise = this.pendingPromise.then(()=>source).then((src)=>this.addFromRulesetPromise(src));
return this;
}
this.pendingPromise = this.pendingPromise.then(()=>this.addFromRulesetPromise(source));
return this;
}
if ('then' in source) {
this.pendingPromise = source.then((src)=>this.addFromRulesetPromise(src));
return this;
}
this.pendingPromise = this.addFromRulesetPromise(source);
return this;
}
static ipToCidr = (ip, version)=>{
if (ip.includes('/')) return ip;
if (version === 4) {
return ip + '/32';
}
return ip + '/128';
};
bulkAddCIDR4(cidrs) {
for(let i = 0, len = cidrs.length; i < len; i++){
this.ipcidr.add(FileOutput.ipToCidr(cidrs[i], 4));
}
return this;
}
bulkAddCIDR4NoResolve(cidrs) {
for(let i = 0, len = cidrs.length; i < len; i++){
this.ipcidrNoResolve.add(FileOutput.ipToCidr(cidrs[i], 4));
}
return this;
}
bulkAddCIDR6(cidrs) {
for(let i = 0, len = cidrs.length; i < len; i++){
this.ipcidr6.add(FileOutput.ipToCidr(cidrs[i], 6));
}
return this;
}
bulkAddCIDR6NoResolve(cidrs) {
for(let i = 0, len = cidrs.length; i < len; i++){
this.ipcidr6NoResolve.add(FileOutput.ipToCidr(cidrs[i], 6));
}
return this;
}
async done() {
await this.pendingPromise;
this.pendingPromise = null;
return this;
}
// private guardPendingPromise() {
// // reverse invariant
// if (this.pendingPromise !== null) {
// console.trace('Pending promise:', this.pendingPromise);
// throw new Error('You should call done() before calling this method');
// }
// }
// async writeClash(outputDir?: null | string) {
// await this.done();
// invariant(this.title, 'Missing title');
// invariant(this.description, 'Missing description');
// return compareAndWriteFile(
// this.span,
// withBannerArray(
// this.title,
// this.description,
// this.date,
// this.clash()
// ),
// path.join(outputDir ?? OUTPUT_CLASH_DIR, this.type, this.id + '.txt')
// );
// }
strategiesWritten;
writeToStrategies() {
if (this.pendingPromise) {
throw new Error('You should call done() before calling writeToStrategies()');
}
if (this.strategiesWritten) {
throw new Error('Strategies already written');
}
this.strategiesWritten = true;
const kwfilter = (0, _retrie.createRetrieKeywordFilter)(Array.from(this.domainKeywords));
if (this.strategies.filter((0, _guard.not)(false)).length === 0) {
throw new Error('No strategies to write ' + this.id);
}
this.domainTrie.dumpWithoutDot((domain, includeAllSubdomain)=>{
if (kwfilter(domain)) {
return;
}
for(let i = 0, len = this.strategies.length; i < len; i++){
const strategy = this.strategies[i];
if (strategy) {
if (includeAllSubdomain) {
strategy.writeDomainSuffix(domain);
} else {
strategy.writeDomain(domain);
}
}
}
}, true);
for(let i = 0, len = this.strategies.length; i < len; i++){
const strategy = this.strategies[i];
if (!strategy) continue;
if (this.domainKeywords.size) {
strategy.writeDomainKeywords(this.domainKeywords);
}
if (this.domainWildcard.size) {
strategy.writeDomainWildcards(this.domainWildcard);
}
if (this.userAgent.size) {
strategy.writeUserAgents(this.userAgent);
}
if (this.processName.size) {
strategy.writeProcessNames(this.processName);
}
if (this.processPath.size) {
strategy.writeProcessPaths(this.processPath);
}
}
if (this.sourceIpOrCidr.size) {
const sourceIpOrCidr = Array.from(this.sourceIpOrCidr);
for(let i = 0, len = this.strategies.length; i < len; i++){
const strategy = this.strategies[i];
if (strategy) {
strategy.writeSourceIpCidrs(sourceIpOrCidr);
}
}
}
for(let i = 0, len = this.strategies.length; i < len; i++){
const strategy = this.strategies[i];
if (strategy) {
if (this.sourcePort.size) {
strategy.writeSourcePorts(this.sourcePort);
}
if (this.destPort.size) {
strategy.writeDestinationPorts(this.destPort);
}
if (this.otherRules.length) {
strategy.writeOtherRules(this.otherRules);
}
if (this.urlRegex.size) {
strategy.writeUrlRegexes(this.urlRegex);
}
}
}
let ipcidr = null;
let ipcidrNoResolve = null;
let ipcidr6 = null;
let ipcidr6NoResolve = null;
if (this.ipcidr.size) {
ipcidr = (0, _fastcidrtools.merge)(Array.from(this.ipcidr), true);
}
if (this.ipcidrNoResolve.size) {
ipcidrNoResolve = (0, _fastcidrtools.merge)(Array.from(this.ipcidrNoResolve), true);
}
if (this.ipcidr6.size) {
ipcidr6 = Array.from(this.ipcidr6);
}
if (this.ipcidr6NoResolve.size) {
ipcidr6NoResolve = Array.from(this.ipcidr6NoResolve);
}
for(let i = 0, len = this.strategies.length; i < len; i++){
const strategy = this.strategies[i];
if (strategy) {
// no-resolve
if (ipcidrNoResolve?.length) {
strategy.writeIpCidrs(ipcidrNoResolve, true);
}
if (ipcidr6NoResolve?.length) {
strategy.writeIpCidr6s(ipcidr6NoResolve, true);
}
if (this.ipasnNoResolve.size) {
strategy.writeIpAsns(this.ipasnNoResolve, true);
}
if (this.groipNoResolve.size) {
strategy.writeGeoip(this.groipNoResolve, true);
}
// triggers DNS resolution
if (ipcidr?.length) {
strategy.writeIpCidrs(ipcidr, false);
}
if (ipcidr6?.length) {
strategy.writeIpCidr6s(ipcidr6, false);
}
if (this.ipasn.size) {
strategy.writeIpAsns(this.ipasn, false);
}
if (this.geoip.size) {
strategy.writeGeoip(this.geoip, false);
}
}
}
}
write() {
return this.span.traceChildAsync('write all', async (childSpan)=>{
await this.done();
childSpan.traceChildSync('write to strategies', this.writeToStrategies.bind(this));
return childSpan.traceChildAsync('output to disk', (childSpan)=>{
const promises = [];
(0, _guard.invariant)(this.title, 'Missing title');
(0, _guard.invariant)(this.description, 'Missing description');
for(let i = 0, len = this.strategies.length; i < len; i++){
const strategy = this.strategies[i];
if (strategy) {
const basename = (strategy.overwriteFilename || this.id) + '.' + strategy.fileExtension;
promises.push(strategy.output(childSpan, this.title, this.description, this.date, _nodepath.default.join(strategy.outputDir, strategy.type ? _nodepath.default.join(strategy.type, basename) : basename)));
}
}
return Promise.all(promises);
});
});
}
async compile() {
await this.done();
this.writeToStrategies();
return this.strategies.reduce((acc, strategy)=>{
if (strategy) {
acc.push(strategy.content);
} else {
acc.push(null);
}
return acc;
}, []);
}
withMitmSgmodulePath(moduleName) {
if (moduleName) {
this.withExtraStrategies(new _surge.SurgeMitmSgmodule(moduleName));
}
return this;
}
}
} (base.__exports));
return base.__exports;
}exports.__require=requireBase;

View File

@@ -0,0 +1,47 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const domainset=require('../../../_virtual/domainset.cjs'),adguardhome=require('../writing-strategy/adguardhome.cjs'),clash=require('../writing-strategy/clash.cjs'),singbox=require('../writing-strategy/singbox.cjs'),surge=require('../writing-strategy/surge.cjs'),base=require('./base.cjs');var hasRequiredDomainset;
function requireDomainset () {
if (hasRequiredDomainset) return domainset.__exports;
hasRequiredDomainset = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
AdGuardHomeOutput: function() {
return AdGuardHomeOutput;
},
DomainsetOutput: function() {
return DomainsetOutput;
}
});
const _adguardhome = /*@__PURE__*/ adguardhome.__require();
const _clash = /*@__PURE__*/ clash.__require();
const _singbox = /*@__PURE__*/ singbox.__require();
const _surge = /*@__PURE__*/ surge.__require();
const _base = /*@__PURE__*/ base.__require();
class DomainsetOutput extends _base.FileOutput {
strategies = [
new _surge.SurgeDomainSet(),
new _clash.ClashDomainSet(),
new _singbox.SingboxSource('domainset')
];
}
class AdGuardHomeOutput extends _base.FileOutput {
strategies;
constructor(span, id, outputDir){
super(span, id);
this.strategies = [
new _adguardhome.AdGuardHome(outputDir)
];
}
}
} (domainset.__exports));
return domainset.__exports;
}exports.__require=requireDomainset;

View File

@@ -0,0 +1,34 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const ip=require('../../../_virtual/ip.cjs'),clash=require('../writing-strategy/clash.cjs'),singbox=require('../writing-strategy/singbox.cjs'),surge=require('../writing-strategy/surge.cjs'),base=require('./base.cjs');var hasRequiredIp;
function requireIp () {
if (hasRequiredIp) return ip.__exports;
hasRequiredIp = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "IPListOutput", {
enumerable: true,
get: function() {
return IPListOutput;
}
});
const _clash = /*@__PURE__*/ clash.__require();
const _singbox = /*@__PURE__*/ singbox.__require();
const _surge = /*@__PURE__*/ surge.__require();
const _base = /*@__PURE__*/ base.__require();
class IPListOutput extends _base.FileOutput {
clashUseRule;
strategies;
constructor(span, id, clashUseRule = true){
super(span, id), this.clashUseRule = clashUseRule;
this.strategies = [
new _surge.SurgeRuleSet('ip'),
this.clashUseRule ? new _clash.ClashClassicRuleSet('ip') : new _clash.ClashIPSet(),
new _singbox.SingboxSource('ip')
];
}
}
} (ip.__exports));
return ip.__exports;
}exports.__require=requireIp;

View File

@@ -0,0 +1,59 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const ruleset=require('../../../_virtual/ruleset.cjs'),clash=require('../writing-strategy/clash.cjs'),singbox=require('../writing-strategy/singbox.cjs'),surge=require('../writing-strategy/surge.cjs'),base=require('./base.cjs');var hasRequiredRuleset;
function requireRuleset () {
if (hasRequiredRuleset) return ruleset.__exports;
hasRequiredRuleset = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
ClashOnlyRulesetOutput: function() {
return ClashOnlyRulesetOutput;
},
RulesetOutput: function() {
return RulesetOutput;
},
SurgeOnlyRulesetOutput: function() {
return SurgeOnlyRulesetOutput;
}
});
const _clash = /*@__PURE__*/ clash.__require();
const _singbox = /*@__PURE__*/ singbox.__require();
const _surge = /*@__PURE__*/ surge.__require();
const _base = /*@__PURE__*/ base.__require();
class RulesetOutput extends _base.FileOutput {
constructor(span, id, type){
super(span, id);
this.strategies = [
new _surge.SurgeRuleSet(type),
new _clash.ClashClassicRuleSet(type),
new _singbox.SingboxSource(type)
];
}
}
class SurgeOnlyRulesetOutput extends _base.FileOutput {
constructor(span, id, type, overrideOutputDir){
super(span, id);
this.strategies = [
new _surge.SurgeRuleSet(type, overrideOutputDir)
];
}
}
class ClashOnlyRulesetOutput extends _base.FileOutput {
constructor(span, id, type){
super(span, id);
this.strategies = [
new _clash.ClashClassicRuleSet(type)
];
}
}
} (ruleset.__exports));
return ruleset.__exports;
}exports.__require=requireRuleset;

View File

@@ -0,0 +1,65 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const textLineTransformStream=require('../../_virtual/text-line-transform-stream.cjs'),require$$0=require('node:stream/web');var hasRequiredTextLineTransformStream;
function requireTextLineTransformStream () {
if (hasRequiredTextLineTransformStream) return textLineTransformStream.__exports;
hasRequiredTextLineTransformStream = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "TextLineStream", {
enumerable: true,
get: function() {
return TextLineStream;
}
});
const _web = require$$0;
class TextLineStream extends _web.TransformStream {
// private __buf = '';
constructor({ allowCR = false } = {}){
let __buf = '';
let chunkIndex = 0;
super({
transform (chunk, controller) {
chunk = __buf + chunk;
chunkIndex = 0;
for(;;){
const lfIndex = chunk.indexOf('\n', chunkIndex);
if (allowCR) {
const crIndex = chunk.indexOf('\r', chunkIndex);
if (crIndex !== -1 && crIndex !== chunk.length - 1 && (lfIndex === -1 || lfIndex - 1 > crIndex)) {
controller.enqueue(chunk.slice(chunkIndex, crIndex));
chunkIndex = crIndex + 1;
continue;
}
}
if (lfIndex === -1) {
break;
}
// enqueue current line, and loop again to find next line
let crOrLfIndex = lfIndex;
if (chunk[lfIndex - 1] === '\r') {
crOrLfIndex--;
}
controller.enqueue(chunk.slice(chunkIndex, crOrLfIndex));
chunkIndex = lfIndex + 1;
continue;
}
__buf = chunk.slice(chunkIndex);
},
flush (controller) {
if (__buf.length > 0) {
// eslint-disable-next-line sukka/string/prefer-string-starts-ends-with -- performance
if (allowCR && __buf[__buf.length - 1] === '\r') {
controller.enqueue(__buf.slice(0, -1));
} else {
controller.enqueue(__buf);
}
}
}
});
}
}
} (textLineTransformStream.__exports));
return textLineTransformStream.__exports;
}exports.__require=requireTextLineTransformStream;

View File

@@ -0,0 +1,75 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const treeDir=require('../../_virtual/tree-dir.cjs'),require$$2=require('node:fs/promises'),require$$0=require('node:path');var hasRequiredTreeDir;
function requireTreeDir () {
if (hasRequiredTreeDir) return treeDir.__exports;
hasRequiredTreeDir = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
TreeFileType: function() {
return TreeFileType;
},
treeDir: function() {
return treeDir;
}
});
const _promises = /*#__PURE__*/ _interop_require_default(require$$2);
const _nodepath = require$$0;
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
var TreeFileType = /*#__PURE__*/ function(TreeFileType) {
TreeFileType[TreeFileType["FILE"] = 1] = "FILE";
TreeFileType[TreeFileType["DIRECTORY"] = 2] = "DIRECTORY";
return TreeFileType;
}({});
async function treeDir(rootPath) {
const tree = [];
const walk = async (dir, node, dirRelativeToRoot = '')=>{
const promises = [];
for await (const child of (await _promises.default.opendir(dir))){
// Ignore hidden files
if (child.name[0] === '.' || child.name === 'CNAME') {
continue;
}
const childFullPath = child.parentPath + _nodepath.sep + child.name;
const childRelativeToRoot = dirRelativeToRoot + _nodepath.sep + child.name;
if (child.isDirectory()) {
const newNode = {
type: 2,
name: child.name,
path: childRelativeToRoot,
children: []
};
node.push(newNode);
promises.push(walk(childFullPath, newNode.children, childRelativeToRoot));
continue;
}
if (child.isFile()) {
const newNode = {
type: 1,
name: child.name,
path: childRelativeToRoot
};
node.push(newNode);
continue;
}
}
return Promise.all(promises);
};
await walk(rootPath, tree);
return tree;
}
} (treeDir.__exports));
return treeDir.__exports;
}exports.__require=requireTreeDir;

540
Dist/Build/lib/trie.cjs Normal file
View File

@@ -0,0 +1,540 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const trie=require('../../_virtual/trie.cjs'),misc=require('./misc.cjs'),require$$1=require('node:util'),require$$2=require('foxts/noop'),require$$3=require('foxts/fast-string-array-join'),require$$4=require('foxts/bitwise');/**
* Hostbane-Optimized Trie based on Mnemonist Trie
*/
var hasRequiredTrie;
function requireTrie () {
if (hasRequiredTrie) return trie.__exports;
hasRequiredTrie = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
HostnameSmolTrie: function() {
return HostnameSmolTrie;
},
HostnameTrie: function() {
return HostnameTrie;
}
});
const _misc = /*@__PURE__*/ misc.__require();
const _nodeutil = /*#__PURE__*/ _interop_require_default(require$$1);
const _noop = require$$2;
const _faststringarrayjoin = require$$3;
const _bitwise = require$$4;
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
var _computedKey;
const START = 1 << 1;
const INCLUDE_ALL_SUBDOMAIN = 1 << 2;
function deepTrieNodeToJSON(node, unpackMeta) {
const obj = {};
obj['[start]'] = (0, _bitwise.getBit)(node[0], START);
obj['[subdomain]'] = (0, _bitwise.getBit)(node[0], INCLUDE_ALL_SUBDOMAIN);
if (node[3] != null) {
if (unpackMeta) {
obj['[meta]'] = unpackMeta(node[3]);
} else {
obj['[meta]'] = node[3];
}
}
node[2].forEach((value, key)=>{
obj[key] = deepTrieNodeToJSON(value, unpackMeta);
});
return obj;
}
const createNode = (parent = null)=>[
1,
parent,
new Map(),
null
];
function hostnameToTokens(hostname, hostnameFromIndex) {
const tokens = hostname.split('.');
const results = [];
let token = '';
for(let i = hostnameFromIndex, l = tokens.length; i < l; i++){
token = tokens[i];
if (token.length > 0) {
results.push(token);
} else {
throw new TypeError(JSON.stringify({
hostname,
hostnameFromIndex
}, null, 2));
}
}
return results;
}
function walkHostnameTokens(hostname, onToken, hostnameFromIndex) {
const tokens = hostname.split('.');
const l = tokens.length - 1;
// we are at the first of hostname, no splitor there
let token = '';
for(let i = l; i >= hostnameFromIndex; i--){
token = tokens[i];
if (token.length > 0) {
const t = onToken(token);
if (t === null) {
return null;
}
// if the callback returns true, we should skip the rest
if (t) {
return true;
}
}
}
return false;
}
_computedKey = _nodeutil.default.inspect.custom;
class Triebase {
$root = createNode();
$size = 0;
get root() {
return this.$root;
}
constructor(from){
// Actually build trie
if (Array.isArray(from)) {
for(let i = 0, l = from.length; i < l; i++){
this.add(from[i]);
}
} else if (from) {
from.forEach((value)=>this.add(value));
}
}
walkIntoLeafWithTokens(tokens, onLoop = _noop.noop) {
let node = this.$root;
let parent = node;
let token;
let child = node[2];
// reverse lookup from end to start
for(let i = tokens.length - 1; i >= 0; i--){
token = tokens[i];
// if (token === '') {
// break;
// }
parent = node;
child = node[2];
// cache node index access is 20% faster than direct access when doing twice
if (child.has(token)) {
node = child.get(token);
} else {
return null;
}
onLoop(node, parent, token);
}
return {
node,
parent
};
}
walkIntoLeafWithSuffix(suffix, hostnameFromIndex, onLoop = _noop.noop) {
let node = this.$root;
let parent = node;
let child = node[2];
const onToken = (token)=>{
// if (token === '') {
// return true;
// }
parent = node;
child = node[2];
if (child.has(token)) {
node = child.get(token);
} else {
return null;
}
onLoop(node, parent, token);
return false;
};
if (walkHostnameTokens(suffix, onToken, hostnameFromIndex) === null) {
return null;
}
return {
node,
parent
};
}
contains(suffix, includeAllSubdomain = suffix[0] === '.') {
const hostnameFromIndex = suffix[0] === '.' ? 1 : 0;
const res = this.walkIntoLeafWithSuffix(suffix, hostnameFromIndex);
if (!res) return false;
if (includeAllSubdomain) return (0, _bitwise.getBit)(res.node[0], INCLUDE_ALL_SUBDOMAIN);
return true;
}
static bfsResults = [
null,
[]
];
static dfs(nodeStack, suffixStack) {
const node = nodeStack.pop();
const suffix = suffixStack.pop();
node[2].forEach((childNode, k)=>{
// Pushing the child node to the stack for next iteration of DFS
nodeStack.push(childNode);
suffixStack.push([
k,
...suffix
]);
});
Triebase.bfsResults[0] = node;
Triebase.bfsResults[1] = suffix;
return Triebase.bfsResults;
}
static dfsWithSort(nodeStack, suffixStack) {
const node = nodeStack.pop();
const suffix = suffixStack.pop();
const child = node[2];
if (child.size) {
const keys = Array.from(child.keys()).sort(Triebase.compare);
for(let i = 0, l = keys.length; i < l; i++){
const key = keys[i];
const childNode = child.get(key);
// Pushing the child node to the stack for next iteration of DFS
nodeStack.push(childNode);
suffixStack.push([
key,
...suffix
]);
}
}
Triebase.bfsResults[0] = node;
Triebase.bfsResults[1] = suffix;
return Triebase.bfsResults;
}
walk(onMatches, initialNode = this.$root, initialSuffix = [], withSort = false) {
const bfsImpl = withSort ? Triebase.dfsWithSort : Triebase.dfs;
const nodeStack = [];
nodeStack.push(initialNode);
// Resolving initial string (begin the start of the stack)
const suffixStack = [];
suffixStack.push(initialSuffix);
let node = initialNode;
let r;
do {
r = bfsImpl(nodeStack, suffixStack);
node = r[0];
const suffix = r[1];
// If the node is a sentinel, we push the suffix to the results
if ((0, _bitwise.getBit)(node[0], START)) {
onMatches(suffix, (0, _bitwise.getBit)(node[0], INCLUDE_ALL_SUBDOMAIN), node[3]);
}
}while (nodeStack.length)
}
static compare(a, b) {
if (a === b) return 0;
return a.length - b.length || (0, _misc.fastStringCompare)(a, b);
}
walkWithSort(onMatches, initialNode = this.$root, initialSuffix = []) {
const nodeStack = [];
nodeStack.push(initialNode);
// Resolving initial string (begin the start of the stack)
const suffixStack = [];
suffixStack.push(initialSuffix);
let node = initialNode;
let child = node[2];
do {
node = nodeStack.pop();
const suffix = suffixStack.pop();
child = node[2];
if (child.size) {
const keys = Array.from(child.keys()).sort(Triebase.compare);
for(let i = 0, l = keys.length; i < l; i++){
const key = keys[i];
const childNode = child.get(key);
// Pushing the child node to the stack for next iteration of DFS
nodeStack.push(childNode);
suffixStack.push([
key,
...suffix
]);
}
}
// If the node is a sentinel, we push the suffix to the results
if ((0, _bitwise.getBit)(node[0], START)) {
onMatches(suffix, (0, _bitwise.getBit)(node[0], INCLUDE_ALL_SUBDOMAIN), node[3]);
}
}while (nodeStack.length)
}
getSingleChildLeaf(tokens) {
let toPrune = null;
let tokenToPrune = null;
const onLoop = (node, parent, token)=>{
// Keeping track of a potential branch to prune
const child = node[2];
// console.log({
// child, parent, token
// });
// console.log(this.inspect(0));
if (toPrune !== null) {
if (child.size > 1) {
// The branch has some children, the branch need retain.
// And we need to abort prune that parent branch, so we set it to null
toPrune = null;
tokenToPrune = null;
}
} else if (child.size < 1) {
// There is only one token child, or no child at all, we can prune it safely
// It is now the top-est branch that could potentially being pruned
toPrune = parent;
tokenToPrune = token;
}
};
const res = this.walkIntoLeafWithTokens(tokens, onLoop);
if (res === null) return null;
return {
node: res.node,
toPrune,
tokenToPrune,
parent: res.parent
};
}
/**
* Method used to retrieve every item in the trie with the given prefix.
*/ find(inputSuffix, subdomainOnly = inputSuffix[0] === '.', hostnameFromIndex = inputSuffix[0] === '.' ? 1 : 0) {
const inputTokens = hostnameToTokens(inputSuffix, hostnameFromIndex);
const res = this.walkIntoLeafWithTokens(inputTokens);
if (res === null) return [];
const results = [];
const onMatches = subdomainOnly ? (suffix, subdomain)=>{
const d = (0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.');
if (!subdomain && subStringEqual(inputSuffix, d, 1)) return;
results.push(subdomain ? '.' + d : d);
} : (suffix, subdomain)=>{
const d = (0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.');
results.push(subdomain ? '.' + d : d);
};
this.walk(onMatches, res.node, inputTokens);
return results;
}
/**
* Method used to delete a prefix from the trie.
*/ remove(suffix) {
const res = this.getSingleChildLeaf(hostnameToTokens(suffix, 0));
if (res === null) return false;
if ((0, _bitwise.missingBit)(res.node[0], START)) return false;
this.$size--;
const { node, toPrune, tokenToPrune } = res;
if (tokenToPrune && toPrune) {
toPrune[2].delete(tokenToPrune);
} else {
node[0] = (0, _bitwise.deleteBit)(node[0], START);
}
return true;
}
// eslint-disable-next-line @typescript-eslint/unbound-method -- safe
delete = this.remove;
/**
* Method used to assert whether the given prefix exists in the Trie.
*/ has(suffix, includeAllSubdomain = suffix[0] === '.') {
const hostnameFromIndex = suffix[0] === '.' ? 1 : 0;
const res = this.walkIntoLeafWithSuffix(suffix, hostnameFromIndex);
if (res === null) return false;
if ((0, _bitwise.missingBit)(res.node[0], START)) return false;
if (includeAllSubdomain) return (0, _bitwise.getBit)(res.node[0], INCLUDE_ALL_SUBDOMAIN);
return true;
}
dumpWithoutDot(onSuffix, withSort = false) {
const handleSuffix = (suffix, subdomain)=>{
onSuffix((0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.'), subdomain);
};
if (withSort) {
this.walkWithSort(handleSuffix);
} else {
this.walk(handleSuffix);
}
}
dump(onSuffix, withSort = false) {
const results = [];
const handleSuffix = onSuffix ? (suffix, subdomain)=>{
const d = (0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.');
onSuffix(subdomain ? '.' + d : d);
} : (suffix, subdomain)=>{
const d = (0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.');
results.push(subdomain ? '.' + d : d);
};
if (withSort) {
this.walkWithSort(handleSuffix);
} else {
this.walk(handleSuffix);
}
return results;
}
dumpMeta(onMeta, withSort = false) {
const results = [];
const handleMeta = onMeta ? (_suffix, _subdomain, meta)=>onMeta(meta) : (_suffix, _subdomain, meta)=>results.push(meta);
if (withSort) {
this.walkWithSort(handleMeta);
} else {
this.walk(handleMeta);
}
return results;
}
dumpWithMeta(onSuffix, withSort = false) {
const results = [];
const handleSuffix = onSuffix ? (suffix, subdomain, meta)=>{
const d = (0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.');
return onSuffix(subdomain ? '.' + d : d, meta);
} : (suffix, subdomain, meta)=>{
const d = (0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.');
results.push([
subdomain ? '.' + d : d,
meta
]);
};
if (withSort) {
this.walkWithSort(handleSuffix);
} else {
this.walk(handleSuffix);
}
return results;
}
inspect(depth, unpackMeta) {
return (0, _faststringarrayjoin.fastStringArrayJoin)(JSON.stringify(deepTrieNodeToJSON(this.$root, unpackMeta), null, 2).split('\n').map((line)=>' '.repeat(depth) + line), '\n');
}
[_computedKey](depth) {
return this.inspect(depth);
}
merge(trie) {
const handleSuffix = (suffix, subdomain, meta)=>{
this.add((0, _faststringarrayjoin.fastStringArrayJoin)(suffix, '.'), subdomain, meta);
};
trie.walk(handleSuffix);
return this;
}
}
class HostnameSmolTrie extends Triebase {
smolTree = true;
add(suffix, includeAllSubdomain = suffix[0] === '.', meta, hostnameFromIndex = suffix[0] === '.' ? 1 : 0) {
let node = this.$root;
let curNodeChildren = node[2];
const onToken = (token)=>{
curNodeChildren = node[2];
if (curNodeChildren.has(token)) {
node = curNodeChildren.get(token);
// During the adding of `[start]blog|.skk.moe` and find out that there is a `[start].skk.moe` in the trie, skip adding the rest of the node
if ((0, _bitwise.getBit)(node[0], INCLUDE_ALL_SUBDOMAIN)) {
return true;
}
} else {
const newNode = createNode(node);
curNodeChildren.set(token, newNode);
node = newNode;
}
return false;
};
// When walkHostnameTokens returns true, we should skip the rest
if (walkHostnameTokens(suffix, onToken, hostnameFromIndex)) {
return;
}
// If we are in smolTree mode, we need to do something at the end of the loop
if (includeAllSubdomain) {
// Trying to add `[.]sub.example.com` where there is already a `blog.sub.example.com` in the trie
// Make sure parent `[start]sub.example.com` (without dot) is removed (SETINEL to false)
// (/** parent */ node[2]!)[0] = false;
// Removing the rest of the parent's child nodes
node[2].clear();
// The SENTINEL of this node will be set to true at the end of the function, so we don't need to set it here
// we can use else-if here, because the children is now empty, we don't need to check the leading "."
} else if ((0, _bitwise.getBit)(node[0], INCLUDE_ALL_SUBDOMAIN)) {
// Trying to add `example.com` when there is already a `.example.com` in the trie
// No need to increment size and set SENTINEL to true (skip this "new" item)
return;
}
node[0] = (0, _bitwise.setBit)(node[0], START);
if (includeAllSubdomain) {
node[0] = (0, _bitwise.setBit)(node[0], INCLUDE_ALL_SUBDOMAIN);
} else {
node[0] = (0, _bitwise.deleteBit)(node[0], INCLUDE_ALL_SUBDOMAIN);
}
node[3] = meta;
}
whitelist(suffix, includeAllSubdomain = suffix[0] === '.', hostnameFromIndex = suffix[0] === '.' ? 1 : 0) {
const tokens = hostnameToTokens(suffix, hostnameFromIndex);
const res = this.getSingleChildLeaf(tokens);
if (res === null) return;
const { node, toPrune, tokenToPrune } = res;
// Trying to whitelist `[start].sub.example.com` where there might already be a `[start]blog.sub.example.com` in the trie
if (includeAllSubdomain) {
// If there is a `[start]sub.example.com` here, remove it
node[0] = (0, _bitwise.deleteBit)(node[0], INCLUDE_ALL_SUBDOMAIN);
node[0] = (0, _bitwise.deleteBit)(node[0], START);
// Removing all the child nodes by empty the children
node[2].clear();
} else {
// Trying to whitelist `example.com` when there is already a `.example.com` in the trie
node[0] = (0, _bitwise.deleteBit)(node[0], INCLUDE_ALL_SUBDOMAIN);
}
// return early if not found
if ((0, _bitwise.missingBit)(node[0], START)) return;
if (toPrune && tokenToPrune) {
toPrune[2].delete(tokenToPrune);
} else {
node[0] = (0, _bitwise.deleteBit)(node[0], START);
}
}
}
class HostnameTrie extends Triebase {
get size() {
return this.$size;
}
add(suffix, includeAllSubdomain = suffix[0] === '.', meta, hostnameFromIndex = suffix[0] === '.' ? 1 : 0) {
let node = this.$root;
let child = node[2];
const onToken = (token)=>{
child = node[2];
if (child.has(token)) {
node = child.get(token);
} else {
const newNode = createNode(node);
child.set(token, newNode);
node = newNode;
}
return false;
};
// When walkHostnameTokens returns true, we should skip the rest
if (walkHostnameTokens(suffix, onToken, hostnameFromIndex)) {
return;
}
// if same entry has been added before, skip
if ((0, _bitwise.getBit)(node[0], START)) {
return;
}
this.$size++;
node[0] = (0, _bitwise.setBit)(node[0], START);
if (includeAllSubdomain) {
node[0] = (0, _bitwise.setBit)(node[0], INCLUDE_ALL_SUBDOMAIN);
} else {
node[0] = (0, _bitwise.deleteBit)(node[0], INCLUDE_ALL_SUBDOMAIN);
}
node[3] = meta;
}
}
// function deepEqualArray(a: string[], b: string[]) {
// let len = a.length;
// if (len !== b.length) return false;
// while (len--) {
// if (a[len] !== b[len]) return false;
// }
// return true;
// };
function subStringEqual(needle, haystack, needleIndex = 0) {
for(let i = 0, l = haystack.length; i < l; i++){
if (needle[i + needleIndex] !== haystack[i]) return false;
}
return true;
}
} (trie.__exports));
return trie.__exports;
}exports.__require=requireTrie;

View File

@@ -0,0 +1,113 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const adguardhome=require('../../../_virtual/adguardhome.cjs'),require$$0=require('foxts/escape-string-regexp'),base=require('./base.cjs'),require$$2=require('foxts/noop'),misc=require('../misc.cjs');var hasRequiredAdguardhome;
function requireAdguardhome () {
if (hasRequiredAdguardhome) return adguardhome.__exports;
hasRequiredAdguardhome = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "AdGuardHome", {
enumerable: true,
get: function() {
return AdGuardHome;
}
});
const _escapestringregexp = require$$0;
const _base = /*@__PURE__*/ base.__require();
const _noop = require$$2;
const _misc = /*@__PURE__*/ misc.__require();
class AdGuardHome extends _base.BaseWriteStrategy {
// readonly type = 'domainset';
fileExtension = 'txt';
type = '';
result = [];
// eslint-disable-next-line @typescript-eslint/class-methods-use-this -- abstract method
withPadding(title, description, date, content) {
return [
`! Title: ${title}`,
'! Last modified: ' + date.toUTCString(),
'! Expires: 6 hours',
'! License: https://github.com/SukkaW/Surge/blob/master/LICENSE',
'! Homepage: https://github.com/SukkaW/Surge',
`! Description: ${description.join(' ')}`,
'!',
...content,
'! EOF'
];
}
writeDomain(domain) {
this.result.push(`|${domain}^`);
}
// const whitelistArray = sortDomains(Array.from(whitelist));
// for (let i = 0, len = whitelistArray.length; i < len; i++) {
// const domain = whitelistArray[i];
// if (domain[0] === '.') {
// results.push(`@@||${domain.slice(1)}^`);
// } else {
// results.push(`@@|${domain}^`);
// }
// }
writeDomainSuffix(domain) {
this.result.push(`||${domain}^`);
}
writeDomainKeywords(keywords) {
for (const keyword of keywords){
// Use regex to match keyword
this.result.push(`/${(0, _escapestringregexp.escapeStringRegexp)(keyword)}/`);
}
}
writeDomainWildcards(wildcards) {
for (const wildcard of wildcards){
const processed = wildcard.replaceAll('?', '*');
if (processed.startsWith('*.')) {
this.result.push(`||${processed.slice(2)}^`);
} else {
this.result.push(`|${processed}^`);
}
}
}
writeUserAgents = _noop.noop;
writeProcessNames = _noop.noop;
writeProcessPaths = _noop.noop;
writeUrlRegexes = _noop.noop;
writeIpCidrs(ipGroup, noResolve) {
if (noResolve) {
// When IP is provided to AdGuardHome, any domain resolve to those IP will be blocked
// So we can't do noResolve
return;
}
for (const ipcidr of ipGroup){
if (ipcidr.endsWith('/32')) {
this.result.push(`||${ipcidr.slice(0, -3)}`);
/* else if (ipcidr.endsWith('.0/24')) {
results.push(`||${ipcidr.slice(0, -6)}.*`);
} */ } else {
this.result.push(`||${ipcidr}^`);
}
}
}
writeIpCidr6s(ipGroup, noResolve) {
if (noResolve) {
// When IP is provided to AdGuardHome, any domain resolve to those IP will be blocked
// So we can't do noResolve
return;
}
for (const ipcidr of ipGroup){
if (ipcidr.endsWith('/128')) {
this.result.push(`||${ipcidr.slice(0, -4)}`);
} else {
this.result.push(`||${ipcidr}`);
}
}
}
writeGeoip = (0, _misc.notSupported)('writeGeoip');
writeIpAsns = (0, _misc.notSupported)('writeIpAsns');
writeSourceIpCidrs = (0, _misc.notSupported)('writeSourceIpCidrs');
writeSourcePorts = (0, _misc.notSupported)('writeSourcePorts');
writeDestinationPorts = _noop.noop;
writeOtherRules = _noop.noop;
}
} (adguardhome.__exports));
return adguardhome.__exports;
}exports.__require=requireAdguardhome;

View File

@@ -0,0 +1,63 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const base=require('../../../_virtual/base2.cjs'),createFile=require('../create-file.cjs');var hasRequiredBase;
function requireBase () {
if (hasRequiredBase) return base.__exports;
hasRequiredBase = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "BaseWriteStrategy", {
enumerable: true,
get: function() {
return BaseWriteStrategy;
}
});
const _createfile = /*@__PURE__*/ createFile.__require();
class BaseWriteStrategy {
outputDir;
/**
* Sometimes a ruleset will create extra files (e.g. reject-url-regex w/ mitm.sgmodule),
* and doesn't share the same filename and id. This property is used to overwrite the filename.
*/ overwriteFilename;
withFilename(filename) {
this.overwriteFilename = filename;
return this;
}
constructor(outputDir){
this.outputDir = outputDir;
this.overwriteFilename = null;
}
static domainWildCardToRegex = (domain)=>{
let result = '^';
for(let i = 0, len = domain.length; i < len; i++){
switch(domain[i]){
case '.':
result += String.raw`\.`;
break;
case '*':
result += String.raw`[\w.-]*?`;
break;
case '?':
result += String.raw`[\w.-]`;
break;
default:
result += domain[i];
}
}
result += '$';
return result;
};
output(span, title, description, date, filePath) {
if (!this.result) {
return;
}
return (0, _createfile.compareAndWriteFile)(span, this.withPadding(title, description, date, this.result), filePath);
}
get content() {
return this.result;
}
}
} (base.__exports));
return base.__exports;
}exports.__require=requireBase;

View File

@@ -0,0 +1,172 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const clash=require('../../../_virtual/clash.cjs'),require$$0=require('foxts/append-set-elements-to-array'),base=require('./base.cjs'),require$$2=require('foxts/noop'),misc=require('../misc.cjs'),dir=require('../../constants/dir.cjs'),appendArrayInPlace=require('../append-array-in-place.cjs');var hasRequiredClash;
function requireClash () {
if (hasRequiredClash) return clash.__exports;
hasRequiredClash = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
ClashClassicRuleSet: function() {
return ClashClassicRuleSet;
},
ClashDomainSet: function() {
return ClashDomainSet;
},
ClashIPSet: function() {
return ClashIPSet;
}
});
const _appendsetelementstoarray = require$$0;
const _base = /*@__PURE__*/ base.__require();
const _noop = require$$2;
const _misc = /*@__PURE__*/ misc.__require();
const _dir = /*@__PURE__*/ dir.__require();
const _appendarrayinplace = /*@__PURE__*/ appendArrayInPlace.__require();
class ClashDomainSet extends _base.BaseWriteStrategy {
outputDir;
// readonly type = 'domainset';
fileExtension;
type;
result;
constructor(outputDir = _dir.OUTPUT_CLASH_DIR){
super(outputDir), this.outputDir = outputDir, this.fileExtension = 'txt', this.type = 'domainset', this.result = [
'this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'
], this.withPadding = _misc.withBannerArray, this.writeDomainKeywords = _noop.noop, this.writeDomainWildcards = _noop.noop, this.writeUserAgents = _noop.noop, this.writeProcessNames = _noop.noop, this.writeProcessPaths = _noop.noop, this.writeUrlRegexes = _noop.noop, this.writeIpCidrs = _noop.noop, this.writeIpCidr6s = _noop.noop, this.writeGeoip = _noop.noop, this.writeIpAsns = _noop.noop, this.writeSourceIpCidrs = _noop.noop, this.writeSourcePorts = _noop.noop, this.writeDestinationPorts = _noop.noop, this.writeOtherRules = _noop.noop;
}
withPadding;
writeDomain(domain) {
this.result.push(domain);
}
writeDomainSuffix(domain) {
this.result.push('+.' + domain);
}
writeDomainKeywords;
writeDomainWildcards;
writeUserAgents;
writeProcessNames;
writeProcessPaths;
writeUrlRegexes;
writeIpCidrs;
writeIpCidr6s;
writeGeoip;
writeIpAsns;
writeSourceIpCidrs;
writeSourcePorts;
writeDestinationPorts;
writeOtherRules;
}
class ClashIPSet extends _base.BaseWriteStrategy {
outputDir;
// readonly type = 'domainset';
fileExtension;
type;
result;
constructor(outputDir = _dir.OUTPUT_CLASH_DIR){
super(outputDir), this.outputDir = outputDir, this.fileExtension = 'txt', this.type = 'ip', this.result = [], this.withPadding = _misc.withBannerArray, this.writeDomain = (0, _misc.notSupported)('writeDomain'), this.writeDomainSuffix = (0, _misc.notSupported)('writeDomainSuffix'), this.writeDomainKeywords = (0, _misc.notSupported)('writeDomainKeywords'), this.writeDomainWildcards = (0, _misc.notSupported)('writeDomainWildcards'), this.writeUserAgents = (0, _misc.notSupported)('writeUserAgents'), this.writeProcessNames = (0, _misc.notSupported)('writeProcessNames'), this.writeProcessPaths = (0, _misc.notSupported)('writeProcessPaths'), this.writeUrlRegexes = (0, _misc.notSupported)('writeUrlRegexes'), this.writeGeoip = (0, _misc.notSupported)('writeGeoip'), this.writeIpAsns = (0, _misc.notSupported)('writeIpAsns'), this.writeSourceIpCidrs = (0, _misc.notSupported)('writeSourceIpCidrs'), this.writeSourcePorts = (0, _misc.notSupported)('writeSourcePorts'), this.writeDestinationPorts = _noop.noop, this.writeOtherRules = _noop.noop;
}
withPadding;
writeDomain;
writeDomainSuffix;
writeDomainKeywords;
writeDomainWildcards;
writeUserAgents;
writeProcessNames;
writeProcessPaths;
writeUrlRegexes;
writeIpCidrs(ipCidr) {
(0, _appendarrayinplace.appendArrayInPlace)(this.result, ipCidr);
}
writeIpCidr6s(ipCidr6) {
(0, _appendarrayinplace.appendArrayInPlace)(this.result, ipCidr6);
}
writeGeoip;
writeIpAsns;
writeSourceIpCidrs;
writeSourcePorts;
writeDestinationPorts;
writeOtherRules;
}
class ClashClassicRuleSet extends _base.BaseWriteStrategy {
type;
outputDir;
fileExtension;
result;
constructor(type/* | (string & {}) */ , outputDir = _dir.OUTPUT_CLASH_DIR){
super(outputDir), this.type = type, this.outputDir = outputDir, this.fileExtension = 'txt', this.result = [
'DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'
], this.withPadding = _misc.withBannerArray, this.writeUserAgents = _noop.noop, this.writeUrlRegexes = _noop.noop, this.writeOtherRules = _noop.noop;
}
withPadding;
writeDomain(domain) {
this.result.push('DOMAIN,' + domain);
}
writeDomainSuffix(domain) {
this.result.push('DOMAIN-SUFFIX,' + domain);
}
writeDomainKeywords(keyword) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, keyword, (i)=>`DOMAIN-KEYWORD,${i}`);
}
writeDomainWildcards(wildcard) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, wildcard, (i)=>`DOMAIN-REGEX,${ClashClassicRuleSet.domainWildCardToRegex(i)}`);
}
writeUserAgents;
writeProcessNames(processName) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, processName, (i)=>`PROCESS-NAME,${i}`);
}
writeProcessPaths(processPath) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, processPath, (i)=>`PROCESS-PATH,${i}`);
}
writeUrlRegexes;
writeIpCidrs(ipCidr, noResolve) {
for(let i = 0, len = ipCidr.length; i < len; i++){
this.result.push(`IP-CIDR,${ipCidr[i]}${noResolve ? ',no-resolve' : ''}`);
}
}
writeIpCidr6s(ipCidr6, noResolve) {
for(let i = 0, len = ipCidr6.length; i < len; i++){
this.result.push(`IP-CIDR6,${ipCidr6[i]}${noResolve ? ',no-resolve' : ''}`);
}
}
writeGeoip(geoip, noResolve) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, geoip, (i)=>`GEOIP,${i}${noResolve ? ',no-resolve' : ''}`);
}
writeIpAsns(asns, noResolve) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, asns, (i)=>`IP-ASN,${i}${noResolve ? ',no-resolve' : ''}`);
}
writeSourceIpCidrs(sourceIpCidr) {
for(let i = 0, len = sourceIpCidr.length; i < len; i++){
const value = sourceIpCidr[i];
if (value.includes('/')) {
this.result.push(`SRC-IP-CIDR,${value}`);
continue;
}
const v = (0, _misc.fastIpVersion)(value);
if (v === 4) {
this.result.push(`SRC-IP-CIDR,${value}/32`);
continue;
}
if (v === 6) {
this.result.push(`SRC-IP-CIDR6,${value}/128`);
continue;
}
}
}
writeSourcePorts(port) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, port, (i)=>`SRC-PORT,${i}`);
}
writeDestinationPorts(port) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, port, (i)=>`DST-PORT,${i}`);
}
writeOtherRules;
}
} (clash.__exports));
return clash.__exports;
}exports.__require=requireClash;

View File

@@ -0,0 +1,121 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const singbox=require('../../../_virtual/singbox.cjs'),base=require('./base.cjs'),appendArrayInPlace=require('../append-array-in-place.cjs'),require$$2=require('foxts/noop'),misc=require('../misc.cjs'),require$$4=require('json-stringify-pretty-compact'),dir=require('../../constants/dir.cjs');var hasRequiredSingbox;
function requireSingbox () {
if (hasRequiredSingbox) return singbox.__exports;
hasRequiredSingbox = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "SingboxSource", {
enumerable: true,
get: function() {
return SingboxSource;
}
});
const _base = /*@__PURE__*/ base.__require();
const _appendarrayinplace = /*@__PURE__*/ appendArrayInPlace.__require();
const _noop = require$$2;
const _misc = /*@__PURE__*/ misc.__require();
const _jsonstringifyprettycompact = /*#__PURE__*/ _interop_require_default(require$$4);
const _dir = /*@__PURE__*/ dir.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class SingboxSource extends _base.BaseWriteStrategy {
type;
outputDir;
fileExtension;
static jsonToLines = (json)=>(0, _jsonstringifyprettycompact.default)(json).split('\n');
singbox;
get result() {
return SingboxSource.jsonToLines({
version: 2,
rules: [
this.singbox
]
});
}
constructor(/** Since sing-box only have one format that does not reflect type, we need to specify it */ type/* | (string & {}) */ , outputDir = _dir.OUTPUT_SINGBOX_DIR){
super(outputDir), this.type = type, this.outputDir = outputDir, this.fileExtension = 'json', this.singbox = {
domain: [
'this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'
],
domain_suffix: [
'this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'
]
}, this.withPadding = _misc.withIdentityContent, this.writeUserAgents = _noop.noop, this.writeUrlRegexes = _noop.noop, this.writeGeoip = _noop.noop, this.writeIpAsns = _noop.noop, this.writeOtherRules = _noop.noop;
}
withPadding;
writeDomain(domain) {
this.singbox.domain.push(domain);
}
writeDomainSuffix(domain) {
this.singbox.domain_suffix.push(domain);
}
writeDomainKeywords(keyword) {
(0, _appendarrayinplace.appendArrayInPlace)(this.singbox.domain_keyword ??= [], Array.from(keyword));
}
writeDomainWildcards(wildcard) {
(0, _appendarrayinplace.appendArrayInPlace)(this.singbox.domain_regex ??= [], Array.from(wildcard, SingboxSource.domainWildCardToRegex));
}
writeUserAgents;
writeProcessNames(processName) {
(0, _appendarrayinplace.appendArrayInPlace)(this.singbox.process_name ??= [], Array.from(processName));
}
writeProcessPaths(processPath) {
(0, _appendarrayinplace.appendArrayInPlace)(this.singbox.process_path ??= [], Array.from(processPath));
}
writeUrlRegexes;
writeIpCidrs(ipCidr) {
(0, _appendarrayinplace.appendArrayInPlace)(this.singbox.ip_cidr ??= [], ipCidr);
}
writeIpCidr6s(ipCidr6) {
(0, _appendarrayinplace.appendArrayInPlace)(this.singbox.ip_cidr ??= [], ipCidr6);
}
writeGeoip;
writeIpAsns;
writeSourceIpCidrs(sourceIpCidr) {
this.singbox.source_ip_cidr ??= [];
for(let i = 0, len = sourceIpCidr.length; i < len; i++){
const value = sourceIpCidr[i];
if (value.includes('/')) {
this.singbox.source_ip_cidr.push(value);
continue;
}
const v = (0, _misc.fastIpVersion)(value);
if (v === 4) {
this.singbox.source_ip_cidr.push(`${value}/32`);
continue;
}
if (v === 6) {
this.singbox.source_ip_cidr.push(`${value}/128`);
continue;
}
}
}
writeSourcePorts(port) {
this.singbox.source_port ??= [];
for (const i of port){
const tmp = Number(i);
if (!Number.isNaN(tmp)) {
this.singbox.source_port.push(tmp);
}
}
}
writeDestinationPorts(port) {
this.singbox.port ??= [];
for (const i of port){
const tmp = Number(i);
if (!Number.isNaN(tmp)) {
this.singbox.port.push(tmp);
}
}
}
writeOtherRules;
}
} (singbox.__exports));
return singbox.__exports;
}exports.__require=requireSingbox;

View File

@@ -0,0 +1,246 @@
'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const surge=require('../../../_virtual/surge.cjs'),require$$0=require('foxts/append-set-elements-to-array'),base=require('./base.cjs'),appendArrayInPlace=require('../append-array-in-place.cjs'),require$$2=require('foxts/noop'),require$$2$1=require('foxts/is-probably-ip'),require$$0$1=require('picocolors'),normalizeDomain=require('../normalize-domain.cjs'),dir=require('../../constants/dir.cjs'),misc=require('../misc.cjs');var hasRequiredSurge;
function requireSurge () {
if (hasRequiredSurge) return surge.__exports;
hasRequiredSurge = 1;
(function (exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
SurgeDomainSet: function() {
return SurgeDomainSet;
},
SurgeMitmSgmodule: function() {
return SurgeMitmSgmodule;
},
SurgeRuleSet: function() {
return SurgeRuleSet;
}
});
const _appendsetelementstoarray = require$$0;
const _base = /*@__PURE__*/ base.__require();
const _appendarrayinplace = /*@__PURE__*/ appendArrayInPlace.__require();
const _noop = require$$2;
const _isprobablyip = require$$2$1;
const _picocolors = /*#__PURE__*/ _interop_require_default(require$$0$1);
const _normalizedomain = /*@__PURE__*/ normalizeDomain.__require();
const _dir = /*@__PURE__*/ dir.__require();
const _misc = /*@__PURE__*/ misc.__require();
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class SurgeDomainSet extends _base.BaseWriteStrategy {
// readonly type = 'domainset';
fileExtension = 'conf';
type = 'domainset';
result = [
'this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'
];
constructor(outputDir = _dir.OUTPUT_SURGE_DIR){
super(outputDir);
}
withPadding = _misc.withBannerArray;
writeDomain(domain) {
this.result.push(domain);
}
writeDomainSuffix(domain) {
this.result.push('.' + domain);
}
writeDomainKeywords = _noop.noop;
writeDomainWildcards = _noop.noop;
writeUserAgents = _noop.noop;
writeProcessNames = _noop.noop;
writeProcessPaths = _noop.noop;
writeUrlRegexes = _noop.noop;
writeIpCidrs = _noop.noop;
writeIpCidr6s = _noop.noop;
writeGeoip = _noop.noop;
writeIpAsns = _noop.noop;
writeSourceIpCidrs = _noop.noop;
writeSourcePorts = _noop.noop;
writeDestinationPorts = _noop.noop;
writeOtherRules = _noop.noop;
}
class SurgeRuleSet extends _base.BaseWriteStrategy {
type;
outputDir;
fileExtension;
result;
constructor(/** Surge RULE-SET can be both ip or non_ip, so this needs to be specified */ type, outputDir = _dir.OUTPUT_SURGE_DIR){
super(outputDir), this.type = type, this.outputDir = outputDir, this.fileExtension = 'conf', this.result = [
'DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'
], this.withPadding = _misc.withBannerArray;
}
withPadding;
writeDomain(domain) {
this.result.push('DOMAIN,' + domain);
}
writeDomainSuffix(domain) {
this.result.push('DOMAIN-SUFFIX,' + domain);
}
writeDomainKeywords(keyword) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, keyword, (i)=>`DOMAIN-KEYWORD,${i}`);
}
writeDomainWildcards(wildcard) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, wildcard, (i)=>`DOMAIN-WILDCARD,${i}`);
}
writeUserAgents(userAgent) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, userAgent, (i)=>`USER-AGENT,${i}`);
}
writeProcessNames(processName) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, processName, (i)=>`PROCESS-NAME,${i}`);
}
writeProcessPaths(processPath) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, processPath, (i)=>`PROCESS-NAME,${i}`);
}
writeUrlRegexes(urlRegex) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, urlRegex, (i)=>`URL-REGEX,${i}`);
}
writeIpCidrs(ipCidr, noResolve) {
for(let i = 0, len = ipCidr.length; i < len; i++){
this.result.push(`IP-CIDR,${ipCidr[i]}${noResolve ? ',no-resolve' : ''}`);
}
}
writeIpCidr6s(ipCidr6, noResolve) {
for(let i = 0, len = ipCidr6.length; i < len; i++){
this.result.push(`IP-CIDR6,${ipCidr6[i]}${noResolve ? ',no-resolve' : ''}`);
}
}
writeGeoip(geoip, noResolve) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, geoip, (i)=>`GEOIP,${i}${noResolve ? ',no-resolve' : ''}`);
}
writeIpAsns(asns, noResolve) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, asns, (i)=>`IP-ASN,${i}${noResolve ? ',no-resolve' : ''}`);
}
writeSourceIpCidrs(sourceIpCidr) {
for(let i = 0, len = sourceIpCidr.length; i < len; i++){
this.result.push(`SRC-IP,${sourceIpCidr[i]}`);
}
}
writeSourcePorts(port) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, port, (i)=>`SRC-PORT,${i}`);
}
writeDestinationPorts(port) {
(0, _appendsetelementstoarray.appendSetElementsToArray)(this.result, port, (i)=>`DEST-PORT,${i}`);
}
writeOtherRules(rule) {
(0, _appendarrayinplace.appendArrayInPlace)(this.result, rule);
}
}
class SurgeMitmSgmodule extends _base.BaseWriteStrategy {
// readonly type = 'domainset';
fileExtension = 'sgmodule';
type = '';
rules = new Set();
get result() {
if (this.rules.size === 0) {
return null;
}
return [
'#!name=[Sukka] Surge Reject MITM',
`#!desc=为 URL Regex 规则组启用 MITM (size: ${this.rules.size})`,
'',
'[MITM]',
'hostname = %APPEND% ' + Array.from(this.rules).join(', ')
];
}
withPadding = _misc.withIdentityContent;
constructor(moduleName, outputDir = _dir.OUTPUT_MODULES_DIR){
super(outputDir);
this.withFilename(moduleName);
}
writeDomain = _noop.noop;
writeDomainSuffix = _noop.noop;
writeDomainKeywords = _noop.noop;
writeDomainWildcards = _noop.noop;
writeUserAgents = _noop.noop;
writeProcessNames = _noop.noop;
writeProcessPaths = _noop.noop;
writeUrlRegexes(urlRegexes) {
const urlRegexResults = [];
const parsedFailures = [];
const parsed = [];
for (let urlRegex of urlRegexes){
if (urlRegex.startsWith('http://') || urlRegex.startsWith('^http://')) {
continue;
}
if (urlRegex.startsWith('^https?://')) {
urlRegex = urlRegex.slice(10);
}
if (urlRegex.startsWith('^https://')) {
urlRegex = urlRegex.slice(9);
}
const potentialHostname = urlRegex.split('/')[0]// pre process regex
.replaceAll(String.raw`\.`, '.').replaceAll('.+', '*').replaceAll(/([a-z])\?/g, '($1|)')// convert regex to surge hostlist syntax
.replaceAll('([a-z])', '?').replaceAll(String.raw`\d`, '?').replaceAll(/\*+/g, '*');
let processed = [
potentialHostname
];
const matches = [
...potentialHostname.matchAll(/\((?:([^()|]+)\|)+([^()|]*)\)/g)
];
if (matches.length > 0) {
const replaceVariant = (combinations, fullMatch, options)=>{
const newCombinations = [];
combinations.forEach((combination)=>{
options.forEach((option)=>{
newCombinations.push(combination.replace(fullMatch, option));
});
});
return newCombinations;
};
for(let i = 0; i < matches.length; i++){
const match = matches[i];
const [_, ...options] = match;
processed = replaceVariant(processed, _, options);
}
}
urlRegexResults.push({
origin: potentialHostname,
processed
});
}
for (const i of urlRegexResults){
for (const processed of i.processed){
if ((0, _normalizedomain.normalizeDomain)(processed.replaceAll('*', 'a').replaceAll('?', 'b'))) {
parsed.push([
i.origin,
processed
]);
} else if (!(0, _isprobablyip.isProbablyIpv4)(processed)) {
parsedFailures.push([
i.origin,
processed
]);
}
}
}
if (parsedFailures.length > 0) {
console.error(_picocolors.default.bold('Parsed Failed'));
console.table(parsedFailures);
}
for(let i = 0, len = parsed.length; i < len; i++){
this.rules.add(parsed[i][1]);
}
}
writeIpCidrs = _noop.noop;
writeIpCidr6s = _noop.noop;
writeGeoip = _noop.noop;
writeIpAsns = _noop.noop;
writeSourceIpCidrs = _noop.noop;
writeSourcePorts = _noop.noop;
writeDestinationPorts = _noop.noop;
writeOtherRules = _noop.noop;
}
} (surge.__exports));
return surge.__exports;
}exports.__require=requireSurge;