AUXteam commited on
Commit
fc44524
·
verified ·
1 Parent(s): 5b73436

Upload folder using huggingface_hub

Browse files
.gitignore CHANGED
@@ -48,3 +48,5 @@ pinchtab.exe
48
  # E2E test results
49
  tests/e2e/results/*
50
  !tests/e2e/results/.gitkeep
 
 
 
48
  # E2E test results
49
  tests/e2e/results/*
50
  !tests/e2e/results/.gitkeep
51
+ !internal/assets/readability.js
52
+ !internal/assets/stealth.js
internal/assets/readability.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (() => {
2
+ const strip = ['nav', 'footer', 'aside', 'header', '[role="navigation"]',
3
+ '[role="banner"]', '[role="contentinfo"]', '[aria-hidden="true"]',
4
+ '.ad', '.ads', '.advertisement', '.sidebar', '.cookie-banner',
5
+ '#cookie-consent', '.popup', '.modal',
6
+ '#SIvCob', '[data-locale-picker]', '[role="listbox"]',
7
+ '#Lb4nn', '.language-selector', '.locale-selector',
8
+ '[data-language-picker]', '#langsec-button'];
9
+
10
+ let root = document.querySelector('article') ||
11
+ document.querySelector('[role="main"]') ||
12
+ document.querySelector('main');
13
+
14
+ if (!root) {
15
+ root = document.body.cloneNode(true);
16
+ for (const sel of strip) {
17
+ root.querySelectorAll(sel).forEach(el => el.remove());
18
+ }
19
+ } else {
20
+ root = root.cloneNode(true);
21
+ }
22
+
23
+ root.querySelectorAll('script, style, noscript, svg, [hidden]').forEach(el => el.remove());
24
+
25
+ return root.innerText.replace(/\n{3,}/g, '\n\n').trim();
26
+ })()
internal/assets/stealth.js ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const sessionSeed = (typeof __pinchtab_seed !== 'undefined') ? __pinchtab_seed : 42;
2
+
3
+ const seededRandom = (function() {
4
+ const cache = {};
5
+ return function(seed) {
6
+ if (cache[seed] !== undefined) return cache[seed];
7
+ let t = (seed + 0x6D2B79F5) | 0;
8
+ t = Math.imul(t ^ (t >>> 15), t | 1);
9
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
10
+ const result = ((t ^ (t >>> 14)) >>> 0) / 4294967296;
11
+ cache[seed] = result;
12
+ return result;
13
+ };
14
+ })();
15
+
16
+ // Webdriver evasion - hide the property completely
17
+ (function() {
18
+ const proto = Object.getPrototypeOf(navigator);
19
+
20
+ // Delete from both instance and prototype
21
+ try { delete navigator.webdriver; } catch(e) {}
22
+ try { delete proto.webdriver; } catch(e) {}
23
+
24
+ // If we can't delete, make it return undefined and be non-enumerable
25
+ // so 'webdriver' in navigator returns false
26
+ const desc = {
27
+ get: () => undefined,
28
+ configurable: false,
29
+ enumerable: false // Hide from 'in' operator and Object.keys
30
+ };
31
+
32
+ // Only define if it still exists after deletion
33
+ if ('webdriver' in navigator) {
34
+ try { Object.defineProperty(navigator, 'webdriver', desc); } catch(e) {}
35
+ }
36
+ if ('webdriver' in proto) {
37
+ try { Object.defineProperty(proto, 'webdriver', desc); } catch(e) {}
38
+ }
39
+ })();
40
+
41
+ delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
42
+ delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
43
+ delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
44
+
45
+ if (!window.chrome) { window.chrome = {}; }
46
+ if (!window.chrome.runtime) {
47
+ window.chrome.runtime = {
48
+ onConnect: undefined,
49
+ onMessage: undefined
50
+ };
51
+ }
52
+
53
+ const originalQuery = window.navigator.permissions.query;
54
+ window.navigator.permissions.query = (parameters) => (
55
+ parameters.name === 'notifications' ?
56
+ Promise.resolve({ state: Notification.permission }) :
57
+ originalQuery(parameters)
58
+ );
59
+
60
+ // Create a proper PluginArray-like object that passes instanceof checks
61
+ (function() {
62
+ const fakePlugins = [
63
+ { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format', length: 1 },
64
+ { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '', length: 1 },
65
+ { name: 'Native Client', filename: 'internal-nacl-plugin', description: '', length: 1 }
66
+ ];
67
+
68
+ // Get the real PluginArray prototype from navigator.plugins
69
+ const realPluginsProto = Object.getPrototypeOf(navigator.plugins);
70
+
71
+ // Create array-like object with PluginArray prototype
72
+ const pluginArray = Object.create(realPluginsProto, {
73
+ length: { value: fakePlugins.length, writable: false, enumerable: true },
74
+ item: { value: function(i) { return this[i] || null; }, writable: false },
75
+ namedItem: { value: function(name) {
76
+ for (let i = 0; i < this.length; i++) {
77
+ if (this[i] && this[i].name === name) return this[i];
78
+ }
79
+ return null;
80
+ }, writable: false },
81
+ refresh: { value: function() {}, writable: false }
82
+ });
83
+
84
+ // Add indexed access
85
+ fakePlugins.forEach((p, i) => {
86
+ // Create Plugin-like object
87
+ const plugin = Object.create(Plugin.prototype, {
88
+ name: { value: p.name, writable: false, enumerable: true },
89
+ filename: { value: p.filename, writable: false, enumerable: true },
90
+ description: { value: p.description, writable: false, enumerable: true },
91
+ length: { value: p.length, writable: false, enumerable: true },
92
+ item: { value: function(i) { return null; }, writable: false },
93
+ namedItem: { value: function(n) { return null; }, writable: false }
94
+ });
95
+ Object.defineProperty(pluginArray, i, { value: plugin, writable: false, enumerable: true });
96
+ Object.defineProperty(pluginArray, p.name, { value: plugin, writable: false, enumerable: false });
97
+ });
98
+
99
+ Object.defineProperty(navigator, 'plugins', {
100
+ get: () => pluginArray,
101
+ configurable: true
102
+ });
103
+ })();
104
+
105
+ Object.defineProperty(navigator, 'languages', {
106
+ get: () => ['en-US', 'en'],
107
+ });
108
+
109
+
110
+ // Derive platform from user agent to avoid mismatch detection
111
+ (function() {
112
+ const ua = navigator.userAgent || '';
113
+ let platform = 'Win32'; // default
114
+ if (ua.includes('Macintosh') || ua.includes('Mac OS X')) {
115
+ platform = 'MacIntel';
116
+ } else if (ua.includes('Linux')) {
117
+ platform = ua.includes('x86_64') || ua.includes('amd64') ? 'Linux x86_64' : 'Linux';
118
+ } else if (ua.includes('Windows')) {
119
+ platform = ua.includes('Win64') || ua.includes('WOW64') ? 'Win32' : 'Win32';
120
+ }
121
+ Object.defineProperty(navigator, 'platform', {
122
+ get: () => platform,
123
+ configurable: true
124
+ });
125
+ })();
126
+
127
+ Object.defineProperty(navigator.connection || {}, 'rtt', {
128
+ get: () => 100,
129
+ });
130
+
131
+ const stealthLevel = (typeof __pinchtab_stealth_level !== 'undefined') ? __pinchtab_stealth_level : 'light';
132
+
133
+ if (stealthLevel === 'full') {
134
+
135
+ const getParameter = WebGLRenderingContext.prototype.getParameter;
136
+ WebGLRenderingContext.prototype.getParameter = function(parameter) {
137
+ if (parameter === 37445) return 'Intel Inc.';
138
+ if (parameter === 37446) return 'Intel Iris OpenGL Engine';
139
+ return getParameter.apply(this, arguments);
140
+ };
141
+
142
+ const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
143
+ const originalToBlob = HTMLCanvasElement.prototype.toBlob;
144
+ const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
145
+
146
+ HTMLCanvasElement.prototype.toDataURL = function(...args) {
147
+ const context = this.getContext('2d');
148
+ if (context && this.width > 0 && this.height > 0) {
149
+ const tempCanvas = document.createElement('canvas');
150
+ tempCanvas.width = this.width;
151
+ tempCanvas.height = this.height;
152
+ const tempCtx = tempCanvas.getContext('2d');
153
+ tempCtx.drawImage(this, 0, 0);
154
+ const imageData = tempCtx.getImageData(0, 0, this.width, this.height);
155
+ const pixelCount = Math.min(10, Math.floor(imageData.data.length / 400));
156
+ for (let i = 0; i < pixelCount; i++) {
157
+ const idx = Math.floor(seededRandom(sessionSeed + i) * (imageData.data.length / 4)) * 4;
158
+ if (imageData.data[idx] < 255) imageData.data[idx] += 1;
159
+ if (imageData.data[idx + 1] < 255) imageData.data[idx + 1] += 1;
160
+ }
161
+ tempCtx.putImageData(imageData, 0, 0);
162
+ return originalToDataURL.apply(tempCanvas, args);
163
+ }
164
+ return originalToDataURL.apply(this, args);
165
+ };
166
+
167
+ HTMLCanvasElement.prototype.toBlob = function(callback, type, quality) {
168
+ const dataURL = this.toDataURL(type, quality);
169
+ const arr = dataURL.split(',');
170
+ const mime = arr[0].match(/:(.*?);/)[1];
171
+ const bstr = atob(arr[1]);
172
+ let n = bstr.length;
173
+ const u8arr = new Uint8Array(n);
174
+ while(n--){ u8arr[n] = bstr.charCodeAt(n); }
175
+ const blob = new Blob([u8arr], {type: mime});
176
+ setTimeout(() => callback(blob), 5 + seededRandom(sessionSeed + 1000) * 10);
177
+ };
178
+
179
+ CanvasRenderingContext2D.prototype.getImageData = function(...args) {
180
+ const imageData = originalGetImageData.apply(this, args);
181
+ const pixelCount = imageData.data.length / 4;
182
+ const noisyPixels = Math.min(10, pixelCount * 0.0001);
183
+ for (let i = 0; i < noisyPixels; i++) {
184
+ const pixelIndex = Math.floor(Math.random() * pixelCount) * 4;
185
+ imageData.data[pixelIndex] = Math.min(255, Math.max(0, imageData.data[pixelIndex] + (Math.random() > 0.5 ? 1 : -1)));
186
+ }
187
+ return imageData;
188
+ };
189
+
190
+ const originalMeasureText = CanvasRenderingContext2D.prototype.measureText;
191
+ CanvasRenderingContext2D.prototype.measureText = function(text) {
192
+ const metrics = originalMeasureText.apply(this, arguments);
193
+ const noise = 0.0001 + (seededRandom(sessionSeed + text.length) * 0.0002);
194
+ return new Proxy(metrics, {
195
+ get(target, prop) {
196
+ if (prop === 'width') return target.width * (1 + noise);
197
+ return target[prop];
198
+ }
199
+ });
200
+ };
201
+
202
+ if (window.RTCPeerConnection) {
203
+ const originalRTCPeerConnection = window.RTCPeerConnection;
204
+ window.RTCPeerConnection = function(config, constraints) {
205
+ if (config && config.iceServers) config.iceTransportPolicy = 'relay';
206
+ return new originalRTCPeerConnection(config, constraints);
207
+ };
208
+ window.RTCPeerConnection.prototype = originalRTCPeerConnection.prototype;
209
+ }
210
+
211
+ }
212
+
213
+ const __pinchtab_origGetTimezoneOffset = Date.prototype.getTimezoneOffset;
214
+ Object.defineProperty(Date.prototype, 'getTimezoneOffset', {
215
+ value: function() {
216
+ return window.__pinchtab_timezone || __pinchtab_origGetTimezoneOffset.call(this);
217
+ }
218
+ });
219
+
220
+ const hardwareCore = 2 + Math.floor(seededRandom(sessionSeed) * 6) * 2;
221
+ const deviceMem = [2, 4, 8, 16][Math.floor(seededRandom(sessionSeed * 2) * 4)];
222
+
223
+ Object.defineProperty(navigator, 'hardwareConcurrency', {
224
+ get: () => hardwareCore,
225
+ configurable: true
226
+ });
227
+
228
+ Object.defineProperty(navigator, 'deviceMemory', {
229
+ get: () => deviceMem
230
+ });