@tnid/filter 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +124 -0
- package/esm/blocklist.d.ts +41 -0
- package/esm/blocklist.d.ts.map +1 -0
- package/esm/blocklist.js +68 -0
- package/esm/filter.d.ts +51 -0
- package/esm/filter.d.ts.map +1 -0
- package/esm/filter.js +84 -0
- package/esm/filter_encryption.d.ts +52 -0
- package/esm/filter_encryption.d.ts.map +1 -0
- package/esm/filter_encryption.js +74 -0
- package/esm/index.d.ts +25 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +24 -0
- package/esm/internals.d.ts +35 -0
- package/esm/internals.d.ts.map +1 -0
- package/esm/internals.js +61 -0
- package/esm/package.json +3 -0
- package/package.json +46 -0
- package/script/blocklist.d.ts +41 -0
- package/script/blocklist.d.ts.map +1 -0
- package/script/blocklist.js +72 -0
- package/script/filter.d.ts +51 -0
- package/script/filter.d.ts.map +1 -0
- package/script/filter.js +90 -0
- package/script/filter_encryption.d.ts +52 -0
- package/script/filter_encryption.d.ts.map +1 -0
- package/script/filter_encryption.js +79 -0
- package/script/index.d.ts +25 -0
- package/script/index.d.ts.map +1 -0
- package/script/index.js +31 -0
- package/script/internals.d.ts +35 -0
- package/script/internals.d.ts.map +1 -0
- package/script/internals.js +71 -0
- package/script/package.json +3 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared internals for filter functions.
|
|
4
|
+
* @internal Not part of the public API.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.lastSafeTimestamp = exports.V1_RANDOM_BITS = exports.V0_RANDOM_BITS = exports.FIRST_CHAR_WITH_RANDOM = void 0;
|
|
8
|
+
exports.recordSafeTimestamp = recordSafeTimestamp;
|
|
9
|
+
exports.getStartingTimestamp = getStartingTimestamp;
|
|
10
|
+
exports.randomBigInt = randomBigInt;
|
|
11
|
+
exports.dataString = dataString;
|
|
12
|
+
exports.matchTouchesRandomPortion = matchTouchesRandomPortion;
|
|
13
|
+
exports.timestampBumpForChar = timestampBumpForChar;
|
|
14
|
+
exports.handleV0Match = handleV0Match;
|
|
15
|
+
// V0 data string character layout:
|
|
16
|
+
// Chars 0-6: pure timestamp bits
|
|
17
|
+
// Char 7: 1 timestamp bit + 2 variant bits + 3 random bits
|
|
18
|
+
// Chars 8-16: pure random bits
|
|
19
|
+
exports.FIRST_CHAR_WITH_RANDOM = 7;
|
|
20
|
+
exports.V0_RANDOM_BITS = 57;
|
|
21
|
+
exports.V1_RANDOM_BITS = 100;
|
|
22
|
+
/** Global last-known-safe timestamp to avoid re-discovering bad windows. */
|
|
23
|
+
exports.lastSafeTimestamp = 0n;
|
|
24
|
+
function recordSafeTimestamp(ts) {
|
|
25
|
+
if (ts > exports.lastSafeTimestamp) {
|
|
26
|
+
exports.lastSafeTimestamp = ts;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function getStartingTimestamp() {
|
|
30
|
+
const current = BigInt(Date.now());
|
|
31
|
+
return current > exports.lastSafeTimestamp ? current : exports.lastSafeTimestamp;
|
|
32
|
+
}
|
|
33
|
+
/** Generate a random bigint with the specified number of bits. */
|
|
34
|
+
function randomBigInt(bits) {
|
|
35
|
+
const bytes = new Uint8Array(Math.ceil(bits / 8));
|
|
36
|
+
crypto.getRandomValues(bytes);
|
|
37
|
+
let result = 0n;
|
|
38
|
+
for (const b of bytes)
|
|
39
|
+
result = (result << 8n) | BigInt(b);
|
|
40
|
+
return result & ((1n << BigInt(bits)) - 1n);
|
|
41
|
+
}
|
|
42
|
+
/** Extract the 17-char data string from a TNID string. */
|
|
43
|
+
function dataString(tnid) {
|
|
44
|
+
return tnid.substring(tnid.indexOf(".") + 1);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Check if a match touches the random portion of V0 data string.
|
|
48
|
+
* If true, regenerating random bits may resolve the match.
|
|
49
|
+
* If false, the match is entirely in the timestamp portion and requires bumping.
|
|
50
|
+
*/
|
|
51
|
+
function matchTouchesRandomPortion(start, length) {
|
|
52
|
+
return start + length > exports.FIRST_CHAR_WITH_RANDOM;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Minimum timestamp bump (in ms) needed to change the character at position `pos`.
|
|
56
|
+
* Each character encodes 6 bits. Lower positions = more significant = larger bump.
|
|
57
|
+
*/
|
|
58
|
+
function timestampBumpForChar(pos) {
|
|
59
|
+
return 1n << BigInt(42 - 6 * pos);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Handle a V0 blocklist match: bump timestamp if match is in timestamp portion.
|
|
63
|
+
* Returns the (possibly bumped) timestamp.
|
|
64
|
+
*/
|
|
65
|
+
function handleV0Match(match, timestamp) {
|
|
66
|
+
if (!matchTouchesRandomPortion(match.start, match.length)) {
|
|
67
|
+
const rightmostChar = match.start + match.length - 1;
|
|
68
|
+
return timestamp + timestampBumpForChar(rightmostChar);
|
|
69
|
+
}
|
|
70
|
+
return timestamp;
|
|
71
|
+
}
|