agent-messenger 1.0.0 → 1.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/.claude/commands/release.md +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/e2e.yml.disabled +69 -0
- package/README.md +16 -14
- package/biome.json +33 -1
- package/bun.lock +63 -0
- package/dist/package.json +8 -4
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +4 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/platforms/discord/cli.js +1 -1
- package/dist/src/platforms/discord/client.d.ts.map +1 -1
- package/dist/src/platforms/discord/client.js +3 -3
- package/dist/src/platforms/discord/client.js.map +1 -1
- package/dist/src/platforms/discord/commands/user.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/user.js +10 -1
- package/dist/src/platforms/discord/commands/user.js.map +1 -1
- package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/discord/credential-manager.js +18 -12
- package/dist/src/platforms/discord/credential-manager.js.map +1 -1
- package/dist/src/platforms/slack/cli.js +1 -1
- package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/slack/credential-manager.js +20 -6
- package/dist/src/platforms/slack/credential-manager.js.map +1 -1
- package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/slack/token-extractor.js +34 -9
- package/dist/src/platforms/slack/token-extractor.js.map +1 -1
- package/dist/src/platforms/teams/cli.d.ts.map +1 -0
- package/dist/{cli.js → src/platforms/teams/cli.js} +11 -10
- package/dist/src/platforms/teams/cli.js.map +1 -0
- package/dist/src/platforms/teams/client.d.ts +32 -0
- package/dist/src/platforms/teams/client.d.ts.map +1 -0
- package/dist/src/platforms/teams/client.js +202 -0
- package/dist/src/platforms/teams/client.js.map +1 -0
- package/dist/src/platforms/teams/commands/auth.d.ts +14 -0
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/auth.js +176 -0
- package/dist/src/platforms/teams/commands/auth.js.map +1 -0
- package/dist/src/platforms/teams/commands/channel.d.ts +13 -0
- package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/channel.js +97 -0
- package/dist/src/platforms/teams/commands/channel.js.map +1 -0
- package/dist/src/platforms/teams/commands/file.d.ts +12 -0
- package/dist/src/platforms/teams/commands/file.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/file.js +104 -0
- package/dist/src/platforms/teams/commands/file.js.map +1 -0
- package/dist/{commands → src/platforms/teams/commands}/index.d.ts +5 -2
- package/dist/src/platforms/teams/commands/index.d.ts.map +1 -0
- package/dist/{commands → src/platforms/teams/commands}/index.js +5 -2
- package/dist/src/platforms/teams/commands/index.js.map +1 -0
- package/dist/src/platforms/teams/commands/message.d.ts +17 -0
- package/dist/src/platforms/teams/commands/message.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/message.js +133 -0
- package/dist/src/platforms/teams/commands/message.js.map +1 -0
- package/dist/src/platforms/teams/commands/reaction.d.ts +9 -0
- package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/reaction.js +68 -0
- package/dist/src/platforms/teams/commands/reaction.js.map +1 -0
- package/dist/src/platforms/teams/commands/snapshot.d.ts +10 -0
- package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/snapshot.js +85 -0
- package/dist/src/platforms/teams/commands/snapshot.js.map +1 -0
- package/dist/src/platforms/teams/commands/team.d.ts +18 -0
- package/dist/src/platforms/teams/commands/team.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/team.js +130 -0
- package/dist/src/platforms/teams/commands/team.js.map +1 -0
- package/dist/src/platforms/teams/commands/user.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/user.js +88 -0
- package/dist/src/platforms/teams/commands/user.js.map +1 -0
- package/dist/src/platforms/teams/credential-manager.d.ts +18 -0
- package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -0
- package/dist/src/platforms/teams/credential-manager.js +81 -0
- package/dist/src/platforms/teams/credential-manager.js.map +1 -0
- package/dist/src/platforms/teams/index.d.ts +4 -0
- package/dist/src/platforms/teams/index.d.ts.map +1 -0
- package/dist/src/platforms/teams/index.js +6 -0
- package/dist/src/platforms/teams/index.js.map +1 -0
- package/dist/src/platforms/teams/token-extractor.d.ts +36 -0
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -0
- package/dist/src/platforms/teams/token-extractor.js +335 -0
- package/dist/src/platforms/teams/token-extractor.js.map +1 -0
- package/dist/src/platforms/teams/types.d.ts +209 -0
- package/dist/src/platforms/teams/types.d.ts.map +1 -0
- package/dist/src/platforms/teams/types.js +65 -0
- package/dist/src/platforms/teams/types.js.map +1 -0
- package/docs/teams.md +321 -0
- package/e2e/README.md +256 -0
- package/e2e/config.ts +45 -0
- package/e2e/discord.e2e.test.ts +252 -0
- package/e2e/helpers.ts +107 -0
- package/e2e/slack.e2e.test.ts +309 -0
- package/package.json +8 -4
- package/scripts/postbuild.ts +15 -0
- package/skills/agent-teams/SKILL.md +292 -0
- package/skills/agent-teams/references/authentication.md +375 -0
- package/skills/agent-teams/references/common-patterns.md +596 -0
- package/skills/agent-teams/templates/monitor-channel.sh +239 -0
- package/skills/agent-teams/templates/post-message.sh +224 -0
- package/skills/agent-teams/templates/team-summary.sh +210 -0
- package/src/cli.ts +4 -0
- package/src/platforms/discord/client.ts +3 -3
- package/src/platforms/discord/commands/auth.test.ts +48 -32
- package/src/platforms/discord/commands/channel.test.ts +54 -42
- package/src/platforms/discord/commands/file.test.ts +40 -53
- package/src/platforms/discord/commands/guild.test.ts +47 -27
- package/src/platforms/discord/commands/message.test.ts +54 -51
- package/src/platforms/discord/commands/reaction.test.ts +54 -42
- package/src/platforms/discord/commands/user.ts +12 -1
- package/src/platforms/discord/credential-manager.test.ts +137 -136
- package/src/platforms/discord/credential-manager.ts +20 -13
- package/src/platforms/discord/token-extractor.test.ts +133 -383
- package/{tests → src/platforms/slack}/cli.test.ts +3 -3
- package/{tests/slack-client.test.ts → src/platforms/slack/client.test.ts} +1 -1
- package/{tests → src/platforms/slack}/commands/auth.test.ts +25 -13
- package/{tests → src/platforms/slack}/commands/channel.test.ts +2 -2
- package/{tests → src/platforms/slack}/commands/file.test.ts +2 -2
- package/{tests → src/platforms/slack}/commands/message.test.ts +2 -2
- package/{tests → src/platforms/slack}/commands/reaction.test.ts +1 -1
- package/{tests → src/platforms/slack}/commands/snapshot.test.ts +117 -105
- package/{tests → src/platforms/slack}/commands/user.test.ts +3 -3
- package/{tests → src/platforms/slack}/commands/workspace.test.ts +44 -95
- package/{tests → src/platforms/slack}/credential-manager.test.ts +2 -2
- package/src/platforms/slack/credential-manager.ts +22 -7
- package/src/platforms/slack/token-extractor-node-test.ts +40 -0
- package/src/platforms/slack/token-extractor-node.test.ts +10 -0
- package/src/platforms/slack/token-extractor.ts +36 -10
- package/{tests → src/platforms/slack}/types.test.ts +1 -1
- package/src/platforms/teams/cli.ts +36 -0
- package/src/platforms/teams/client.test.ts +500 -0
- package/src/platforms/teams/client.ts +365 -0
- package/src/platforms/teams/commands/auth.test.ts +99 -0
- package/src/platforms/teams/commands/auth.ts +232 -0
- package/src/platforms/teams/commands/channel.test.ts +147 -0
- package/src/platforms/teams/commands/channel.ts +129 -0
- package/src/platforms/teams/commands/file.test.ts +88 -0
- package/src/platforms/teams/commands/file.ts +144 -0
- package/src/platforms/teams/commands/index.ts +12 -0
- package/src/platforms/teams/commands/message.test.ts +110 -0
- package/src/platforms/teams/commands/message.ts +188 -0
- package/src/platforms/teams/commands/reaction.test.ts +87 -0
- package/src/platforms/teams/commands/reaction.ts +104 -0
- package/src/platforms/teams/commands/snapshot.test.ts +35 -0
- package/src/platforms/teams/commands/snapshot.ts +115 -0
- package/src/platforms/teams/commands/team.test.ts +157 -0
- package/src/platforms/teams/commands/team.ts +164 -0
- package/src/platforms/teams/commands/user.test.ts +83 -0
- package/src/platforms/teams/commands/user.ts +112 -0
- package/src/platforms/teams/credential-manager.test.ts +178 -0
- package/src/platforms/teams/credential-manager.ts +92 -0
- package/src/platforms/teams/index.ts +5 -0
- package/src/platforms/teams/token-extractor.test.ts +429 -0
- package/src/platforms/teams/token-extractor.ts +462 -0
- package/src/platforms/teams/types.test.ts +226 -0
- package/src/platforms/teams/types.ts +140 -0
- package/tsconfig.json +1 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/auth.d.ts +0 -3
- package/dist/commands/auth.d.ts.map +0 -1
- package/dist/commands/auth.js +0 -140
- package/dist/commands/auth.js.map +0 -1
- package/dist/commands/channel.d.ts +0 -3
- package/dist/commands/channel.d.ts.map +0 -1
- package/dist/commands/channel.js +0 -118
- package/dist/commands/channel.js.map +0 -1
- package/dist/commands/file.d.ts +0 -3
- package/dist/commands/file.d.ts.map +0 -1
- package/dist/commands/file.js +0 -113
- package/dist/commands/file.js.map +0 -1
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/message.d.ts +0 -3
- package/dist/commands/message.d.ts.map +0 -1
- package/dist/commands/message.js +0 -214
- package/dist/commands/message.js.map +0 -1
- package/dist/commands/reaction.d.ts +0 -3
- package/dist/commands/reaction.d.ts.map +0 -1
- package/dist/commands/reaction.js +0 -100
- package/dist/commands/reaction.js.map +0 -1
- package/dist/commands/snapshot.d.ts +0 -3
- package/dist/commands/snapshot.d.ts.map +0 -1
- package/dist/commands/snapshot.js +0 -88
- package/dist/commands/snapshot.js.map +0 -1
- package/dist/commands/user.d.ts.map +0 -1
- package/dist/commands/user.js +0 -96
- package/dist/commands/user.js.map +0 -1
- package/dist/commands/workspace.d.ts +0 -3
- package/dist/commands/workspace.d.ts.map +0 -1
- package/dist/commands/workspace.js +0 -89
- package/dist/commands/workspace.js.map +0 -1
- package/dist/lib/credential-manager.d.ts +0 -13
- package/dist/lib/credential-manager.d.ts.map +0 -1
- package/dist/lib/credential-manager.js +0 -58
- package/dist/lib/credential-manager.js.map +0 -1
- package/dist/lib/index.d.ts +0 -3
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js +0 -3
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/ref-manager.d.ts +0 -26
- package/dist/lib/ref-manager.d.ts.map +0 -1
- package/dist/lib/ref-manager.js +0 -92
- package/dist/lib/ref-manager.js.map +0 -1
- package/dist/lib/slack-client.d.ts +0 -37
- package/dist/lib/slack-client.d.ts.map +0 -1
- package/dist/lib/slack-client.js +0 -379
- package/dist/lib/slack-client.js.map +0 -1
- package/dist/lib/token-extractor.d.ts +0 -28
- package/dist/lib/token-extractor.d.ts.map +0 -1
- package/dist/lib/token-extractor.js +0 -401
- package/dist/lib/token-extractor.js.map +0 -1
- package/dist/src/platforms/discord/client.test.d.ts +0 -2
- package/dist/src/platforms/discord/client.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/client.test.js +0 -367
- package/dist/src/platforms/discord/client.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/auth.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/auth.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/auth.test.js +0 -65
- package/dist/src/platforms/discord/commands/auth.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/channel.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/channel.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/channel.test.js +0 -136
- package/dist/src/platforms/discord/commands/channel.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/file.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/file.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/file.test.js +0 -83
- package/dist/src/platforms/discord/commands/file.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/guild.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/guild.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/guild.test.js +0 -100
- package/dist/src/platforms/discord/commands/guild.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/message.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/message.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/message.test.js +0 -91
- package/dist/src/platforms/discord/commands/message.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/reaction.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/reaction.test.js +0 -115
- package/dist/src/platforms/discord/commands/reaction.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/snapshot.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/snapshot.test.js +0 -25
- package/dist/src/platforms/discord/commands/snapshot.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/user.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/user.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/user.test.js +0 -103
- package/dist/src/platforms/discord/commands/user.test.js.map +0 -1
- package/dist/src/platforms/discord/credential-manager.test.d.ts +0 -2
- package/dist/src/platforms/discord/credential-manager.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/credential-manager.test.js +0 -136
- package/dist/src/platforms/discord/credential-manager.test.js.map +0 -1
- package/dist/src/platforms/discord/token-extractor.test.d.ts +0 -2
- package/dist/src/platforms/discord/token-extractor.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/token-extractor.test.js +0 -789
- package/dist/src/platforms/discord/token-extractor.test.js.map +0 -1
- package/dist/src/platforms/discord/types.test.d.ts +0 -2
- package/dist/src/platforms/discord/types.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/types.test.js +0 -211
- package/dist/src/platforms/discord/types.test.js.map +0 -1
- package/dist/src/shared/utils/concurrency.test.d.ts +0 -2
- package/dist/src/shared/utils/concurrency.test.d.ts.map +0 -1
- package/dist/src/shared/utils/concurrency.test.js +0 -39
- package/dist/src/shared/utils/concurrency.test.js.map +0 -1
- package/dist/tests/cli.test.d.ts +0 -2
- package/dist/tests/cli.test.d.ts.map +0 -1
- package/dist/tests/cli.test.js +0 -83
- package/dist/tests/cli.test.js.map +0 -1
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +0 -1
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +0 -3
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +0 -1
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
- package/dist/tests/commands/auth.test.d.ts +0 -2
- package/dist/tests/commands/auth.test.d.ts.map +0 -1
- package/dist/tests/commands/auth.test.js +0 -304
- package/dist/tests/commands/auth.test.js.map +0 -1
- package/dist/tests/commands/channel.test.d.ts +0 -2
- package/dist/tests/commands/channel.test.d.ts.map +0 -1
- package/dist/tests/commands/channel.test.js +0 -166
- package/dist/tests/commands/channel.test.js.map +0 -1
- package/dist/tests/commands/file.test.d.ts +0 -2
- package/dist/tests/commands/file.test.d.ts.map +0 -1
- package/dist/tests/commands/file.test.js +0 -175
- package/dist/tests/commands/file.test.js.map +0 -1
- package/dist/tests/commands/message.test.d.ts +0 -2
- package/dist/tests/commands/message.test.d.ts.map +0 -1
- package/dist/tests/commands/message.test.js +0 -293
- package/dist/tests/commands/message.test.js.map +0 -1
- package/dist/tests/commands/reaction.test.d.ts +0 -2
- package/dist/tests/commands/reaction.test.d.ts.map +0 -1
- package/dist/tests/commands/reaction.test.js +0 -84
- package/dist/tests/commands/reaction.test.js.map +0 -1
- package/dist/tests/commands/snapshot.test.d.ts +0 -2
- package/dist/tests/commands/snapshot.test.d.ts.map +0 -1
- package/dist/tests/commands/snapshot.test.js +0 -280
- package/dist/tests/commands/snapshot.test.js.map +0 -1
- package/dist/tests/commands/user.test.d.ts +0 -2
- package/dist/tests/commands/user.test.d.ts.map +0 -1
- package/dist/tests/commands/user.test.js +0 -117
- package/dist/tests/commands/user.test.js.map +0 -1
- package/dist/tests/commands/workspace.test.d.ts +0 -2
- package/dist/tests/commands/workspace.test.d.ts.map +0 -1
- package/dist/tests/commands/workspace.test.js +0 -453
- package/dist/tests/commands/workspace.test.js.map +0 -1
- package/dist/tests/credential-manager.test.d.ts +0 -2
- package/dist/tests/credential-manager.test.d.ts.map +0 -1
- package/dist/tests/credential-manager.test.js +0 -199
- package/dist/tests/credential-manager.test.js.map +0 -1
- package/dist/tests/slack-client.test.d.ts +0 -2
- package/dist/tests/slack-client.test.d.ts.map +0 -1
- package/dist/tests/slack-client.test.js +0 -741
- package/dist/tests/slack-client.test.js.map +0 -1
- package/dist/tests/types.test.d.ts +0 -2
- package/dist/tests/types.test.d.ts.map +0 -1
- package/dist/tests/types.test.js +0 -215
- package/dist/tests/types.test.js.map +0 -1
- package/dist/types/index.d.ts +0 -369
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -92
- package/dist/types/index.js.map +0 -1
- package/dist/utils/error-handler.d.ts +0 -2
- package/dist/utils/error-handler.d.ts.map +0 -1
- package/dist/utils/error-handler.js +0 -5
- package/dist/utils/error-handler.js.map +0 -1
- package/dist/utils/output.d.ts +0 -2
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/output.js +0 -4
- package/dist/utils/output.js.map +0 -1
- /package/dist/{cli.d.ts → src/platforms/teams/cli.d.ts} +0 -0
- /package/dist/{commands → src/platforms/teams/commands}/user.d.ts +0 -0
|
@@ -1,32 +1,23 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, mock, test } from 'bun:test'
|
|
2
|
-
import { execSync, spawn } from 'node:child_process'
|
|
3
|
-
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from 'bun:test'
|
|
4
2
|
import { homedir } from 'node:os'
|
|
5
3
|
import { join } from 'node:path'
|
|
6
4
|
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
// Mock modules
|
|
10
|
-
mock.module('node:fs', () => ({
|
|
11
|
-
existsSync: mock(() => false),
|
|
12
|
-
readdirSync: mock(() => []),
|
|
13
|
-
readFileSync: mock(() => Buffer.from('')),
|
|
14
|
-
}))
|
|
15
|
-
|
|
16
|
-
const mockSpawn = mock(() => ({
|
|
17
|
-
unref: mock(() => {}),
|
|
18
|
-
}))
|
|
19
|
-
|
|
20
|
-
mock.module('node:child_process', () => ({
|
|
21
|
-
execSync: mock(() => ''),
|
|
22
|
-
spawn: mockSpawn,
|
|
23
|
-
}))
|
|
5
|
+
import { DiscordTokenExtractor, TOKEN_EXTRACTION_JS } from './token-extractor'
|
|
24
6
|
|
|
25
7
|
describe('DiscordTokenExtractor', () => {
|
|
26
8
|
let extractor: DiscordTokenExtractor
|
|
9
|
+
let originalFetch: typeof fetch
|
|
10
|
+
let originalWebSocket: typeof WebSocket
|
|
27
11
|
|
|
28
12
|
beforeEach(() => {
|
|
29
13
|
extractor = new DiscordTokenExtractor()
|
|
14
|
+
originalFetch = globalThis.fetch
|
|
15
|
+
originalWebSocket = globalThis.WebSocket
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
globalThis.fetch = originalFetch
|
|
20
|
+
globalThis.WebSocket = originalWebSocket
|
|
30
21
|
})
|
|
31
22
|
|
|
32
23
|
describe('getDiscordDirs', () => {
|
|
@@ -66,8 +57,7 @@ describe('DiscordTokenExtractor', () => {
|
|
|
66
57
|
|
|
67
58
|
describe('token patterns', () => {
|
|
68
59
|
test('validates standard token format (base64.base64.base64)', () => {
|
|
69
|
-
|
|
70
|
-
const validToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.abcdefghijklmnopqrstuvwxyz1234567890'
|
|
60
|
+
const validToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.ZZZZZZZZZZZZZZZZZZZZZZZZZ'
|
|
71
61
|
expect(extractor.isValidToken(validToken)).toBe(true)
|
|
72
62
|
})
|
|
73
63
|
|
|
@@ -91,182 +81,79 @@ describe('DiscordTokenExtractor', () => {
|
|
|
91
81
|
|
|
92
82
|
describe('extract', () => {
|
|
93
83
|
test('returns null when no Discord directories exist on linux', async () => {
|
|
94
|
-
const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
|
|
95
|
-
mockExistsSync.mockImplementation(() => false)
|
|
96
|
-
|
|
97
84
|
const linuxExtractor = new DiscordTokenExtractor('linux')
|
|
85
|
+
const extractFromLevelDBSpy = spyOn(
|
|
86
|
+
linuxExtractor as any,
|
|
87
|
+
'extractFromLevelDB'
|
|
88
|
+
).mockResolvedValue(null)
|
|
89
|
+
|
|
98
90
|
const result = await linuxExtractor.extract()
|
|
99
91
|
expect(result).toBeNull()
|
|
100
|
-
})
|
|
101
92
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const ldbContent = Buffer.from(`some_data"${mockToken}"more_data`)
|
|
105
|
-
|
|
106
|
-
const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
|
|
107
|
-
mockExistsSync.mockImplementation((path: string) => {
|
|
108
|
-
if (path.includes('discord') || path.includes('leveldb')) return true
|
|
109
|
-
if (path.includes('Local Storage')) return true
|
|
110
|
-
return false
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
|
|
114
|
-
mockReaddirSync.mockImplementation((path: string) => {
|
|
115
|
-
if (path.includes('leveldb')) return ['000001.ldb']
|
|
116
|
-
if (path.includes('Local Storage')) return ['leveldb']
|
|
117
|
-
return []
|
|
118
|
-
})
|
|
93
|
+
extractFromLevelDBSpy.mockRestore()
|
|
94
|
+
})
|
|
119
95
|
|
|
120
|
-
|
|
121
|
-
|
|
96
|
+
test('extracts token from LevelDB when available', async () => {
|
|
97
|
+
const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.ZZZZZZZZZZZZZZZZZZZZZZZZZ'
|
|
122
98
|
|
|
123
99
|
const linuxExtractor = new DiscordTokenExtractor('linux')
|
|
100
|
+
const extractFromLevelDBSpy = spyOn(
|
|
101
|
+
linuxExtractor as any,
|
|
102
|
+
'extractFromLevelDB'
|
|
103
|
+
).mockResolvedValue({ token: mockToken })
|
|
104
|
+
|
|
124
105
|
const result = await linuxExtractor.extract()
|
|
125
106
|
|
|
126
107
|
expect(result).not.toBeNull()
|
|
127
108
|
expect(result?.token).toBe(mockToken)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
test('tries LevelDB first on macOS, CDP as fallback', async () => {
|
|
131
|
-
const levelDbToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.leveldb_token_123456789012345'
|
|
132
|
-
const ldbContent = Buffer.from(`some_data"${levelDbToken}"more_data`)
|
|
133
109
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (path.includes('Discord') || path.includes('leveldb')) return true
|
|
137
|
-
if (path.includes('Local Storage')) return true
|
|
138
|
-
return false
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
|
|
142
|
-
mockReaddirSync.mockImplementation((path: string) => {
|
|
143
|
-
if (path.includes('leveldb')) return ['000001.ldb']
|
|
144
|
-
if (path.includes('Local Storage')) return ['leveldb']
|
|
145
|
-
return []
|
|
146
|
-
})
|
|
110
|
+
extractFromLevelDBSpy.mockRestore()
|
|
111
|
+
})
|
|
147
112
|
|
|
148
|
-
|
|
149
|
-
|
|
113
|
+
test('tries CDP on macOS when LevelDB extraction fails', async () => {
|
|
114
|
+
const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.cdp_token_12345678901234567'
|
|
150
115
|
|
|
151
116
|
const darwinExtractor = new DiscordTokenExtractor('darwin', 0)
|
|
117
|
+
const extractFromLevelDBSpy = spyOn(
|
|
118
|
+
darwinExtractor as any,
|
|
119
|
+
'extractFromLevelDB'
|
|
120
|
+
).mockResolvedValue(null)
|
|
121
|
+
const tryExtractViaCDPSpy = spyOn(
|
|
122
|
+
darwinExtractor as any,
|
|
123
|
+
'tryExtractViaCDP'
|
|
124
|
+
).mockResolvedValue(mockToken)
|
|
125
|
+
|
|
152
126
|
const result = await darwinExtractor.extract()
|
|
153
127
|
|
|
154
128
|
expect(result).not.toBeNull()
|
|
155
|
-
expect(result?.token).toBe(
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
test('falls back to leveldb on macOS when CDP fails', async () => {
|
|
159
|
-
const mockToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.leveldb_fallback_token_12345'
|
|
160
|
-
const ldbContent = Buffer.from(`some_data"${mockToken}"more_data`)
|
|
161
|
-
|
|
162
|
-
const originalFetch = globalThis.fetch
|
|
163
|
-
globalThis.fetch = mock(async () => ({
|
|
164
|
-
ok: true,
|
|
165
|
-
json: async () => [],
|
|
166
|
-
})) as unknown as typeof fetch
|
|
167
|
-
|
|
168
|
-
const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
|
|
169
|
-
mockExistsSync.mockImplementation((path: string) => {
|
|
170
|
-
if (path.includes('/Applications/')) return false
|
|
171
|
-
if (path.includes('Discord') || path.includes('leveldb')) return true
|
|
172
|
-
if (path.includes('Local Storage')) return true
|
|
173
|
-
return false
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
|
|
177
|
-
mockReaddirSync.mockImplementation((path: string) => {
|
|
178
|
-
if (path.includes('leveldb')) return ['000001.ldb']
|
|
179
|
-
if (path.includes('Local Storage')) return ['leveldb']
|
|
180
|
-
return []
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
|
|
184
|
-
mockReadFileSync.mockImplementation(() => ldbContent)
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
const darwinExtractor = new DiscordTokenExtractor('darwin', 0)
|
|
188
|
-
const result = await darwinExtractor.extract()
|
|
129
|
+
expect(result?.token).toBe(mockToken)
|
|
189
130
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
} finally {
|
|
193
|
-
globalThis.fetch = originalFetch
|
|
194
|
-
}
|
|
131
|
+
extractFromLevelDBSpy.mockRestore()
|
|
132
|
+
tryExtractViaCDPSpy.mockRestore()
|
|
195
133
|
})
|
|
196
134
|
|
|
197
|
-
test('returns first valid token found across variants
|
|
198
|
-
const mockToken = '
|
|
199
|
-
const ldbContent = Buffer.from(`"${mockToken}"`)
|
|
200
|
-
|
|
201
|
-
const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
|
|
202
|
-
mockExistsSync.mockImplementation(() => true)
|
|
203
|
-
|
|
204
|
-
const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
|
|
205
|
-
mockReaddirSync.mockImplementation((path: string) => {
|
|
206
|
-
if (path.includes('leveldb')) return ['test.ldb']
|
|
207
|
-
if (path.includes('Local Storage')) return ['leveldb']
|
|
208
|
-
return []
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
|
|
212
|
-
mockReadFileSync.mockImplementation(() => ldbContent)
|
|
135
|
+
test('returns first valid token found across variants', async () => {
|
|
136
|
+
const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.first_token_found_1234567'
|
|
213
137
|
|
|
214
138
|
const linuxExtractor = new DiscordTokenExtractor('linux')
|
|
139
|
+
const extractFromLevelDBSpy = spyOn(
|
|
140
|
+
linuxExtractor as any,
|
|
141
|
+
'extractFromLevelDB'
|
|
142
|
+
).mockResolvedValue({ token: mockToken })
|
|
143
|
+
|
|
215
144
|
const result = await linuxExtractor.extract()
|
|
216
145
|
|
|
217
146
|
expect(result).not.toBeNull()
|
|
218
147
|
expect(typeof result?.token).toBe('string')
|
|
219
|
-
})
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
describe('encrypted token handling', () => {
|
|
223
|
-
test('decrypts Windows DPAPI encrypted token', async () => {
|
|
224
|
-
const mockExecSync = execSync as unknown as ReturnType<typeof mock>
|
|
225
|
-
const decryptedKey = Buffer.from('0'.repeat(32), 'hex').toString('base64')
|
|
226
|
-
|
|
227
|
-
mockExecSync.mockImplementation((cmd: string) => {
|
|
228
|
-
if (cmd.includes('powershell') && cmd.includes('ProtectedData')) {
|
|
229
|
-
return `${decryptedKey}\n`
|
|
230
|
-
}
|
|
231
|
-
return ''
|
|
232
|
-
})
|
|
233
148
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
// Mock Local State file reading
|
|
237
|
-
const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
|
|
238
|
-
mockReadFileSync.mockImplementation((path: string) => {
|
|
239
|
-
if (path.includes('Local State')) {
|
|
240
|
-
return JSON.stringify({
|
|
241
|
-
os_crypt: {
|
|
242
|
-
encrypted_key: Buffer.from(`DPAPI${'x'.repeat(32)}`).toString('base64'),
|
|
243
|
-
},
|
|
244
|
-
})
|
|
245
|
-
}
|
|
246
|
-
return Buffer.from('')
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
// Test that DPAPI decryption is called
|
|
250
|
-
const encryptedToken = `dQw4w9WgXcQ:${Buffer.from('test').toString('base64')}`
|
|
251
|
-
expect(winExtractor.isEncryptedToken(encryptedToken)).toBe(true)
|
|
149
|
+
extractFromLevelDBSpy.mockRestore()
|
|
252
150
|
})
|
|
151
|
+
})
|
|
253
152
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const keychainPassword = 'test_password'
|
|
257
|
-
|
|
258
|
-
mockExecSync.mockImplementation((cmd: string) => {
|
|
259
|
-
if (cmd.includes('security find-generic-password')) {
|
|
260
|
-
if (cmd.includes('Discord Safe Storage')) {
|
|
261
|
-
return keychainPassword
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
throw new Error('Not found')
|
|
265
|
-
})
|
|
266
|
-
|
|
153
|
+
describe('getKeychainVariants', () => {
|
|
154
|
+
test('returns keychain variants for macOS', () => {
|
|
267
155
|
const macExtractor = new DiscordTokenExtractor('darwin')
|
|
268
156
|
|
|
269
|
-
// Verify keychain command patterns
|
|
270
157
|
expect(macExtractor.getKeychainVariants()).toEqual([
|
|
271
158
|
{ service: 'discord Safe Storage', account: 'discord Key' },
|
|
272
159
|
{ service: 'discordcanary Safe Storage', account: 'discordcanary Key' },
|
|
@@ -297,177 +184,101 @@ describe('DiscordTokenExtractor', () => {
|
|
|
297
184
|
|
|
298
185
|
describe('process management', () => {
|
|
299
186
|
describe('isDiscordRunning', () => {
|
|
300
|
-
test('returns true when Discord process is found
|
|
301
|
-
const mockExecSync = execSync as unknown as ReturnType<typeof mock>
|
|
302
|
-
mockExecSync.mockImplementation((cmd: string) => {
|
|
303
|
-
if (cmd.includes('pgrep') && cmd.includes('Discord')) {
|
|
304
|
-
return '12345\n'
|
|
305
|
-
}
|
|
306
|
-
return ''
|
|
307
|
-
})
|
|
308
|
-
|
|
187
|
+
test('returns true when Discord process is found', async () => {
|
|
309
188
|
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
189
|
+
const checkProcessRunningSpy = spyOn(
|
|
190
|
+
darwinExtractor as any,
|
|
191
|
+
'checkProcessRunning'
|
|
192
|
+
).mockReturnValue(true)
|
|
193
|
+
|
|
310
194
|
const result = await darwinExtractor.isDiscordRunning('stable')
|
|
311
195
|
expect(result).toBe(true)
|
|
196
|
+
|
|
197
|
+
checkProcessRunningSpy.mockRestore()
|
|
312
198
|
})
|
|
313
199
|
|
|
314
200
|
test('returns false when no Discord process is found', async () => {
|
|
315
|
-
const mockExecSync = execSync as unknown as ReturnType<typeof mock>
|
|
316
|
-
mockExecSync.mockImplementation(() => '')
|
|
317
|
-
|
|
318
201
|
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
202
|
+
const checkProcessRunningSpy = spyOn(
|
|
203
|
+
darwinExtractor as any,
|
|
204
|
+
'checkProcessRunning'
|
|
205
|
+
).mockReturnValue(false)
|
|
206
|
+
|
|
319
207
|
const result = await darwinExtractor.isDiscordRunning('stable')
|
|
320
208
|
expect(result).toBe(false)
|
|
209
|
+
|
|
210
|
+
checkProcessRunningSpy.mockRestore()
|
|
321
211
|
})
|
|
322
212
|
|
|
323
213
|
test('checks all variants when no specific variant provided', async () => {
|
|
324
|
-
const
|
|
214
|
+
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
325
215
|
const checkedProcesses: string[] = []
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return ''
|
|
216
|
+
const checkProcessRunningSpy = spyOn(
|
|
217
|
+
darwinExtractor as any,
|
|
218
|
+
'checkProcessRunning'
|
|
219
|
+
).mockImplementation((name: string) => {
|
|
220
|
+
checkedProcesses.push(name)
|
|
221
|
+
return false
|
|
333
222
|
})
|
|
334
223
|
|
|
335
|
-
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
336
224
|
await darwinExtractor.isDiscordRunning()
|
|
337
225
|
|
|
338
226
|
expect(checkedProcesses).toContain('Discord')
|
|
339
227
|
expect(checkedProcesses).toContain('Discord Canary')
|
|
340
228
|
expect(checkedProcesses).toContain('Discord PTB')
|
|
341
|
-
})
|
|
342
|
-
|
|
343
|
-
test('returns true when Windows process is found', async () => {
|
|
344
|
-
const mockExecSync = execSync as unknown as ReturnType<typeof mock>
|
|
345
|
-
mockExecSync.mockImplementation((cmd: string) => {
|
|
346
|
-
if (cmd.includes('tasklist') && cmd.includes('Discord.exe')) {
|
|
347
|
-
return 'Discord.exe 12345 Console 1 123,456 K\n'
|
|
348
|
-
}
|
|
349
|
-
return ''
|
|
350
|
-
})
|
|
351
229
|
|
|
352
|
-
|
|
353
|
-
const result = await winExtractor.isDiscordRunning('stable')
|
|
354
|
-
expect(result).toBe(true)
|
|
230
|
+
checkProcessRunningSpy.mockRestore()
|
|
355
231
|
})
|
|
356
232
|
})
|
|
357
233
|
|
|
358
234
|
describe('killDiscord', () => {
|
|
359
|
-
test('kills Discord process
|
|
360
|
-
const
|
|
235
|
+
test('kills Discord process', async () => {
|
|
236
|
+
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
361
237
|
const killedProcesses: string[] = []
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
const match = cmd.match(/pkill -f "([^"]+)"/)
|
|
366
|
-
if (match) killedProcesses.push(match[1])
|
|
238
|
+
const killProcessSpy = spyOn(darwinExtractor as any, 'killProcess').mockImplementation(
|
|
239
|
+
(name: string) => {
|
|
240
|
+
killedProcesses.push(name)
|
|
367
241
|
}
|
|
368
|
-
|
|
369
|
-
})
|
|
242
|
+
)
|
|
370
243
|
|
|
371
|
-
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
372
244
|
await darwinExtractor.killDiscord('stable')
|
|
373
245
|
|
|
374
246
|
expect(killedProcesses).toContain('Discord')
|
|
375
|
-
})
|
|
376
|
-
|
|
377
|
-
test('kills Discord process on Windows using taskkill', async () => {
|
|
378
|
-
const mockExecSync = execSync as unknown as ReturnType<typeof mock>
|
|
379
|
-
const killedProcesses: string[] = []
|
|
380
|
-
|
|
381
|
-
mockExecSync.mockImplementation((cmd: string) => {
|
|
382
|
-
if (cmd.includes('taskkill')) {
|
|
383
|
-
const match = cmd.match(/taskkill \/F \/IM "([^"]+)"/)
|
|
384
|
-
if (match) killedProcesses.push(match[1])
|
|
385
|
-
}
|
|
386
|
-
return ''
|
|
387
|
-
})
|
|
388
247
|
|
|
389
|
-
|
|
390
|
-
await winExtractor.killDiscord('stable')
|
|
391
|
-
|
|
392
|
-
expect(killedProcesses).toContain('Discord.exe')
|
|
248
|
+
killProcessSpy.mockRestore()
|
|
393
249
|
})
|
|
394
250
|
|
|
395
251
|
test('kills all variants when no specific variant provided', async () => {
|
|
396
|
-
const
|
|
252
|
+
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
397
253
|
const killedProcesses: string[] = []
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const match = cmd.match(/pkill -f "([^"]+)"/)
|
|
402
|
-
if (match) killedProcesses.push(match[1])
|
|
254
|
+
const killProcessSpy = spyOn(darwinExtractor as any, 'killProcess').mockImplementation(
|
|
255
|
+
(name: string) => {
|
|
256
|
+
killedProcesses.push(name)
|
|
403
257
|
}
|
|
404
|
-
|
|
405
|
-
})
|
|
258
|
+
)
|
|
406
259
|
|
|
407
|
-
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
408
260
|
await darwinExtractor.killDiscord()
|
|
409
261
|
|
|
410
262
|
expect(killedProcesses).toContain('Discord')
|
|
411
263
|
expect(killedProcesses).toContain('Discord Canary')
|
|
412
264
|
expect(killedProcesses).toContain('Discord PTB')
|
|
265
|
+
|
|
266
|
+
killProcessSpy.mockRestore()
|
|
413
267
|
})
|
|
414
268
|
})
|
|
415
269
|
|
|
416
270
|
describe('launchDiscordWithDebug', () => {
|
|
417
271
|
test('throws error when Discord app not found', async () => {
|
|
418
|
-
const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
|
|
419
|
-
mockExistsSync.mockImplementation(() => false)
|
|
420
|
-
|
|
421
272
|
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
273
|
+
const getAppPathSpy = spyOn(darwinExtractor as any, 'getAppPath').mockReturnValue(
|
|
274
|
+
'/nonexistent/path'
|
|
275
|
+
)
|
|
422
276
|
|
|
423
277
|
await expect(darwinExtractor.launchDiscordWithDebug('stable')).rejects.toThrow(
|
|
424
278
|
'Discord stable not found'
|
|
425
279
|
)
|
|
426
|
-
})
|
|
427
|
-
|
|
428
|
-
test('launches Discord with remote debugging port on macOS', async () => {
|
|
429
|
-
const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
|
|
430
|
-
mockExistsSync.mockImplementation((path: string) => {
|
|
431
|
-
return path.includes('/Applications/Discord.app')
|
|
432
|
-
})
|
|
433
|
-
|
|
434
|
-
const mockExecSync = execSync as unknown as ReturnType<typeof mock>
|
|
435
|
-
mockExecSync.mockImplementation(() => '')
|
|
436
|
-
|
|
437
|
-
let spawnedPath = ''
|
|
438
|
-
let spawnedArgs: string[] = []
|
|
439
|
-
const mockSpawnFn = spawn as unknown as ReturnType<typeof mock>
|
|
440
|
-
mockSpawnFn.mockImplementation((path: string, args: string[]) => {
|
|
441
|
-
spawnedPath = path
|
|
442
|
-
spawnedArgs = args
|
|
443
|
-
return { unref: () => {} }
|
|
444
|
-
})
|
|
445
|
-
|
|
446
|
-
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
447
|
-
await darwinExtractor.launchDiscordWithDebug('stable', 9222)
|
|
448
|
-
|
|
449
|
-
expect(spawnedPath).toBe('/Applications/Discord.app/Contents/MacOS/Discord')
|
|
450
|
-
expect(spawnedArgs).toContain('--remote-debugging-port=9222')
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
test('uses default CDP port when not specified', async () => {
|
|
454
|
-
const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
|
|
455
|
-
mockExistsSync.mockImplementation(() => true)
|
|
456
|
-
|
|
457
|
-
const mockExecSync = execSync as unknown as ReturnType<typeof mock>
|
|
458
|
-
mockExecSync.mockImplementation(() => '')
|
|
459
|
-
|
|
460
|
-
let spawnedArgs: string[] = []
|
|
461
|
-
const mockSpawnFn = spawn as unknown as ReturnType<typeof mock>
|
|
462
|
-
mockSpawnFn.mockImplementation((_path: string, args: string[]) => {
|
|
463
|
-
spawnedArgs = args
|
|
464
|
-
return { unref: () => {} }
|
|
465
|
-
})
|
|
466
|
-
|
|
467
|
-
const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
|
|
468
|
-
await darwinExtractor.launchDiscordWithDebug('stable')
|
|
469
280
|
|
|
470
|
-
|
|
281
|
+
getAppPathSpy.mockRestore()
|
|
471
282
|
})
|
|
472
283
|
})
|
|
473
284
|
})
|
|
@@ -475,18 +286,13 @@ describe('DiscordTokenExtractor', () => {
|
|
|
475
286
|
describe('CDP client methods', () => {
|
|
476
287
|
describe('discoverCDPTargets', () => {
|
|
477
288
|
test('returns empty array when CDP endpoint is not reachable', async () => {
|
|
478
|
-
const originalFetch = globalThis.fetch
|
|
479
289
|
globalThis.fetch = mock(async () => {
|
|
480
290
|
throw new Error('Connection refused')
|
|
481
291
|
}) as unknown as typeof fetch
|
|
482
292
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
expect(targets).toEqual([])
|
|
487
|
-
} finally {
|
|
488
|
-
globalThis.fetch = originalFetch
|
|
489
|
-
}
|
|
293
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
294
|
+
const targets = await extractor.discoverCDPTargets(19999)
|
|
295
|
+
expect(targets).toEqual([])
|
|
490
296
|
})
|
|
491
297
|
|
|
492
298
|
test('returns targets from CDP endpoint', async () => {
|
|
@@ -500,35 +306,25 @@ describe('DiscordTokenExtractor', () => {
|
|
|
500
306
|
},
|
|
501
307
|
]
|
|
502
308
|
|
|
503
|
-
const originalFetch = globalThis.fetch
|
|
504
309
|
globalThis.fetch = mock(async () => ({
|
|
505
310
|
ok: true,
|
|
506
311
|
json: async () => mockTargets,
|
|
507
312
|
})) as unknown as typeof fetch
|
|
508
313
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
expect(targets).toEqual(mockTargets)
|
|
513
|
-
} finally {
|
|
514
|
-
globalThis.fetch = originalFetch
|
|
515
|
-
}
|
|
314
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
315
|
+
const targets = await extractor.discoverCDPTargets(9222)
|
|
316
|
+
expect(targets).toEqual(mockTargets)
|
|
516
317
|
})
|
|
517
318
|
|
|
518
319
|
test('returns empty array on HTTP error', async () => {
|
|
519
|
-
const originalFetch = globalThis.fetch
|
|
520
320
|
globalThis.fetch = mock(async () => ({
|
|
521
321
|
ok: false,
|
|
522
322
|
status: 500,
|
|
523
323
|
})) as unknown as typeof fetch
|
|
524
324
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
expect(targets).toEqual([])
|
|
529
|
-
} finally {
|
|
530
|
-
globalThis.fetch = originalFetch
|
|
531
|
-
}
|
|
325
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
326
|
+
const targets = await extractor.discoverCDPTargets(9222)
|
|
327
|
+
expect(targets).toEqual([])
|
|
532
328
|
})
|
|
533
329
|
})
|
|
534
330
|
|
|
@@ -630,19 +426,14 @@ describe('DiscordTokenExtractor', () => {
|
|
|
630
426
|
close() {}
|
|
631
427
|
}
|
|
632
428
|
|
|
633
|
-
const originalWebSocket = globalThis.WebSocket
|
|
634
429
|
globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
|
|
635
430
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
expect(result).toBe(mockToken)
|
|
643
|
-
} finally {
|
|
644
|
-
globalThis.WebSocket = originalWebSocket
|
|
645
|
-
}
|
|
431
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
432
|
+
const result = await extractor.executeJSViaCDP(
|
|
433
|
+
'ws://localhost:9222/devtools/page/1',
|
|
434
|
+
TOKEN_EXTRACTION_JS
|
|
435
|
+
)
|
|
436
|
+
expect(result).toBe(mockToken)
|
|
646
437
|
})
|
|
647
438
|
|
|
648
439
|
test('rejects on CDP error response', async () => {
|
|
@@ -672,17 +463,12 @@ describe('DiscordTokenExtractor', () => {
|
|
|
672
463
|
close() {}
|
|
673
464
|
}
|
|
674
465
|
|
|
675
|
-
const originalWebSocket = globalThis.WebSocket
|
|
676
466
|
globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
|
|
677
467
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
).rejects.toThrow('Evaluation failed')
|
|
683
|
-
} finally {
|
|
684
|
-
globalThis.WebSocket = originalWebSocket
|
|
685
|
-
}
|
|
468
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
469
|
+
await expect(
|
|
470
|
+
extractor.executeJSViaCDP('ws://localhost:9222/devtools/page/1', TOKEN_EXTRACTION_JS)
|
|
471
|
+
).rejects.toThrow('Evaluation failed')
|
|
686
472
|
})
|
|
687
473
|
|
|
688
474
|
test('rejects on WebSocket error', async () => {
|
|
@@ -701,39 +487,28 @@ describe('DiscordTokenExtractor', () => {
|
|
|
701
487
|
close() {}
|
|
702
488
|
}
|
|
703
489
|
|
|
704
|
-
const originalWebSocket = globalThis.WebSocket
|
|
705
490
|
globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
|
|
706
491
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
).rejects.toThrow()
|
|
712
|
-
} finally {
|
|
713
|
-
globalThis.WebSocket = originalWebSocket
|
|
714
|
-
}
|
|
492
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
493
|
+
await expect(
|
|
494
|
+
extractor.executeJSViaCDP('ws://localhost:9222/devtools/page/1', TOKEN_EXTRACTION_JS)
|
|
495
|
+
).rejects.toThrow()
|
|
715
496
|
})
|
|
716
497
|
})
|
|
717
498
|
|
|
718
499
|
describe('extractViaCDP', () => {
|
|
719
500
|
test('returns null when no CDP targets available', async () => {
|
|
720
|
-
const originalFetch = globalThis.fetch
|
|
721
501
|
globalThis.fetch = mock(async () => ({
|
|
722
502
|
ok: true,
|
|
723
503
|
json: async () => [],
|
|
724
504
|
})) as unknown as typeof fetch
|
|
725
505
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
expect(result).toBeNull()
|
|
730
|
-
} finally {
|
|
731
|
-
globalThis.fetch = originalFetch
|
|
732
|
-
}
|
|
506
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
507
|
+
const result = await extractor.extractViaCDP(9222)
|
|
508
|
+
expect(result).toBeNull()
|
|
733
509
|
})
|
|
734
510
|
|
|
735
511
|
test('returns null when no Discord page target found', async () => {
|
|
736
|
-
const originalFetch = globalThis.fetch
|
|
737
512
|
globalThis.fetch = mock(async () => ({
|
|
738
513
|
ok: true,
|
|
739
514
|
json: async () => [
|
|
@@ -747,19 +522,14 @@ describe('DiscordTokenExtractor', () => {
|
|
|
747
522
|
],
|
|
748
523
|
})) as unknown as typeof fetch
|
|
749
524
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
expect(result).toBeNull()
|
|
754
|
-
} finally {
|
|
755
|
-
globalThis.fetch = originalFetch
|
|
756
|
-
}
|
|
525
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
526
|
+
const result = await extractor.extractViaCDP(9222)
|
|
527
|
+
expect(result).toBeNull()
|
|
757
528
|
})
|
|
758
529
|
|
|
759
530
|
test('extracts token via CDP when Discord is running with debug port', async () => {
|
|
760
|
-
const mockToken = '
|
|
531
|
+
const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.ZZZZZZZZZZZZZZZZZZZZZZZZZ'
|
|
761
532
|
|
|
762
|
-
const originalFetch = globalThis.fetch
|
|
763
533
|
globalThis.fetch = mock(async () => ({
|
|
764
534
|
ok: true,
|
|
765
535
|
json: async () => [
|
|
@@ -797,21 +567,14 @@ describe('DiscordTokenExtractor', () => {
|
|
|
797
567
|
close() {}
|
|
798
568
|
}
|
|
799
569
|
|
|
800
|
-
const originalWebSocket = globalThis.WebSocket
|
|
801
570
|
globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
|
|
802
571
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
expect(result).toBe(mockToken)
|
|
807
|
-
} finally {
|
|
808
|
-
globalThis.fetch = originalFetch
|
|
809
|
-
globalThis.WebSocket = originalWebSocket
|
|
810
|
-
}
|
|
572
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
573
|
+
const result = await extractor.extractViaCDP(9222)
|
|
574
|
+
expect(result).toBe(mockToken)
|
|
811
575
|
})
|
|
812
576
|
|
|
813
577
|
test('returns null when token extraction JS fails', async () => {
|
|
814
|
-
const originalFetch = globalThis.fetch
|
|
815
578
|
globalThis.fetch = mock(async () => ({
|
|
816
579
|
ok: true,
|
|
817
580
|
json: async () => [
|
|
@@ -849,21 +612,14 @@ describe('DiscordTokenExtractor', () => {
|
|
|
849
612
|
close() {}
|
|
850
613
|
}
|
|
851
614
|
|
|
852
|
-
const originalWebSocket = globalThis.WebSocket
|
|
853
615
|
globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
|
|
854
616
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
expect(result).toBeNull()
|
|
859
|
-
} finally {
|
|
860
|
-
globalThis.fetch = originalFetch
|
|
861
|
-
globalThis.WebSocket = originalWebSocket
|
|
862
|
-
}
|
|
617
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
618
|
+
const result = await extractor.extractViaCDP(9222)
|
|
619
|
+
expect(result).toBeNull()
|
|
863
620
|
})
|
|
864
621
|
|
|
865
622
|
test('returns null when returned value is not a valid token', async () => {
|
|
866
|
-
const originalFetch = globalThis.fetch
|
|
867
623
|
globalThis.fetch = mock(async () => ({
|
|
868
624
|
ok: true,
|
|
869
625
|
json: async () => [
|
|
@@ -901,17 +657,11 @@ describe('DiscordTokenExtractor', () => {
|
|
|
901
657
|
close() {}
|
|
902
658
|
}
|
|
903
659
|
|
|
904
|
-
const originalWebSocket = globalThis.WebSocket
|
|
905
660
|
globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
|
|
906
661
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
expect(result).toBeNull()
|
|
911
|
-
} finally {
|
|
912
|
-
globalThis.fetch = originalFetch
|
|
913
|
-
globalThis.WebSocket = originalWebSocket
|
|
914
|
-
}
|
|
662
|
+
const extractor = new DiscordTokenExtractor('darwin')
|
|
663
|
+
const result = await extractor.extractViaCDP(9222)
|
|
664
|
+
expect(result).toBeNull()
|
|
915
665
|
})
|
|
916
666
|
})
|
|
917
667
|
})
|