untiktok-api 1.0.3 → 1.0.4

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 CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2019 David Teather
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2019 David Teather
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/LICENSE.txt CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2019 David Teather
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2019 David Teather
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/README.md CHANGED
@@ -1,83 +1,83 @@
1
- # UnTikTok-Api
2
-
3
- > An unofficial TikTok API wrapper in TypeScript, originally ported from the [TikTok-Api](https://github.com/davidteather/TikTok-Api) Python library.
4
- >
5
- > **Disclaimer:** This project is not affiliated with, endorsed by, or connected to TikTok, ByteDance, or the original author of the Python TikTok-Api. It is an independent, open-source TypeScript port designed for integration into Node.js applications and AI tools.
6
-
7
- [![NPM Version](https://img.shields.io/npm/v/untiktok-api?color=red)](https://www.npmjs.com/package/untiktok-api)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue?logo=typescript)](https://www.typescriptlang.org/)
9
- [![Playwright](https://img.shields.io/badge/Playwright-1.44+-green?logo=playwright)](https://playwright.dev/)
10
- [![Node.js](https://img.shields.io/badge/Node.js-18+-brightgreen?logo=node.js)](https://nodejs.org/)
11
-
12
- ---
13
-
14
- ## Table of Contents
15
-
16
- - [Features](#features)
17
- - [Installation](#installation)
18
- - [Quick Start](#quick-start)
19
- - [API Reference](#api-reference)
20
- - [Examples](#examples)
21
- - [Common Issues](#common-issues)
22
-
23
- ---
24
-
25
- ## Features
26
-
27
- This API allows you to extract and automate interactions with TikTok data without requiring an official developer API key. It achieves this by using Playwright and stealth scripts to interface directly with TikTok's web endpoints.
28
-
29
- **Capabilities include:**
30
- - **Trending Feeds:** Fetch the most viral and trending videos on the platform.
31
- - **User Profiles:** Retrieve a user's uploaded videos, liked videos, **favorited videos**, **reposted videos**, **pinned videos**, **followers/following lists**, profile information, and **live stream status**.
32
- - **Hashtags:** Fetch videos under specific hashtags.
33
- - **Search:** Search for specific users or videos by keyword.
34
- - **Comments:** Extract comments and replies from specific videos, including support for **TikTok Stickers**.
35
- - **Sounds/Music:** Retrieve videos associated with a specific audio track or sound.
36
- - **Downloads:** Download raw video bytes (without watermarks) and audio streams directly.
37
-
38
- ---
39
-
40
- ## Installation
41
-
42
- Install the package directly from NPM:
43
- ```bash
44
- npm install untiktok-api
45
- ```
46
-
47
- Since this wrapper relies on Playwright to interface with TikTok, you must also install the required Playwright browsers (specifically Chromium):
48
- ```bash
49
- npx playwright install chromium
50
- ```
51
-
52
- ### Building from Source
53
-
54
- If you want to contribute, modify, or build the project locally:
55
- ```bash
56
- git clone https://github.com/AlGhozaliRamadhan/UnTikTok-Api.git
57
- cd UnTikTok-Api
58
- npm install
59
- npm run build
60
- ```
61
-
62
- ---
63
-
64
- ## Quick Start
65
- Looking to get started immediately? Check out the [Quick Start Guide](./docs/quick_start.md).
66
-
67
- ---
68
-
69
- ## API Reference
70
- For a full list of classes, methods, and constructor options, check out the [API Reference](./docs/api_reference.md).
71
-
72
- ---
73
-
74
- ## Examples & Guides
75
-
76
- For detailed examples and tutorials on how to use specific features, check out the dedicated guides in the `docs/` folder:
77
-
78
- - [Trending Videos](./docs/trending.md)
79
- - [User Data (Videos, Likes, Reposts) 🆕](./docs/user.md)
80
- - [Hashtag Videos](./docs/hashtag.md)
81
- - [Search Users](./docs/search.md)
82
- - [Download Videos](./docs/download.md)
83
- - [Session Caching (Bot evasion)](./docs/session_caching.md)
1
+ # UnTikTok-Api
2
+
3
+ > An unofficial TikTok API wrapper in TypeScript, originally ported from the [TikTok-Api](https://github.com/davidteather/TikTok-Api) Python library.
4
+ >
5
+ > **Disclaimer:** This project is not affiliated with, endorsed by, or connected to TikTok, ByteDance, or the original author of the Python TikTok-Api. It is an independent, open-source TypeScript port designed for integration into Node.js applications and AI tools.
6
+
7
+ [![NPM Version](https://img.shields.io/npm/v/untiktok-api?color=red)](https://www.npmjs.com/package/untiktok-api)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue?logo=typescript)](https://www.typescriptlang.org/)
9
+ [![Playwright](https://img.shields.io/badge/Playwright-1.44+-green?logo=playwright)](https://playwright.dev/)
10
+ [![Node.js](https://img.shields.io/badge/Node.js-18+-brightgreen?logo=node.js)](https://nodejs.org/)
11
+
12
+ ---
13
+
14
+ ## Table of Contents
15
+
16
+ - [Features](#features)
17
+ - [Installation](#installation)
18
+ - [Quick Start](#quick-start)
19
+ - [API Reference](#api-reference)
20
+ - [Examples](#examples)
21
+ - [Common Issues](#common-issues)
22
+
23
+ ---
24
+
25
+ ## Features
26
+
27
+ This API allows you to extract and automate interactions with TikTok data without requiring an official developer API key. It achieves this by using Playwright and stealth scripts to interface directly with TikTok's web endpoints.
28
+
29
+ **Capabilities include:**
30
+ - **Trending Feeds:** Fetch the most viral and trending videos on the platform.
31
+ - **User Profiles:** Retrieve a user's uploaded videos, liked videos, **favorited videos**, **reposted videos**, **pinned videos**, **followers/following lists**, profile information, and **live stream status**.
32
+ - **Hashtags:** Fetch videos under specific hashtags.
33
+ - **Search:** Search for specific users or videos by keyword.
34
+ - **Comments:** Extract comments and replies from specific videos, including support for **TikTok Stickers**.
35
+ - **Sounds/Music:** Retrieve videos associated with a specific audio track or sound.
36
+ - **Downloads:** Download raw video bytes (without watermarks) and audio streams directly.
37
+
38
+ ---
39
+
40
+ ## Installation
41
+
42
+ Install the package directly from NPM:
43
+ ```bash
44
+ npm install untiktok-api
45
+ ```
46
+
47
+ Since this wrapper relies on Playwright to interface with TikTok, you must also install the required Playwright browsers (specifically Chromium):
48
+ ```bash
49
+ npx playwright install chromium
50
+ ```
51
+
52
+ ### Building from Source
53
+
54
+ If you want to contribute, modify, or build the project locally:
55
+ ```bash
56
+ git clone https://github.com/AlGhozaliRamadhan/UnTikTok-Api.git
57
+ cd UnTikTok-Api
58
+ npm install
59
+ npm run build
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Quick Start
65
+ Looking to get started immediately? Check out the [Quick Start Guide](./docs/quick_start.md).
66
+
67
+ ---
68
+
69
+ ## API Reference
70
+ For a full list of classes, methods, and constructor options, check out the [API Reference](./docs/api_reference.md).
71
+
72
+ ---
73
+
74
+ ## Examples & Guides
75
+
76
+ For detailed examples and tutorials on how to use specific features, check out the dedicated guides in the `docs/` folder:
77
+
78
+ - [Trending Videos](./docs/trending.md)
79
+ - [User Data (Videos, Likes, Reposts) 🆕](./docs/user.md)
80
+ - [Hashtag Videos](./docs/hashtag.md)
81
+ - [Search Users](./docs/search.md)
82
+ - [Download Videos](./docs/download.md)
83
+ - [Session Caching (Bot evasion)](./docs/session_caching.md)
@@ -1,27 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chrome_app = void 0;
4
- exports.chrome_app = `
5
- if (!window.chrome) {
6
- Object.defineProperty(window, 'chrome', {
7
- writable: true, enumerable: true, configurable: false, value: {}
8
- })
9
- }
10
- if (!('app' in window.chrome)) {
11
- const makeError = {
12
- ErrorInInvocation: fn => {
13
- const err = new TypeError(\`Error in invocation of app.\${fn}()\`)
14
- return utils.stripErrorWithAnchor(err, \`at \${fn} (eval at <anonymous>\`)
15
- }
16
- }
17
- const APP_STATIC_DATA = JSON.parse(\`{"isInstalled":false,"InstallState":{"DISABLED":"disabled","INSTALLED":"installed","NOT_INSTALLED":"not_installed"},"RunningState":{"CANNOT_RUN":"cannot_run","READY_TO_RUN":"ready_to_run","RUNNING":"running"}}\`)
18
- window.chrome.app = {
19
- ...APP_STATIC_DATA,
20
- get isInstalled() { return false },
21
- getDetails: function getDetails() { if (arguments.length) throw makeError.ErrorInInvocation('getDetails'); return null },
22
- getIsInstalled: function getIsInstalled() { if (arguments.length) throw makeError.ErrorInInvocation('getIsInstalled'); return false },
23
- runningState: function runningState() { if (arguments.length) throw makeError.ErrorInInvocation('runningState'); return 'cannot_run' }
24
- }
25
- utils.patchToStringNested(window.chrome.app)
26
- }
4
+ exports.chrome_app = `
5
+ if (!window.chrome) {
6
+ Object.defineProperty(window, 'chrome', {
7
+ writable: true, enumerable: true, configurable: false, value: {}
8
+ })
9
+ }
10
+ if (!('app' in window.chrome)) {
11
+ const makeError = {
12
+ ErrorInInvocation: fn => {
13
+ const err = new TypeError(\`Error in invocation of app.\${fn}()\`)
14
+ return utils.stripErrorWithAnchor(err, \`at \${fn} (eval at <anonymous>\`)
15
+ }
16
+ }
17
+ const APP_STATIC_DATA = JSON.parse(\`{"isInstalled":false,"InstallState":{"DISABLED":"disabled","INSTALLED":"installed","NOT_INSTALLED":"not_installed"},"RunningState":{"CANNOT_RUN":"cannot_run","READY_TO_RUN":"ready_to_run","RUNNING":"running"}}\`)
18
+ window.chrome.app = {
19
+ ...APP_STATIC_DATA,
20
+ get isInstalled() { return false },
21
+ getDetails: function getDetails() { if (arguments.length) throw makeError.ErrorInInvocation('getDetails'); return null },
22
+ getIsInstalled: function getIsInstalled() { if (arguments.length) throw makeError.ErrorInInvocation('getIsInstalled'); return false },
23
+ runningState: function runningState() { if (arguments.length) throw makeError.ErrorInInvocation('runningState'); return 'cannot_run' }
24
+ }
25
+ utils.patchToStringNested(window.chrome.app)
26
+ }
27
27
  `;
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chrome_csi = void 0;
4
- exports.chrome_csi = `
5
- if (!window.chrome) {
6
- Object.defineProperty(window, 'chrome', { writable: true, enumerable: true, configurable: false, value: {} })
7
- }
8
- if (!('csi' in window.chrome)) {
9
- window.chrome.csi = function() {
10
- return { onloadT: Date.now(), startE: Date.now(), pageT: Date.now() - performance.timing.navigationStart, tran: 15 }
11
- }
12
- utils.patchToString(window.chrome.csi)
13
- }
4
+ exports.chrome_csi = `
5
+ if (!window.chrome) {
6
+ Object.defineProperty(window, 'chrome', { writable: true, enumerable: true, configurable: false, value: {} })
7
+ }
8
+ if (!('csi' in window.chrome)) {
9
+ window.chrome.csi = function() {
10
+ return { onloadT: Date.now(), startE: Date.now(), pageT: Date.now() - performance.timing.navigationStart, tran: 15 }
11
+ }
12
+ utils.patchToString(window.chrome.csi)
13
+ }
14
14
  `;
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chrome_hairline = void 0;
4
- exports.chrome_hairline = `
5
- const canvasContext = document.createElement('canvas').getContext('webgl')
6
- if (canvasContext) {
7
- const nativeGetParameter = WebGLRenderingContext.prototype.getParameter
8
- utils.replaceWithProxy(WebGLRenderingContext.prototype, 'getParameter', {
9
- apply: function(target, ctx, args) {
10
- const param = (args || [])[0]
11
- if (param === 37446) { return 0 }
12
- return utils.cache.Reflect.apply(target, ctx, args)
13
- }
14
- })
15
- }
4
+ exports.chrome_hairline = `
5
+ const canvasContext = document.createElement('canvas').getContext('webgl')
6
+ if (canvasContext) {
7
+ const nativeGetParameter = WebGLRenderingContext.prototype.getParameter
8
+ utils.replaceWithProxy(WebGLRenderingContext.prototype, 'getParameter', {
9
+ apply: function(target, ctx, args) {
10
+ const param = (args || [])[0]
11
+ if (param === 37446) { return 0 }
12
+ return utils.cache.Reflect.apply(target, ctx, args)
13
+ }
14
+ })
15
+ }
16
16
  `;
@@ -1,28 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chrome_load_times = void 0;
4
- exports.chrome_load_times = `
5
- if (!window.chrome) {
6
- Object.defineProperty(window, 'chrome', { writable: true, enumerable: true, configurable: false, value: {} })
7
- }
8
- if (!('loadTimes' in window.chrome)) {
9
- const loadTime = Date.now() / 1000 - Math.random() * 20
10
- const startLoadTime = loadTime - Math.random() * 2
11
- const data = {
12
- get commitLoadTime() { return startLoadTime },
13
- get finishDocumentLoadTime() { return loadTime },
14
- get finishLoadTime() { return loadTime + Math.random() },
15
- get firstPaintAfterLoadTime() { return 0 },
16
- get firstPaintTime() { return startLoadTime + Math.random() * 2 },
17
- get navigationType() { return 'Other' },
18
- get npnNegotiatedProtocol() { return 'unknown' },
19
- get requestTime() { return startLoadTime - 0.01 },
20
- get startLoadTime() { return startLoadTime },
21
- get wasAlternateProtocolAvailable() { return false },
22
- get wasFetchedViaSpdy() { return false },
23
- get wasNpnNegotiated() { return false }
24
- }
25
- utils.replaceProperty(window.chrome, 'loadTimes', { value: function loadTimes() { return data } })
26
- utils.patchToString(window.chrome.loadTimes)
27
- }
4
+ exports.chrome_load_times = `
5
+ if (!window.chrome) {
6
+ Object.defineProperty(window, 'chrome', { writable: true, enumerable: true, configurable: false, value: {} })
7
+ }
8
+ if (!('loadTimes' in window.chrome)) {
9
+ const loadTime = Date.now() / 1000 - Math.random() * 20
10
+ const startLoadTime = loadTime - Math.random() * 2
11
+ const data = {
12
+ get commitLoadTime() { return startLoadTime },
13
+ get finishDocumentLoadTime() { return loadTime },
14
+ get finishLoadTime() { return loadTime + Math.random() },
15
+ get firstPaintAfterLoadTime() { return 0 },
16
+ get firstPaintTime() { return startLoadTime + Math.random() * 2 },
17
+ get navigationType() { return 'Other' },
18
+ get npnNegotiatedProtocol() { return 'unknown' },
19
+ get requestTime() { return startLoadTime - 0.01 },
20
+ get startLoadTime() { return startLoadTime },
21
+ get wasAlternateProtocolAvailable() { return false },
22
+ get wasFetchedViaSpdy() { return false },
23
+ get wasNpnNegotiated() { return false }
24
+ }
25
+ utils.replaceProperty(window.chrome, 'loadTimes', { value: function loadTimes() { return data } })
26
+ utils.patchToString(window.chrome.loadTimes)
27
+ }
28
28
  `;
@@ -1,84 +1,84 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chrome_runtime_script = void 0;
4
- exports.chrome_runtime_script = `
5
- const STATIC_DATA = {"OnInstalledReason":{"CHROME_UPDATE":"chrome_update","INSTALL":"install","SHARED_MODULE_UPDATE":"shared_module_update","UPDATE":"update"},"OnRestartRequiredReason":{"APP_UPDATE":"app_update","OS_UPDATE":"os_update","PERIODIC":"periodic"},"PlatformArch":{"ARM":"arm","ARM64":"arm64","MIPS":"mips","MIPS64":"mips64","X86_32":"x86-32","X86_64":"x86-64"},"PlatformNaclArch":{"ARM":"arm","MIPS":"mips","MIPS64":"mips64","X86_32":"x86-32","X86_64":"x86-64"},"PlatformOs":{"ANDROID":"android","CROS":"cros","LINUX":"linux","MAC":"mac","OPENBSD":"openbsd","WIN":"win"},"RequestUpdateCheckStatus":{"NO_UPDATE":"no_update","THROTTLED":"throttled","UPDATE_AVAILABLE":"update_available"}}
6
- if (!window.chrome) {
7
- Object.defineProperty(window, 'chrome', { writable: true, enumerable: true, configurable: false, value: {} })
8
- }
9
- const existsAlready = 'runtime' in window.chrome
10
- const isNotSecure = !window.location.protocol.startsWith('https')
11
- if (!(existsAlready || (isNotSecure && !opts.runOnInsecureOrigins))) {
12
- window.chrome.runtime = {
13
- ...STATIC_DATA,
14
- get id() { return undefined },
15
- connect: null,
16
- sendMessage: null
17
- }
18
- const makeCustomRuntimeErrors = (preamble, method, extensionId) => ({
19
- NoMatchingSignature: new TypeError(preamble + 'No matching signature.'),
20
- MustSpecifyExtensionID: new TypeError(preamble + method + ' called from a webpage must specify an Extension ID (string) for its first argument.'),
21
- InvalidExtensionID: new TypeError(preamble + "Invalid extension id: '" + extensionId + "'")
22
- })
23
- const isValidExtensionID = str => str.length === 32 && str.toLowerCase().match(/^[a-p]+$/)
24
- const sendMessageHandler = {
25
- apply: function(target, ctx, args) {
26
- const [extensionId, options, responseCallback] = args || []
27
- const errorPreamble = 'Error in invocation of runtime.sendMessage(optional string extensionId, any message, optional object options, optional function responseCallback): '
28
- const Errors = makeCustomRuntimeErrors(errorPreamble, 'chrome.runtime.sendMessage()', extensionId)
29
- const noArguments = args.length === 0, tooManyArguments = args.length > 4
30
- const incorrectOptions = options && typeof options !== 'object'
31
- const incorrectResponseCallback = responseCallback && typeof responseCallback !== 'function'
32
- if (noArguments || tooManyArguments || incorrectOptions || incorrectResponseCallback) throw Errors.NoMatchingSignature
33
- if (args.length < 2) throw Errors.MustSpecifyExtensionID
34
- if (typeof extensionId !== 'string') throw Errors.NoMatchingSignature
35
- if (!isValidExtensionID(extensionId)) throw Errors.InvalidExtensionID
36
- return undefined
37
- }
38
- }
39
- utils.mockWithProxy(window.chrome.runtime, 'sendMessage', function sendMessage() {}, sendMessageHandler)
40
- const connectHandler = {
41
- apply: function(target, ctx, args) {
42
- const [extensionId, connectInfo] = args || []
43
- const errorPreamble = 'Error in invocation of runtime.connect(optional string extensionId, optional object connectInfo): '
44
- const Errors = makeCustomRuntimeErrors(errorPreamble, 'chrome.runtime.connect()', extensionId)
45
- const noArguments = args.length === 0, emptyStringArgument = args.length === 1 && extensionId === ''
46
- if (noArguments || emptyStringArgument) throw Errors.MustSpecifyExtensionID
47
- const tooManyArguments = args.length > 2, incorrectConnectInfoType = connectInfo && typeof connectInfo !== 'object'
48
- if (tooManyArguments || incorrectConnectInfoType) throw Errors.NoMatchingSignature
49
- const extensionIdIsString = typeof extensionId === 'string'
50
- if (extensionIdIsString && extensionId === '') throw Errors.MustSpecifyExtensionID
51
- if (extensionIdIsString && !isValidExtensionID(extensionId)) throw Errors.InvalidExtensionID
52
- const validateConnectInfo = ci => {
53
- if (args.length > 1) throw Errors.NoMatchingSignature
54
- if (Object.keys(ci).length === 0) throw Errors.MustSpecifyExtensionID
55
- Object.entries(ci).forEach(([k, v]) => {
56
- const isExpected = ['name', 'includeTlsChannelId'].includes(k)
57
- if (!isExpected) throw new TypeError(errorPreamble + "Unexpected property: '" + k + "'.")
58
- if (k === 'name' && typeof v !== 'string') throw TypeError(errorPreamble + "Error at property '" + k + "': Invalid type: expected string, found " + typeof v + ".")
59
- if (k === 'includeTlsChannelId' && typeof v !== 'boolean') throw TypeError(errorPreamble + "Error at property '" + k + "': Invalid type: expected boolean, found " + typeof v + ".")
60
- })
61
- }
62
- if (typeof extensionId === 'object') { validateConnectInfo(extensionId); throw Errors.MustSpecifyExtensionID }
63
- return utils.patchToStringNested(makeConnectResponse())
64
- }
65
- }
66
- utils.mockWithProxy(window.chrome.runtime, 'connect', function connect() {}, connectHandler)
67
- function makeConnectResponse() {
68
- const onSomething = () => ({
69
- addListener: function addListener() {}, dispatch: function dispatch() {},
70
- hasListener: function hasListener() {}, hasListeners: function hasListeners() { return false },
71
- removeListener: function removeListener() {}
72
- })
73
- return {
74
- name: '', sender: undefined,
75
- disconnect: function disconnect() {},
76
- onDisconnect: onSomething(), onMessage: onSomething(),
77
- postMessage: function postMessage() {
78
- if (!arguments.length) throw new TypeError('Insufficient number of arguments.')
79
- throw new Error('Attempting to use a disconnected port object')
80
- }
81
- }
82
- }
83
- }
4
+ exports.chrome_runtime_script = `
5
+ const STATIC_DATA = {"OnInstalledReason":{"CHROME_UPDATE":"chrome_update","INSTALL":"install","SHARED_MODULE_UPDATE":"shared_module_update","UPDATE":"update"},"OnRestartRequiredReason":{"APP_UPDATE":"app_update","OS_UPDATE":"os_update","PERIODIC":"periodic"},"PlatformArch":{"ARM":"arm","ARM64":"arm64","MIPS":"mips","MIPS64":"mips64","X86_32":"x86-32","X86_64":"x86-64"},"PlatformNaclArch":{"ARM":"arm","MIPS":"mips","MIPS64":"mips64","X86_32":"x86-32","X86_64":"x86-64"},"PlatformOs":{"ANDROID":"android","CROS":"cros","LINUX":"linux","MAC":"mac","OPENBSD":"openbsd","WIN":"win"},"RequestUpdateCheckStatus":{"NO_UPDATE":"no_update","THROTTLED":"throttled","UPDATE_AVAILABLE":"update_available"}}
6
+ if (!window.chrome) {
7
+ Object.defineProperty(window, 'chrome', { writable: true, enumerable: true, configurable: false, value: {} })
8
+ }
9
+ const existsAlready = 'runtime' in window.chrome
10
+ const isNotSecure = !window.location.protocol.startsWith('https')
11
+ if (!(existsAlready || (isNotSecure && !opts.runOnInsecureOrigins))) {
12
+ window.chrome.runtime = {
13
+ ...STATIC_DATA,
14
+ get id() { return undefined },
15
+ connect: null,
16
+ sendMessage: null
17
+ }
18
+ const makeCustomRuntimeErrors = (preamble, method, extensionId) => ({
19
+ NoMatchingSignature: new TypeError(preamble + 'No matching signature.'),
20
+ MustSpecifyExtensionID: new TypeError(preamble + method + ' called from a webpage must specify an Extension ID (string) for its first argument.'),
21
+ InvalidExtensionID: new TypeError(preamble + "Invalid extension id: '" + extensionId + "'")
22
+ })
23
+ const isValidExtensionID = str => str.length === 32 && str.toLowerCase().match(/^[a-p]+$/)
24
+ const sendMessageHandler = {
25
+ apply: function(target, ctx, args) {
26
+ const [extensionId, options, responseCallback] = args || []
27
+ const errorPreamble = 'Error in invocation of runtime.sendMessage(optional string extensionId, any message, optional object options, optional function responseCallback): '
28
+ const Errors = makeCustomRuntimeErrors(errorPreamble, 'chrome.runtime.sendMessage()', extensionId)
29
+ const noArguments = args.length === 0, tooManyArguments = args.length > 4
30
+ const incorrectOptions = options && typeof options !== 'object'
31
+ const incorrectResponseCallback = responseCallback && typeof responseCallback !== 'function'
32
+ if (noArguments || tooManyArguments || incorrectOptions || incorrectResponseCallback) throw Errors.NoMatchingSignature
33
+ if (args.length < 2) throw Errors.MustSpecifyExtensionID
34
+ if (typeof extensionId !== 'string') throw Errors.NoMatchingSignature
35
+ if (!isValidExtensionID(extensionId)) throw Errors.InvalidExtensionID
36
+ return undefined
37
+ }
38
+ }
39
+ utils.mockWithProxy(window.chrome.runtime, 'sendMessage', function sendMessage() {}, sendMessageHandler)
40
+ const connectHandler = {
41
+ apply: function(target, ctx, args) {
42
+ const [extensionId, connectInfo] = args || []
43
+ const errorPreamble = 'Error in invocation of runtime.connect(optional string extensionId, optional object connectInfo): '
44
+ const Errors = makeCustomRuntimeErrors(errorPreamble, 'chrome.runtime.connect()', extensionId)
45
+ const noArguments = args.length === 0, emptyStringArgument = args.length === 1 && extensionId === ''
46
+ if (noArguments || emptyStringArgument) throw Errors.MustSpecifyExtensionID
47
+ const tooManyArguments = args.length > 2, incorrectConnectInfoType = connectInfo && typeof connectInfo !== 'object'
48
+ if (tooManyArguments || incorrectConnectInfoType) throw Errors.NoMatchingSignature
49
+ const extensionIdIsString = typeof extensionId === 'string'
50
+ if (extensionIdIsString && extensionId === '') throw Errors.MustSpecifyExtensionID
51
+ if (extensionIdIsString && !isValidExtensionID(extensionId)) throw Errors.InvalidExtensionID
52
+ const validateConnectInfo = ci => {
53
+ if (args.length > 1) throw Errors.NoMatchingSignature
54
+ if (Object.keys(ci).length === 0) throw Errors.MustSpecifyExtensionID
55
+ Object.entries(ci).forEach(([k, v]) => {
56
+ const isExpected = ['name', 'includeTlsChannelId'].includes(k)
57
+ if (!isExpected) throw new TypeError(errorPreamble + "Unexpected property: '" + k + "'.")
58
+ if (k === 'name' && typeof v !== 'string') throw TypeError(errorPreamble + "Error at property '" + k + "': Invalid type: expected string, found " + typeof v + ".")
59
+ if (k === 'includeTlsChannelId' && typeof v !== 'boolean') throw TypeError(errorPreamble + "Error at property '" + k + "': Invalid type: expected boolean, found " + typeof v + ".")
60
+ })
61
+ }
62
+ if (typeof extensionId === 'object') { validateConnectInfo(extensionId); throw Errors.MustSpecifyExtensionID }
63
+ return utils.patchToStringNested(makeConnectResponse())
64
+ }
65
+ }
66
+ utils.mockWithProxy(window.chrome.runtime, 'connect', function connect() {}, connectHandler)
67
+ function makeConnectResponse() {
68
+ const onSomething = () => ({
69
+ addListener: function addListener() {}, dispatch: function dispatch() {},
70
+ hasListener: function hasListener() {}, hasListeners: function hasListeners() { return false },
71
+ removeListener: function removeListener() {}
72
+ })
73
+ return {
74
+ name: '', sender: undefined,
75
+ disconnect: function disconnect() {},
76
+ onDisconnect: onSomething(), onMessage: onSomething(),
77
+ postMessage: function postMessage() {
78
+ if (!arguments.length) throw new TypeError('Insufficient number of arguments.')
79
+ throw new Error('Attempting to use a disconnected port object')
80
+ }
81
+ }
82
+ }
83
+ }
84
84
  `;
@@ -1,28 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generate_magic_arrays = void 0;
4
- exports.generate_magic_arrays = `
5
- function generateMagicArray(dataArray = [], proto = MimeTypeArray.prototype, itemProto = MimeType.prototype, itemMainProp = 'type') {
6
- const arr = []
7
- arr.__proto__ = proto
8
- for (const item of dataArray) {
9
- const obj = {}
10
- obj.__proto__ = itemProto
11
- for (const [key, value] of Object.entries(item)) {
12
- if (!key.startsWith('__')) { obj[key] = value }
13
- }
14
- Object.defineProperty(obj, itemMainProp, { configurable: true, enumerable: true, get: () => item[itemMainProp] })
15
- arr.push(obj)
16
- arr[item[itemMainProp]] = obj
17
- }
18
- const proxy = new Proxy(arr, {
19
- get(target, key) {
20
- if (key === 'length') { return target.length }
21
- if (key === Symbol.toStringTag) { return Object.getPrototypeOf(target)[Symbol.toStringTag] }
22
- if (key in target) { return target[key] }
23
- return undefined
24
- }
25
- })
26
- return proxy
27
- }
4
+ exports.generate_magic_arrays = `
5
+ function generateMagicArray(dataArray = [], proto = MimeTypeArray.prototype, itemProto = MimeType.prototype, itemMainProp = 'type') {
6
+ const arr = []
7
+ arr.__proto__ = proto
8
+ for (const item of dataArray) {
9
+ const obj = {}
10
+ obj.__proto__ = itemProto
11
+ for (const [key, value] of Object.entries(item)) {
12
+ if (!key.startsWith('__')) { obj[key] = value }
13
+ }
14
+ Object.defineProperty(obj, itemMainProp, { configurable: true, enumerable: true, get: () => item[itemMainProp] })
15
+ arr.push(obj)
16
+ arr[item[itemMainProp]] = obj
17
+ }
18
+ const proxy = new Proxy(arr, {
19
+ get(target, key) {
20
+ if (key === 'length') { return target.length }
21
+ if (key === Symbol.toStringTag) { return Object.getPrototypeOf(target)[Symbol.toStringTag] }
22
+ if (key in target) { return target[key] }
23
+ return undefined
24
+ }
25
+ })
26
+ return proxy
27
+ }
28
28
  `;
@@ -1,22 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.iframe_contentWindow = void 0;
4
- exports.iframe_contentWindow = `
5
- try {
6
- const getContentWindowProxy = {
7
- apply: function(target, ctx, args) {
8
- const iframe = args[0]
9
- if (!iframe || iframe.nodeName !== 'IFRAME') { return utils.cache.Reflect.apply(target, ctx, args) }
10
- const win = utils.cache.Reflect.apply(target, ctx, args)
11
- win.Object = window.Object
12
- win.Reflect = window.Reflect
13
- return win
14
- }
15
- }
16
- Object.defineProperty(HTMLIFrameElement.prototype, 'contentWindow', {
17
- get() {
18
- return new Proxy(HTMLIFrameElement.prototype.contentWindow, getContentWindowProxy)
19
- }
20
- })
21
- } catch (err) { /* noop */ }
4
+ exports.iframe_contentWindow = `
5
+ try {
6
+ const getContentWindowProxy = {
7
+ apply: function(target, ctx, args) {
8
+ const iframe = args[0]
9
+ if (!iframe || iframe.nodeName !== 'IFRAME') { return utils.cache.Reflect.apply(target, ctx, args) }
10
+ const win = utils.cache.Reflect.apply(target, ctx, args)
11
+ win.Object = window.Object
12
+ win.Reflect = window.Reflect
13
+ return win
14
+ }
15
+ }
16
+ Object.defineProperty(HTMLIFrameElement.prototype, 'contentWindow', {
17
+ get() {
18
+ return new Proxy(HTMLIFrameElement.prototype.contentWindow, getContentWindowProxy)
19
+ }
20
+ })
21
+ } catch (err) { /* noop */ }
22
22
  `;
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.media_codecs = void 0;
4
- exports.media_codecs = `
5
- const makeCanPlayType = (supported, fn) => {
6
- utils.replaceWithProxy(HTMLMediaElement.prototype, 'canPlayType', {
7
- apply: function(target, ctx, args) {
8
- const type = (args || [])[0]
9
- const result = utils.cache.Reflect.apply(target, ctx, args)
10
- if (type === supported) { return 'probably' }
11
- return result
12
- }
13
- })
14
- }
15
- makeCanPlayType('video/ogg; codecs="theora"', fn => fn)
4
+ exports.media_codecs = `
5
+ const makeCanPlayType = (supported, fn) => {
6
+ utils.replaceWithProxy(HTMLMediaElement.prototype, 'canPlayType', {
7
+ apply: function(target, ctx, args) {
8
+ const type = (args || [])[0]
9
+ const result = utils.cache.Reflect.apply(target, ctx, args)
10
+ if (type === supported) { return 'probably' }
11
+ return result
12
+ }
13
+ })
14
+ }
15
+ makeCanPlayType('video/ogg; codecs="theora"', fn => fn)
16
16
  `;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.navigator_hardwareConcurrency = void 0;
4
- exports.navigator_hardwareConcurrency = `
5
- utils.replaceProperty(Object.getPrototypeOf(navigator), 'hardwareConcurrency', { get: () => opts.navigator_hardware_concurrency || 4 })
4
+ exports.navigator_hardwareConcurrency = `
5
+ utils.replaceProperty(Object.getPrototypeOf(navigator), 'hardwareConcurrency', { get: () => opts.navigator_hardware_concurrency || 4 })
6
6
  `;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.navigator_languages = void 0;
4
- exports.navigator_languages = `
5
- utils.replaceProperty(Object.getPrototypeOf(navigator), 'languages', { get: () => opts.languages || ['en-US', 'en'] })
4
+ exports.navigator_languages = `
5
+ utils.replaceProperty(Object.getPrototypeOf(navigator), 'languages', { get: () => opts.languages || ['en-US', 'en'] })
6
6
  `;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.navigator_permissions = void 0;
4
- exports.navigator_permissions = `
5
- const originalQuery = window.navigator.permissions.query
6
- window.navigator.permissions.__proto__.query = parameters =>
7
- parameters.name === 'notifications'
8
- ? Promise.resolve({ state: Notification.permission })
9
- : originalQuery(parameters)
10
- utils.patchToString(window.navigator.permissions.__proto__.query)
4
+ exports.navigator_permissions = `
5
+ const originalQuery = window.navigator.permissions.query
6
+ window.navigator.permissions.__proto__.query = parameters =>
7
+ parameters.name === 'notifications'
8
+ ? Promise.resolve({ state: Notification.permission })
9
+ : originalQuery(parameters)
10
+ utils.patchToString(window.navigator.permissions.__proto__.query)
11
11
  `;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.navigator_platform = void 0;
4
- exports.navigator_platform = `
5
- if (opts.navigator_platform) {
6
- utils.replaceProperty(Object.getPrototypeOf(navigator), 'platform', { get: () => opts.navigator_platform })
7
- }
4
+ exports.navigator_platform = `
5
+ if (opts.navigator_platform) {
6
+ utils.replaceProperty(Object.getPrototypeOf(navigator), 'platform', { get: () => opts.navigator_platform })
7
+ }
8
8
  `;
@@ -1,37 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.navigator_plugins_script = void 0;
4
- exports.navigator_plugins_script = `
5
- const data = {
6
- mimeTypes: [
7
- { type: 'application/pdf', suffixes: 'pdf', description: '', __pluginName: 'Chrome PDF Viewer' },
8
- { type: 'application/x-google-chrome-pdf', suffixes: 'pdf', description: 'Portable Document Format', __pluginName: 'Chrome PDF Plugin' },
9
- { type: 'application/x-nacl', suffixes: '', description: 'Native Client Executable', __pluginName: 'Native Client' },
10
- { type: 'application/x-pnacl', suffixes: '', description: 'Portable Native Client Executable', __pluginName: 'Native Client' }
11
- ],
12
- plugins: [
13
- { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format', __mimeTypes: ['application/x-google-chrome-pdf'] },
14
- { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '', __mimeTypes: ['application/pdf'] },
15
- { name: 'Native Client', filename: 'internal-nacl-plugin', description: '', __mimeTypes: ['application/x-nacl', 'application/x-pnacl'] }
16
- ]
17
- }
18
- const hasPlugins = 'plugins' in navigator && navigator.plugins.length
19
- if (!hasPlugins) {
20
- const mimeTypes = generateMagicArray(data.mimeTypes, MimeTypeArray.prototype, MimeType.prototype, 'type')
21
- const plugins = generateMagicArray(data.plugins, PluginArray.prototype, Plugin.prototype, 'name')
22
- for (const pluginData of data.plugins) {
23
- pluginData.__mimeTypes.forEach((type, index) => {
24
- plugins[pluginData.name][index] = mimeTypes[type]
25
- plugins[type] = mimeTypes[type]
26
- Object.defineProperty(mimeTypes[type], 'enabledPlugin', {
27
- value: JSON.parse(JSON.stringify(plugins[pluginData.name])),
28
- writable: false, enumerable: false, configurable: false
29
- })
30
- })
31
- }
32
- const patchNavigator = (name, value) =>
33
- utils.replaceProperty(Object.getPrototypeOf(navigator), name, { get() { return value } })
34
- patchNavigator('mimeTypes', mimeTypes)
35
- patchNavigator('plugins', plugins)
36
- }
4
+ exports.navigator_plugins_script = `
5
+ const data = {
6
+ mimeTypes: [
7
+ { type: 'application/pdf', suffixes: 'pdf', description: '', __pluginName: 'Chrome PDF Viewer' },
8
+ { type: 'application/x-google-chrome-pdf', suffixes: 'pdf', description: 'Portable Document Format', __pluginName: 'Chrome PDF Plugin' },
9
+ { type: 'application/x-nacl', suffixes: '', description: 'Native Client Executable', __pluginName: 'Native Client' },
10
+ { type: 'application/x-pnacl', suffixes: '', description: 'Portable Native Client Executable', __pluginName: 'Native Client' }
11
+ ],
12
+ plugins: [
13
+ { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format', __mimeTypes: ['application/x-google-chrome-pdf'] },
14
+ { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '', __mimeTypes: ['application/pdf'] },
15
+ { name: 'Native Client', filename: 'internal-nacl-plugin', description: '', __mimeTypes: ['application/x-nacl', 'application/x-pnacl'] }
16
+ ]
17
+ }
18
+ const hasPlugins = 'plugins' in navigator && navigator.plugins.length
19
+ if (!hasPlugins) {
20
+ const mimeTypes = generateMagicArray(data.mimeTypes, MimeTypeArray.prototype, MimeType.prototype, 'type')
21
+ const plugins = generateMagicArray(data.plugins, PluginArray.prototype, Plugin.prototype, 'name')
22
+ for (const pluginData of data.plugins) {
23
+ pluginData.__mimeTypes.forEach((type, index) => {
24
+ plugins[pluginData.name][index] = mimeTypes[type]
25
+ plugins[type] = mimeTypes[type]
26
+ Object.defineProperty(mimeTypes[type], 'enabledPlugin', {
27
+ value: JSON.parse(JSON.stringify(plugins[pluginData.name])),
28
+ writable: false, enumerable: false, configurable: false
29
+ })
30
+ })
31
+ }
32
+ const patchNavigator = (name, value) =>
33
+ utils.replaceProperty(Object.getPrototypeOf(navigator), name, { get() { return value } })
34
+ patchNavigator('mimeTypes', mimeTypes)
35
+ patchNavigator('plugins', plugins)
36
+ }
37
37
  `;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.navigator_userAgent_script = void 0;
4
- exports.navigator_userAgent_script = `
5
- if (opts.navigator_user_agent) {
6
- utils.replaceProperty(Object.getPrototypeOf(navigator), 'userAgent', { get: () => opts.navigator_user_agent })
7
- }
4
+ exports.navigator_userAgent_script = `
5
+ if (opts.navigator_user_agent) {
6
+ utils.replaceProperty(Object.getPrototypeOf(navigator), 'userAgent', { get: () => opts.navigator_user_agent })
7
+ }
8
8
  `;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.navigator_vendor_script = void 0;
4
- exports.navigator_vendor_script = `
5
- utils.replaceProperty(Object.getPrototypeOf(navigator), 'vendor', { get: () => opts.navigator_vendor || 'Google Inc.' })
4
+ exports.navigator_vendor_script = `
5
+ utils.replaceProperty(Object.getPrototypeOf(navigator), 'vendor', { get: () => opts.navigator_vendor || 'Google Inc.' })
6
6
  `;
@@ -1,119 +1,119 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.utils_script = void 0;
4
- exports.utils_script = `
5
- const utils = {}
6
- utils.stripProxyFromErrors = (handler = {}) => {
7
- const newHandler = {}
8
- const traps = Object.getOwnPropertyNames(handler)
9
- traps.forEach(trap => {
10
- newHandler[trap] = function() {
11
- try { return handler[trap].apply(this, arguments || []) } catch (err) {
12
- if (!err || !err.stack || !err.stack.includes('at ')) { throw err }
13
- const stripWithBlacklist = stack => {
14
- const blacklist = ['at Reflect.' + trap + ' ', 'at Object.' + trap + ' ', 'at Object.newHandler.<computed> [as ' + trap + '] ']
15
- return err.stack.split('\\n').filter((line, index) => index !== 1).filter(line => !blacklist.some(bl => line.trim().startsWith(bl))).join('\\n')
16
- }
17
- const stripWithAnchor = stack => {
18
- const stackArr = stack.split('\\n')
19
- const anchor = 'at Object.newHandler.<computed> [as ' + trap + '] '
20
- const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))
21
- if (anchorIndex === -1) return false
22
- stackArr.splice(1, anchorIndex)
23
- return stackArr.join('\\n')
24
- }
25
- err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)
26
- throw err
27
- }
28
- }
29
- })
30
- return newHandler
31
- }
32
- utils.stripErrorWithAnchor = (err, anchor) => {
33
- const stackArr = err.stack.split('\\n')
34
- const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))
35
- if (anchorIndex === -1) return err
36
- stackArr.splice(1, anchorIndex)
37
- err.stack = stackArr.join('\\n')
38
- return err
39
- }
40
- utils.replaceProperty = (obj, propName, descriptorOverrides = {}) => {
41
- return Object.defineProperty(obj, propName, { ...(Object.getOwnPropertyDescriptor(obj, propName) || {}), ...descriptorOverrides })
42
- }
43
- utils.preloadCache = () => {
44
- if (utils.cache) return
45
- utils.cache = { Reflect: { get: Reflect.get.bind(Reflect), apply: Reflect.apply.bind(Reflect) }, nativeToStringStr: Function.toString + '' }
46
- }
47
- utils.makeNativeString = (name = '') => { utils.preloadCache(); return utils.cache.nativeToStringStr.replace('toString', name || '') }
48
- utils.patchToString = (obj, str = '') => {
49
- utils.preloadCache()
50
- const toStringProxy = new Proxy(Function.prototype.toString, {
51
- apply: function(target, ctx) {
52
- if (ctx === Function.prototype.toString) return utils.makeNativeString('toString')
53
- if (ctx === obj) return str || utils.makeNativeString(obj.name)
54
- const hasSameProto = Object.getPrototypeOf(Function.prototype.toString).isPrototypeOf(ctx.toString)
55
- if (!hasSameProto) return ctx.toString()
56
- return target.call(ctx)
57
- }
58
- })
59
- utils.replaceProperty(Function.prototype, 'toString', { value: toStringProxy })
60
- }
61
- utils.patchToStringNested = (obj = {}) => { return utils.execRecursively(obj, ['function'], utils.patchToString) }
62
- utils.redirectToString = (proxyObj, originalObj) => {
63
- utils.preloadCache()
64
- const toStringProxy = new Proxy(Function.prototype.toString, {
65
- apply: function(target, ctx) {
66
- if (ctx === Function.prototype.toString) return utils.makeNativeString('toString')
67
- if (ctx === proxyObj) {
68
- const fallback = () => originalObj && originalObj.name ? utils.makeNativeString(originalObj.name) : utils.makeNativeString(proxyObj.name)
69
- return originalObj + '' || fallback()
70
- }
71
- const hasSameProto = Object.getPrototypeOf(Function.prototype.toString).isPrototypeOf(ctx.toString)
72
- if (!hasSameProto) return ctx.toString()
73
- return target.call(ctx)
74
- }
75
- })
76
- utils.replaceProperty(Function.prototype, 'toString', { value: toStringProxy })
77
- }
78
- utils.replaceWithProxy = (obj, propName, handler) => {
79
- utils.preloadCache()
80
- const originalObj = obj[propName]
81
- const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))
82
- utils.replaceProperty(obj, propName, { value: proxyObj })
83
- utils.redirectToString(proxyObj, originalObj)
84
- return true
85
- }
86
- utils.mockWithProxy = (obj, propName, pseudoTarget, handler) => {
87
- utils.preloadCache()
88
- const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))
89
- utils.replaceProperty(obj, propName, { value: proxyObj })
90
- utils.patchToString(proxyObj)
91
- return true
92
- }
93
- utils.createProxy = (pseudoTarget, handler) => {
94
- utils.preloadCache()
95
- const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))
96
- utils.patchToString(proxyObj)
97
- return proxyObj
98
- }
99
- utils.splitObjPath = objPath => ({
100
- objName: objPath.split('.').slice(0, -1).join('.'),
101
- propName: objPath.split('.').slice(-1)[0]
102
- })
103
- utils.replaceObjPathWithProxy = (objPath, handler) => {
104
- const { objName, propName } = utils.splitObjPath(objPath)
105
- const obj = eval(objName)
106
- return utils.replaceWithProxy(obj, propName, handler)
107
- }
108
- utils.execRecursively = (obj = {}, typeFilter = [], fn) => {
109
- function recurse(obj) {
110
- for (const key in obj) {
111
- if (obj[key] === undefined) continue
112
- if (obj[key] && typeof obj[key] === 'object') recurse(obj[key])
113
- else if (obj[key] && typeFilter.includes(typeof obj[key])) fn.call(this, obj[key])
114
- }
115
- }
116
- recurse(obj)
117
- return obj
118
- }
4
+ exports.utils_script = `
5
+ const utils = {}
6
+ utils.stripProxyFromErrors = (handler = {}) => {
7
+ const newHandler = {}
8
+ const traps = Object.getOwnPropertyNames(handler)
9
+ traps.forEach(trap => {
10
+ newHandler[trap] = function() {
11
+ try { return handler[trap].apply(this, arguments || []) } catch (err) {
12
+ if (!err || !err.stack || !err.stack.includes('at ')) { throw err }
13
+ const stripWithBlacklist = stack => {
14
+ const blacklist = ['at Reflect.' + trap + ' ', 'at Object.' + trap + ' ', 'at Object.newHandler.<computed> [as ' + trap + '] ']
15
+ return err.stack.split('\\n').filter((line, index) => index !== 1).filter(line => !blacklist.some(bl => line.trim().startsWith(bl))).join('\\n')
16
+ }
17
+ const stripWithAnchor = stack => {
18
+ const stackArr = stack.split('\\n')
19
+ const anchor = 'at Object.newHandler.<computed> [as ' + trap + '] '
20
+ const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))
21
+ if (anchorIndex === -1) return false
22
+ stackArr.splice(1, anchorIndex)
23
+ return stackArr.join('\\n')
24
+ }
25
+ err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)
26
+ throw err
27
+ }
28
+ }
29
+ })
30
+ return newHandler
31
+ }
32
+ utils.stripErrorWithAnchor = (err, anchor) => {
33
+ const stackArr = err.stack.split('\\n')
34
+ const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))
35
+ if (anchorIndex === -1) return err
36
+ stackArr.splice(1, anchorIndex)
37
+ err.stack = stackArr.join('\\n')
38
+ return err
39
+ }
40
+ utils.replaceProperty = (obj, propName, descriptorOverrides = {}) => {
41
+ return Object.defineProperty(obj, propName, { ...(Object.getOwnPropertyDescriptor(obj, propName) || {}), ...descriptorOverrides })
42
+ }
43
+ utils.preloadCache = () => {
44
+ if (utils.cache) return
45
+ utils.cache = { Reflect: { get: Reflect.get.bind(Reflect), apply: Reflect.apply.bind(Reflect) }, nativeToStringStr: Function.toString + '' }
46
+ }
47
+ utils.makeNativeString = (name = '') => { utils.preloadCache(); return utils.cache.nativeToStringStr.replace('toString', name || '') }
48
+ utils.patchToString = (obj, str = '') => {
49
+ utils.preloadCache()
50
+ const toStringProxy = new Proxy(Function.prototype.toString, {
51
+ apply: function(target, ctx) {
52
+ if (ctx === Function.prototype.toString) return utils.makeNativeString('toString')
53
+ if (ctx === obj) return str || utils.makeNativeString(obj.name)
54
+ const hasSameProto = Object.getPrototypeOf(Function.prototype.toString).isPrototypeOf(ctx.toString)
55
+ if (!hasSameProto) return ctx.toString()
56
+ return target.call(ctx)
57
+ }
58
+ })
59
+ utils.replaceProperty(Function.prototype, 'toString', { value: toStringProxy })
60
+ }
61
+ utils.patchToStringNested = (obj = {}) => { return utils.execRecursively(obj, ['function'], utils.patchToString) }
62
+ utils.redirectToString = (proxyObj, originalObj) => {
63
+ utils.preloadCache()
64
+ const toStringProxy = new Proxy(Function.prototype.toString, {
65
+ apply: function(target, ctx) {
66
+ if (ctx === Function.prototype.toString) return utils.makeNativeString('toString')
67
+ if (ctx === proxyObj) {
68
+ const fallback = () => originalObj && originalObj.name ? utils.makeNativeString(originalObj.name) : utils.makeNativeString(proxyObj.name)
69
+ return originalObj + '' || fallback()
70
+ }
71
+ const hasSameProto = Object.getPrototypeOf(Function.prototype.toString).isPrototypeOf(ctx.toString)
72
+ if (!hasSameProto) return ctx.toString()
73
+ return target.call(ctx)
74
+ }
75
+ })
76
+ utils.replaceProperty(Function.prototype, 'toString', { value: toStringProxy })
77
+ }
78
+ utils.replaceWithProxy = (obj, propName, handler) => {
79
+ utils.preloadCache()
80
+ const originalObj = obj[propName]
81
+ const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))
82
+ utils.replaceProperty(obj, propName, { value: proxyObj })
83
+ utils.redirectToString(proxyObj, originalObj)
84
+ return true
85
+ }
86
+ utils.mockWithProxy = (obj, propName, pseudoTarget, handler) => {
87
+ utils.preloadCache()
88
+ const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))
89
+ utils.replaceProperty(obj, propName, { value: proxyObj })
90
+ utils.patchToString(proxyObj)
91
+ return true
92
+ }
93
+ utils.createProxy = (pseudoTarget, handler) => {
94
+ utils.preloadCache()
95
+ const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))
96
+ utils.patchToString(proxyObj)
97
+ return proxyObj
98
+ }
99
+ utils.splitObjPath = objPath => ({
100
+ objName: objPath.split('.').slice(0, -1).join('.'),
101
+ propName: objPath.split('.').slice(-1)[0]
102
+ })
103
+ utils.replaceObjPathWithProxy = (objPath, handler) => {
104
+ const { objName, propName } = utils.splitObjPath(objPath)
105
+ const obj = eval(objName)
106
+ return utils.replaceWithProxy(obj, propName, handler)
107
+ }
108
+ utils.execRecursively = (obj = {}, typeFilter = [], fn) => {
109
+ function recurse(obj) {
110
+ for (const key in obj) {
111
+ if (obj[key] === undefined) continue
112
+ if (obj[key] && typeof obj[key] === 'object') recurse(obj[key])
113
+ else if (obj[key] && typeFilter.includes(typeof obj[key])) fn.call(this, obj[key])
114
+ }
115
+ }
116
+ recurse(obj)
117
+ return obj
118
+ }
119
119
  `;
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.webgl_vendor_script = void 0;
4
- exports.webgl_vendor_script = `
5
- const getParameterProxy = {
6
- apply: function(target, ctx, args) {
7
- const param = (args || [])[0]
8
- const UNMASKED_VENDOR_WEBGL = 0x9245
9
- const UNMASKED_RENDERER_WEBGL = 0x9246
10
- if (param === UNMASKED_VENDOR_WEBGL) { return opts.webgl_vendor || 'Intel Inc.' }
11
- if (param === UNMASKED_RENDERER_WEBGL) { return opts.webgl_renderer || 'Intel Iris OpenGL Engine' }
12
- return utils.cache.Reflect.apply(target, ctx, args)
13
- }
14
- }
15
- utils.replaceWithProxy(WebGLRenderingContext.prototype, 'getParameter', getParameterProxy)
4
+ exports.webgl_vendor_script = `
5
+ const getParameterProxy = {
6
+ apply: function(target, ctx, args) {
7
+ const param = (args || [])[0]
8
+ const UNMASKED_VENDOR_WEBGL = 0x9245
9
+ const UNMASKED_RENDERER_WEBGL = 0x9246
10
+ if (param === UNMASKED_VENDOR_WEBGL) { return opts.webgl_vendor || 'Intel Inc.' }
11
+ if (param === UNMASKED_RENDERER_WEBGL) { return opts.webgl_renderer || 'Intel Iris OpenGL Engine' }
12
+ return utils.cache.Reflect.apply(target, ctx, args)
13
+ }
14
+ }
15
+ utils.replaceWithProxy(WebGLRenderingContext.prototype, 'getParameter', getParameterProxy)
16
16
  `;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.window_outerdimensions = void 0;
4
- exports.window_outerdimensions = `
5
- try {
6
- if (window.outerWidth === 0) { Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth }) }
7
- if (window.outerHeight === 0) { Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight }) }
8
- } catch (err) { /* noop */ }
4
+ exports.window_outerdimensions = `
5
+ try {
6
+ if (window.outerWidth === 0) { Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth }) }
7
+ if (window.outerHeight === 0) { Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight }) }
8
+ } catch (err) { /* noop */ }
9
9
  `;
package/package.json CHANGED
@@ -1,49 +1,49 @@
1
- {
2
- "name": "untiktok-api",
3
- "version": "1.0.3",
4
- "description": "Unofficial TikTok API wrapper in TypeScript (ported from Python)",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "scripts": {
8
- "build": "tsc -p tsconfig.build.json",
9
- "dev": "ts-node src/index.ts",
10
- "typecheck": "tsc --noEmit",
11
- "lint": "eslint src",
12
- "clean": "rimraf dist",
13
- "prepublishOnly": "npm run clean && npm run build"
14
- },
15
- "files": [
16
- "dist"
17
- ],
18
- "keywords": [
19
- "tiktok",
20
- "api",
21
- "scraper",
22
- "typescript",
23
- "playwright"
24
- ],
25
- "author": "AlGhozaliRamadhan",
26
- "license": "MIT",
27
- "repository": {
28
- "type": "git",
29
- "url": "git+https://github.com/AlGhozaliRamadhan/UnTikTok-Api.git"
30
- },
31
- "bugs": {
32
- "url": "https://github.com/AlGhozaliRamadhan/UnTikTok-Api/issues"
33
- },
34
- "homepage": "https://github.com/AlGhozaliRamadhan/UnTikTok-Api#readme",
35
- "dependencies": {
36
- "axios": "^1.17.0",
37
- "https-proxy-agent": "^9.1.0",
38
- "playwright": "^1.44.0"
39
- },
40
- "devDependencies": {
41
- "@eslint/js": "^10.0.1",
42
- "@types/node": "^25.9.3",
43
- "eslint": "^10.5.0",
44
- "rimraf": "^6.1.3",
45
- "ts-node": "^10.9.2",
46
- "typescript": "^6.0.3",
47
- "typescript-eslint": "^8.61.0"
48
- }
49
- }
1
+ {
2
+ "name": "untiktok-api",
3
+ "version": "1.0.4",
4
+ "description": "Unofficial TikTok API wrapper in TypeScript (ported from Python)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc -p tsconfig.build.json",
9
+ "dev": "ts-node src/index.ts",
10
+ "typecheck": "tsc --noEmit",
11
+ "lint": "eslint src",
12
+ "clean": "rimraf dist",
13
+ "prepublishOnly": "npm run clean && npm run build"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "keywords": [
19
+ "tiktok",
20
+ "api",
21
+ "scraper",
22
+ "typescript",
23
+ "playwright"
24
+ ],
25
+ "author": "AlGhozaliRamadhan",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/AlGhozaliRamadhan/UnTikTok-Api.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/AlGhozaliRamadhan/UnTikTok-Api/issues"
33
+ },
34
+ "homepage": "https://github.com/AlGhozaliRamadhan/UnTikTok-Api#readme",
35
+ "dependencies": {
36
+ "axios": "^1.17.0",
37
+ "https-proxy-agent": "^9.1.0",
38
+ "playwright": "^1.44.0"
39
+ },
40
+ "devDependencies": {
41
+ "@eslint/js": "^10.0.1",
42
+ "@types/node": "^25.9.3",
43
+ "eslint": "^10.5.0",
44
+ "rimraf": "^6.1.3",
45
+ "ts-node": "^10.9.2",
46
+ "typescript": "^6.0.3",
47
+ "typescript-eslint": "^8.61.0"
48
+ }
49
+ }