diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..9625450 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +TESTING_VALORANT_REGION=# "na" | "eu" | "latam" | "br" | "ap" | "kr" | "pbe"; \ No newline at end of file diff --git a/.github/workflows/update-types.yml b/.github/workflows/update-types.yml index fdafde9..3047025 100644 --- a/.github/workflows/update-types.yml +++ b/.github/workflows/update-types.yml @@ -13,6 +13,7 @@ jobs: - name: Cache node modules uses: actions/cache@v2 + id: cache-node-modules env: cache-name: cache-node-modules with: diff --git a/.husky/pre-push b/.husky/pre-push index 2481fb0..ab99c37 100644 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -yarn test --coverage && npx istanbul-badges-readme && git add 'README.md' +yarn test:unit --coverage && npx istanbul-badges-readme && git add 'README.md' diff --git a/__tests__/__setup__/integration.ts b/__tests__/__setup__/integration.ts new file mode 100644 index 0000000..eefbe40 --- /dev/null +++ b/__tests__/__setup__/integration.ts @@ -0,0 +1,11 @@ +import { ValClient } from "@app/client"; + +import type { Regions } from "@type/resources"; + +export const client = new ValClient(); + +beforeAll(async () => { + if (!client.auth || !client.endpoints.local) { + await client.init({ region: process.env.TESTING_VALORANT_REGION as Regions }); + } +}); diff --git a/__tests__/__setup__/jest-extended.ts b/__tests__/__setup__/jest-extended.ts new file mode 100644 index 0000000..9f41aba --- /dev/null +++ b/__tests__/__setup__/jest-extended.ts @@ -0,0 +1,2 @@ +import "jest-extended"; +import "jest-extended/all"; diff --git a/__tests__/integration/valorant.test.ts b/__tests__/integration/valorant.test.ts new file mode 100644 index 0000000..b6cbdea --- /dev/null +++ b/__tests__/integration/valorant.test.ts @@ -0,0 +1,57 @@ +import { client } from "@tests/__setup__/integration"; + +describe("Process", () => { + test("when valorant is not open, launcher is open and logged should return empty object", async () => { + const spy = jest.spyOn(client.valorant, "process"); + const data = await client.valorant.process(); + expect(spy).toHaveBeenCalled(); + expect(data).toMatchObject({}); + + spy.mockRestore(); + }); + + test("should return info about valorant process running", async () => { + const data = await client.valorant.process(); + + const process = Object.keys(data)[0]; + + expect(data[process]).toContainAllKeys([ + "exitCode", + "exitReason", + "isInternal", + "launchConfiguration", + "patchlineFullName", + "patchlineId", + "phase", + "productId", + "version", + ]); + + expect(data[process]["launchConfiguration"]).toContainAllKeys([ + "arguments", + "executable", + "locale", + "voiceLocale", + "workingDirectory", + ]); + }); +}); + +test("should return client settings", async () => { + const settings = await client.valorant.clientSettings(); + + expect(settings).toContainAllKeys(["data", "modified", "type"]); + + expect(settings.type).toEqual("Ares.PlayerSettings"); + + expect(settings.data).toContainAllKeys([ + "actionMappings", + "axisMappings", + "boolSettings", + "floatSettings", + "intSettings", + "roamingSetttingsVersion", + "stringSettings", + "settingsProfiles", + ]); +}); diff --git a/__tests__/unit/chat.test.ts b/__tests__/unit/chat.test.ts new file mode 100644 index 0000000..269543f --- /dev/null +++ b/__tests__/unit/chat.test.ts @@ -0,0 +1,226 @@ +import { Chat } from "@app/chat"; +import { mock } from "jest-mock-extended"; + +import { IHttp } from "@interfaces/http"; +import { ChatInfoResponse, MessageResponse, ParticipantsResponse } from "@interfaces/chat"; + +const mockedHttpService = mock(); + +const chat = new Chat(mockedHttpService); + +const cid = "someid@server"; +const friend_pid = "friend@server"; + +const mockedPartyChatResponse: ChatInfoResponse = { + conversations: [ + { + cid: "someid@server", + direct_messages: true, + global_readership: false, + message_history: false, + mid: "mid", + muted: false, + mutedRestriction: false, + type: "groupchat", + uiState: { + changedSinceHidden: false, + hidden: false, + }, + unread_count: 0, + }, + ], +}; + +const mockedPreGameChatResponse: ChatInfoResponse = { + conversations: mockedPartyChatResponse.conversations.map((chat) => ({ ...chat, cid: "someid-1@server" })), +}; + +const mockedLiveGameChatResponse: ChatInfoResponse = { + conversations: [ + ...mockedPartyChatResponse.conversations.map((chat) => ({ ...chat, cid: "someid-blue@server" })), + { ...mockedPartyChatResponse.conversations[0], cid: "someid-red@server" }, + ], +}; + +const mockedAllGameChatResponse: ChatInfoResponse = { + conversations: [ + ...mockedPreGameChatResponse.conversations, + ...mockedLiveGameChatResponse.conversations, + { ...mockedLiveGameChatResponse.conversations[0], cid: "someid-all@server" }, + ], +}; + +const mockedParticipantsResponse: ParticipantsResponse = { + participants: [ + { + cid: "someid@server", + game_name: "test", + game_tag: "test", + muted: false, + name: "test", + pid: "test", + puuid: "test", + region: "test", + }, + ], +}; + +const mockedMessagesResponse: MessageResponse = { + messages: [ + { + body: "eae", + cid: "someid@server", + game_name: "iws", + game_tag: "777", + id: "test", + mid: "test", + name: "test", + pid: "test", + puuid: "test", + read: true, + region: "test", + time: "test", + type: "groupchat", + }, + ], +}; + +afterEach(() => { + mockedHttpService.fetch.mockClear(); +}); + +test("should return current info about party chat", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedPartyChatResponse); + + const data = await chat.getPartyChat(); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith("/chat/v6/conversations/ares-parties", "local"); + + expect(data).toEqual(mockedPartyChatResponse); +}); + +test("should return current info about pregame chat", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedPreGameChatResponse); + + const data = await chat.getPreGameChat(); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith("/chat/v6/conversations/ares-pregame", "local"); + + expect(data).toEqual(mockedPreGameChatResponse); +}); + +test("should return current info about livegame chat", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedLiveGameChatResponse); + + const data = await chat.getLiveGameChat(); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith("/chat/v6/conversations/ares-coregame", "local"); + + expect(data).toEqual(mockedLiveGameChatResponse); +}); + +test("should return current info about all chats", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedAllGameChatResponse); + + const data = await chat.getAllChat(); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith("/chat/v6/conversations/", "local"); + + expect(data).toEqual(mockedAllGameChatResponse); +}); + +test("should return participants in specific chat", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedParticipantsResponse); + + const data = await chat.getParticipants(cid); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith(`/chat/v5/participants/?cid=${cid}`, "local"); + + expect(data).toEqual(mockedParticipantsResponse); +}); + +test("should return all participants in all active chats", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedParticipantsResponse); + + const data = await chat.getAllParticipants(); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith(`/chat/v5/participants/`, "local"); + + expect(data).toEqual(mockedParticipantsResponse); +}); + +test("should return history from all active chats", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedMessagesResponse); + + const data = await chat.getAllHistory(); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith("/chat/v6/messages", "local"); + + expect(data).toEqual(mockedMessagesResponse); +}); + +test("should return history from specific chat", async () => { + mockedHttpService.fetch.mockResolvedValueOnce(mockedMessagesResponse); + + const data = await chat.getHistory(cid); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith(`/chat/v6/messages?cid=${cid}`, "local"); + + expect(data).toEqual(mockedMessagesResponse); +}); + +test("should send whisper to friend", async () => { + const mockedFriendWhisper = { + messages: [{ ...mockedMessagesResponse.messages[0], cid: friend_pid }], + }; + const message = "eae"; + + mockedHttpService.post.mockResolvedValueOnce(mockedFriendWhisper); + + const data = await chat.sendWhisper(friend_pid, message); + + expect(mockedHttpService.post).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.post).toHaveBeenCalledWith("/chat/v6/messages/", "local", { + cid: friend_pid, + message, + type: "chat", + }); + + expect(data).toEqual(mockedFriendWhisper); +}); + +test("should send message to any chat", async () => { + mockedHttpService.post.mockClear(); + mockedHttpService.post.mockResolvedValueOnce(mockedMessagesResponse); + + const message = "eae"; + + const data = await chat.sendMessage(cid, message); + + expect(mockedHttpService.post).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.post).toHaveBeenCalledWith("/chat/v6/messages/", "local", { + cid, + message, + type: "groupchat", + }); + + expect(data).toEqual(mockedMessagesResponse); +}); diff --git a/__tests__/client.test.ts b/__tests__/unit/client.test.ts similarity index 100% rename from __tests__/client.test.ts rename to __tests__/unit/client.test.ts diff --git a/__tests__/contracts.test.ts b/__tests__/unit/contracts.test.ts similarity index 100% rename from __tests__/contracts.test.ts rename to __tests__/unit/contracts.test.ts diff --git a/__tests__/group.test.ts b/__tests__/unit/group.test.ts similarity index 100% rename from __tests__/group.test.ts rename to __tests__/unit/group.test.ts diff --git a/__tests__/http.test.ts b/__tests__/unit/http.test.ts similarity index 100% rename from __tests__/http.test.ts rename to __tests__/unit/http.test.ts diff --git a/__tests__/liveGame.test.ts b/__tests__/unit/liveGame.test.ts similarity index 100% rename from __tests__/liveGame.test.ts rename to __tests__/unit/liveGame.test.ts diff --git a/__tests__/loadout.test.ts b/__tests__/unit/loadout.test.ts similarity index 100% rename from __tests__/loadout.test.ts rename to __tests__/unit/loadout.test.ts diff --git a/__tests__/player.test.ts b/__tests__/unit/player.test.ts similarity index 100% rename from __tests__/player.test.ts rename to __tests__/unit/player.test.ts diff --git a/__tests__/preGame.test.ts b/__tests__/unit/preGame.test.ts similarity index 100% rename from __tests__/preGame.test.ts rename to __tests__/unit/preGame.test.ts diff --git a/__tests__/pvp.test.ts b/__tests__/unit/pvp.test.ts similarity index 95% rename from __tests__/pvp.test.ts rename to __tests__/unit/pvp.test.ts index 56a3d7a..939a07f 100644 --- a/__tests__/pvp.test.ts +++ b/__tests__/unit/pvp.test.ts @@ -165,110 +165,36 @@ const mockedPvpMmr: PvpMMR = { }; const mockedContents: PvpContents = { - Attachments: [ - { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", - }, - ], - Characters: [ - { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", - }, - ], - CharmLevels: [ - { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", - }, - ], - Charms: [ - { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", - }, - ], - Chromas: [ - { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", - }, - ], - CompetitiveSeasons: [ + DisabledIDs: [], + Seasons: [ { + ID: "0df5adb9-4dcb-6899-1306-3e9860661dd3", + Name: "Closed Beta", + Type: "episode", + StartTime: "2020-04-07T05:15:00Z", + EndTime: "2020-05-29T20:14:00Z", + IsActive: false, DevelopmentOnly: false, - EndTime: "timestamp", - ID: "id", - SeasonID: "season", - StartTime: "timestamp", - }, - ], - Equips: [ - { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", }, ], Events: [ { + ID: "3bd00051-4518-411d-046d-a7a554850267", + Name: "YR1 ANNIVERSARY PASS", + StartTime: "2021-06-22T12:00:00Z", + EndTime: "2021-07-07T07:59:59Z", + IsActive: false, DevelopmentOnly: false, - EndTime: "timestamp", - ID: "id", - IsActive: true, - IsEnabled: true, - Name: "teste", - StartTime: "timestamp", - }, - ], - GameModes: [ - { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", }, - ], - Maps: [ { - AssetName: "test", - ID: "test", - IsEnabled: true, - Name: "teste", - }, - ], - PlayerCards: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], - PlayerTitles: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], - Seasons: [ - { - Name: "test", - IsEnabled: true, - IsActive: true, - StartTime: "timestamp", - ID: "test", - EndTime: "timestamp", + ID: "cee09894-41d6-7000-848b-ea9de6c28f44", + Name: "RiotX Arcane Pass", + StartTime: "2021-11-05T21:00:00Z", + EndTime: "2021-11-22T22:00:00Z", + IsActive: false, DevelopmentOnly: false, - Type: "type", }, ], - SkinLevels: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], - Skins: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], - SprayLevels: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], - Sprays: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], - StorefrontItems: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], - Themes: [{ AssetName: "test", ID: "test", IsEnabled: true, Name: "teste" }], }; const mockedAccountXP: PvpAccountXp = { @@ -1206,14 +1132,14 @@ test("should return mmr info about current user authenticated", async () => { expect(data).toEqual(mockedPvpMmr); }); -test("should return all game contents such as maps, agents, etc...", async () => { +test("should return pvp game content (battlepass, act, events)", async () => { mockedHttpService.fetch.mockResolvedValueOnce(mockedContents); const data = await pvp.contents(); expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); - expect(mockedHttpService.fetch).toHaveBeenCalledWith(`/content-service/v2/content`, "shared"); + expect(mockedHttpService.fetch).toHaveBeenCalledWith(`/content-service/v3/content`, "shared"); expect(data).toEqual(mockedContents); }); diff --git a/__tests__/session.test.ts b/__tests__/unit/session.test.ts similarity index 100% rename from __tests__/session.test.ts rename to __tests__/unit/session.test.ts diff --git a/__tests__/store.test.ts b/__tests__/unit/store.test.ts similarity index 100% rename from __tests__/store.test.ts rename to __tests__/unit/store.test.ts diff --git a/__tests__/utils.test.ts b/__tests__/unit/utils.test.ts similarity index 100% rename from __tests__/utils.test.ts rename to __tests__/unit/utils.test.ts diff --git a/__tests__/valorant.test.ts b/__tests__/unit/valorant.test.ts similarity index 88% rename from __tests__/valorant.test.ts rename to __tests__/unit/valorant.test.ts index d924389..77f38cf 100644 --- a/__tests__/valorant.test.ts +++ b/__tests__/unit/valorant.test.ts @@ -40,10 +40,17 @@ const mockedClientSettings: ClientSettingsResponse = { shift: true, }, ], + settingsProfiles: [], axisMapping: [], - floatSettings: [{ settingEnum: "float_setting", value: 5 }], - intSettings: [{ settingEnum: "int_setting", value: 1 }], + floatSettings: [{ settingEnum: "EAresFloatSettingName::MouseSensitivity", value: 5 }], + intSettings: [{ settingEnum: "EAresIntSettingName::VoiceVolume", value: 1 }], roamingSetttingsVersion: 0, + boolSettings: [ + { + settingEnum: "EAresBoolSettingName::CollectionShowOwnedOnly", + value: true, + }, + ], stringSettings: [ { settingEnum: "EAresStringSettingName::SavedCrosshairProfileData", @@ -240,3 +247,41 @@ test("should return crosshair profiles", async () => { expect(data).toEqual(mockedCrossHairProfiles); }); + +test("should update client settings", async () => { + const resolvedValue = { + data: "format", + type: "Ares.PlayerSettings", + modified: 1642758359892, + }; + + mockedHttpService.fetch.mockResolvedValueOnce(mockedClientSettings); + mockedHttpService.put.mockResolvedValueOnce(resolvedValue); + + const { data: actualSettings } = await valorant.clientSettings(); + + expect(mockedHttpService.fetch).toHaveBeenCalledTimes(1); + + expect(mockedHttpService.fetch).toHaveBeenCalledWith( + "/player-preferences/v1/data-json/Ares.PlayerSettings", + "local", + ); + + const newSettings = { + ...actualSettings, + floatSettings: actualSettings.floatSettings.map((setting) => + setting.settingEnum.includes("MouseSensitivity") ? { ...setting, value: 0.5 } : setting, + ), + }; + + const data = await valorant.changeSettings(newSettings); + + expect(mockedHttpService.put).toHaveBeenCalledTimes(1); + expect(mockedHttpService.put).toHaveBeenCalledWith( + "/player-preferences/v1/data-json/Ares.PlayerSettings", + "local", + newSettings, + ); + + expect(data).toEqual(resolvedValue); +}); diff --git a/docs/Chat/getAllChat.md b/docs/Chat/getAllChat.md new file mode 100644 index 0000000..d5d8b02 --- /dev/null +++ b/docs/Chat/getAllChat.md @@ -0,0 +1,30 @@ +# Get All Chat + +Get information about all active conversations (party, pregame and livegame) + +```js +const allChat = await client.chat.getAllChat(); +``` + +Returns + +```ts +export type ChatTypes = "chat" | "groupchat"; + +export interface ChatInfo { + cid: string; + direct_messages: boolean; + global_readership: boolean; + message_history: boolean; + mid: string; + muted: boolean; + mutedRestriction: boolean; + type: ChatTypes; + uiState: { changedSinceHidden: boolean; hidden: boolean }; + unread_count: number; +} + +export interface ChatInfoResponse { + conversations: ChatInfo[]; +} +``` diff --git a/docs/Chat/getAllHistory.md b/docs/Chat/getAllHistory.md new file mode 100644 index 0000000..d05e912 --- /dev/null +++ b/docs/Chat/getAllHistory.md @@ -0,0 +1,31 @@ +# Get All Chats History + +Get history for all active chats (party, pregame, livegame and whisper) + +```js +const allHistory = await client.chat.getAllHistory(); +``` + +Returns + +```ts +export interface MessageInfo { + body: string; + cid: string; + game_name: string; + game_tag: string; + id: string; + mid: string; + name: string; + pid: string; + puuid: string; + read: boolean; + region: string; + time: string; + type: string; +} + +export interface MessageResponse { + messages: MessageInfo[]; +} +``` diff --git a/docs/Chat/getAllParticipants.md b/docs/Chat/getAllParticipants.md new file mode 100644 index 0000000..6cf5999 --- /dev/null +++ b/docs/Chat/getAllParticipants.md @@ -0,0 +1,26 @@ +# Get All Participants + +Get information about the participants for all active chats. + +```js +const participants = await client.chat.getAllParticipants(); +``` + +Returns + +```ts +export interface ParticipantInfo { + cid: string; + game_name: string; + game_tag: string; + muted: boolean; + name: string; + pid: string; + puuid: string; + region: string; +} + +export interface ParticipantsResponse { + participants: ParticipantInfo[]; +} +``` diff --git a/docs/Chat/getHistory.md b/docs/Chat/getHistory.md new file mode 100644 index 0000000..dedfec3 --- /dev/null +++ b/docs/Chat/getHistory.md @@ -0,0 +1,39 @@ +# Get Chat History + +Get history for specificy chat. +You can use getPreGameChat, getLiveGameChat, getAllChat and getPartyChat to get CID for each chat. + +```js +const { conversations } = await client.chat.getLiveGameChat(); +const history = await client.chat.getHistory(conversations[0].cid); +``` + +Parameter + +``` +cid: string +``` + +Returns + +```ts +export interface MessageInfo { + body: string; + cid: string; + game_name: string; + game_tag: string; + id: string; + mid: string; + name: string; + pid: string; + puuid: string; + read: boolean; + region: string; + time: string; + type: string; +} + +export interface MessageResponse { + messages: MessageInfo[]; +} +``` diff --git a/docs/Chat/getLiveGameChat.md b/docs/Chat/getLiveGameChat.md new file mode 100644 index 0000000..ea2f43e --- /dev/null +++ b/docs/Chat/getLiveGameChat.md @@ -0,0 +1,30 @@ +# Get Live Game Chat + +Get information about the live game chat + +```js +const liveGameChat = await client.chat.getLiveGameChat(); +``` + +Returns + +```ts +export type ChatTypes = "chat" | "groupchat"; + +export interface ChatInfo { + cid: string; + direct_messages: boolean; + global_readership: boolean; + message_history: boolean; + mid: string; + muted: boolean; + mutedRestriction: boolean; + type: ChatTypes; + uiState: { changedSinceHidden: boolean; hidden: boolean }; + unread_count: number; +} + +export interface ChatInfoResponse { + conversations: ChatInfo[]; +} +``` diff --git a/docs/Chat/getParticipants.md b/docs/Chat/getParticipants.md new file mode 100644 index 0000000..3ef69f4 --- /dev/null +++ b/docs/Chat/getParticipants.md @@ -0,0 +1,34 @@ +# Get Participants + +Get information about the participants for specificy chat. +You can get CID parameter with getPreGameChat, getLiveGameChat, getAllChat and getPartyChat. + +```js +const { conversations } = await client.chat.getLiveGameChat(); +const participants = await client.chat.getParticipants(conversations[0].cid); +``` + +Parameter + +``` +cid: string +``` + +Returns + +```ts +export interface ParticipantInfo { + cid: string; + game_name: string; + game_tag: string; + muted: boolean; + name: string; + pid: string; + puuid: string; + region: string; +} + +export interface ParticipantsResponse { + participants: ParticipantInfo[]; +} +``` diff --git a/docs/Chat/getPartyChat.md b/docs/Chat/getPartyChat.md new file mode 100644 index 0000000..4f3e052 --- /dev/null +++ b/docs/Chat/getPartyChat.md @@ -0,0 +1,30 @@ +# Get Party Chat + +Get information about the party chat + +```js +const partyChat = await client.chat.getPartyChat(); +``` + +Returns + +```ts +export type ChatTypes = "chat" | "groupchat"; + +export interface ChatInfo { + cid: string; + direct_messages: boolean; + global_readership: boolean; + message_history: boolean; + mid: string; + muted: boolean; + mutedRestriction: boolean; + type: ChatTypes; + uiState: { changedSinceHidden: boolean; hidden: boolean }; + unread_count: number; +} + +export interface ChatInfoResponse { + conversations: ChatInfo[]; +} +``` diff --git a/docs/Chat/getPreGameChat.md b/docs/Chat/getPreGameChat.md new file mode 100644 index 0000000..1b657cf --- /dev/null +++ b/docs/Chat/getPreGameChat.md @@ -0,0 +1,30 @@ +# Get Pregame Chat + +Get information about the pregame chat + +```js +const preGameChat = await client.chat.getPreGameChat(); +``` + +Returns + +```ts +export type ChatTypes = "chat" | "groupchat"; + +export interface ChatInfo { + cid: string; + direct_messages: boolean; + global_readership: boolean; + message_history: boolean; + mid: string; + muted: boolean; + mutedRestriction: boolean; + type: ChatTypes; + uiState: { changedSinceHidden: boolean; hidden: boolean }; + unread_count: number; +} + +export interface ChatInfoResponse { + conversations: ChatInfo[]; +} +``` diff --git a/docs/Chat/sendMessage.md b/docs/Chat/sendMessage.md new file mode 100644 index 0000000..65e5c39 --- /dev/null +++ b/docs/Chat/sendMessage.md @@ -0,0 +1,39 @@ +# Send Message + +Send a message to the specified chat. +You can get CID parameter with getPreGameChat, getLiveGameChat, getAllChat and getPartyChat. + +```js +const { conversations } = await client.chat.getAllChat(); +const message = await client.chat.sendMessage(conversations[0].cid, "hi!"); +``` + +Parameter + +```ts +cid: string; +``` + +Returns + +```ts +export interface MessageInfo { + body: string; + cid: string; + game_name: string; + game_tag: string; + id: string; + mid: string; + name: string; + pid: string; + puuid: string; + read: boolean; + region: string; + time: string; + type: string; +} + +export interface MessageResponse { + messages: MessageInfo[]; +} +``` diff --git a/docs/Chat/sendWhisper.md b/docs/Chat/sendWhisper.md new file mode 100644 index 0000000..d018ee6 --- /dev/null +++ b/docs/Chat/sendWhisper.md @@ -0,0 +1,39 @@ +# Send Whisper + +Send a whisper to the specified player. +You can get PID parameter with allFriends, allFriendsOnline and pendingFriendsRequests. + +```js +const allFriends = await client.player.allFriendsOnline(); +const whisper = await client.chat.sendWhisper(allFriends[0].pid, "hi!"); +``` + +Parameter + +```ts +pid: string; +``` + +Returns + +```ts +export interface MessageInfo { + body: string; + cid: string; + game_name: string; + game_tag: string; + id: string; + mid: string; + name: string; + pid: string; + puuid: string; + read: boolean; + region: string; + time: string; + type: string; +} + +export interface MessageResponse { + messages: MessageInfo[]; +} +``` diff --git a/docs/README.md b/docs/README.md index 46896b8..5609e3c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,73 +1,84 @@ # Docs -- Group - - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/current.md) - - [Current Available Game Modes](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/currentAvailableGameModes.md) - - [Current Details](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/currentDetails.md) - - [Change Queue](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/changeQueue.md) - - [Change State](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/changeState.md) - - [Request Join to Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/requestJoinToGroup.md) - - [Decline Request Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/declineRequestGroup.md) - - [Enter Matchmaking Queue](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/enterMatchmakingQueue.md) - - [Leave Matchmaking Queue](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/leaveMatchmakingQueue.md) - - [Invite by Display Name](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/inviteByDisplayName.md) - - [Join Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/joinGroup.md) - - [Leave Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/leaveGroup.md) - - [Remove Player](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/removePlayer.md) - - [Set Member Ready](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/setMemberReady.md) - - [Set Custom Game Settings](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/setCustomGameSettings.md) - - [Start Custom Game](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/startCustomGame.md) - - [Refresh Competitive Tier](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/refreshCompetitiveTier.md) - - [Refresh Player Identity](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/refreshPlayerIdentity.md) - - [Refresh Player Pings](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/refreshPlayerPings.md) -- Pvp - - [Account XP](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/accountXp.md) - - [Competitive Updates](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/competitiveUpdates.md) - - [Contents](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/contents.md) - - [Internal Config](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/internalConfig.md) - - [Item Progress Definitions](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/itemProgressDefinitions.md) - - [Leadersboards](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/leadersboards.md) - - [Match Details](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/matchDetails.md) - - [Match History](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/matchHistory.md) - - [MMR](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/mmr.md) - - [Player Restrictions](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/playerRestrictions.md) -- Player - - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/current.md) - - [All Friends](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/allFriends.md) - - [All Friends Online](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/allFriendsOnline.md) - - [Online Friend](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/onlineFriend.md) - - [Pending Friends Requests](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/pendingFriendsRequests.md) - - [Session](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/session.md) -- Loadout - - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/current.md) - - [Change Gun Skin](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/changeGunSkin.md) - - [Change Spray](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/changeSpray.md) - - [Add Skin Buddy](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/addSkinBuddy.md) -- LiveGame - - [Current Live-Game](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/current.md) - - [Details](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/details.md) - - [Loadout](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/loadout.md) - - [Disconnect](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/disconnect.md) -- PreGame - - [Current Pre-Game](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/current.md) - - [Details](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/details.md) - - [Loadout](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/loadout.md) - - [Lock Character](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/lockCharacter.md) - - [Select Character](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/selectCharacter.md) - - [Quit Match](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/quitMatch.md) -- Contracts - - [All](https://github.com/igorwessel/valclient.js/tree/master/docs/Contracts/all.md) - - [Activate](https://github.com/igorwessel/valclient.js/tree/master/docs/Contracts/activate.md) - - [Item Upgrades](https://github.com/igorwessel/valclient.js/tree/master/docs/Contracts/upgrades.md) -- Valorant - - [Client Settings](https://github.com/igorwessel/valclient.js/tree/master/docs/Valorant/clientSettings.md) - - [Crosshair](https://github.com/igorwessel/valclient.js/tree/master/docs/Valorant/crossHair.md) - - [Process](https://github.com/igorwessel/valclient.js/tree/master/docs/Valorant/process.md) -- Store - - [Your Items](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/yourItems.md) - - [Wallet](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/wallet.md) - - [Offers](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/offers.md) - - [Current Offers](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/currentOffers.md) -- Session - - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Session/current.md) - - [Reconnect](https://github.com/igorwessel/valclient.js/tree/master/docs/Session/reconnect.md) \ No newline at end of file +- Group + - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/current.md) + - [Current Available Game Modes](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/currentAvailableGameModes.md) + - [Current Details](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/currentDetails.md) + - [Change Queue](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/changeQueue.md) + - [Change State](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/changeState.md) + - [Request Join to Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/requestJoinToGroup.md) + - [Decline Request Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/declineRequestGroup.md) + - [Enter Matchmaking Queue](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/enterMatchmakingQueue.md) + - [Leave Matchmaking Queue](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/leaveMatchmakingQueue.md) + - [Invite by Display Name](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/inviteByDisplayName.md) + - [Join Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/joinGroup.md) + - [Leave Group](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/leaveGroup.md) + - [Remove Player](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/removePlayer.md) + - [Set Member Ready](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/setMemberReady.md) + - [Set Custom Game Settings](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/setCustomGameSettings.md) + - [Start Custom Game](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/startCustomGame.md) + - [Refresh Competitive Tier](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/refreshCompetitiveTier.md) + - [Refresh Player Identity](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/refreshPlayerIdentity.md) + - [Refresh Player Pings](https://github.com/igorwessel/valclient.js/tree/master/docs/Group/refreshPlayerPings.md) +- Pvp + - [Account XP](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/accountXp.md) + - [Competitive Updates](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/competitiveUpdates.md) + - [Contents](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/contents.md) + - [Internal Config](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/internalConfig.md) + - [Item Progress Definitions](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/itemProgressDefinitions.md) + - [Leadersboards](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/leadersboards.md) + - [Match Details](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/matchDetails.md) + - [Match History](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/matchHistory.md) + - [MMR](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/mmr.md) + - [Player Restrictions](https://github.com/igorwessel/valclient.js/tree/master/docs/Pvp/playerRestrictions.md) +- Player + - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/current.md) + - [All Friends](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/allFriends.md) + - [All Friends Online](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/allFriendsOnline.md) + - [Online Friend](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/onlineFriend.md) + - [Pending Friends Requests](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/pendingFriendsRequests.md) + - [Session](https://github.com/igorwessel/valclient.js/tree/master/docs/Player/session.md) +- Chat + - [Get Live](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getLiveGameChat.md) + - [Get Pre Game](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getPreGameChat.md) + - [Get Party](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getPartyChat.md) + - [Get All Chat](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getAllChat.md) + - [Get History](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getHistory.md) + - [Get All History](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getAllHistory.md) + - [Get Participants](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getParticipants.md) + - [Get All Participants](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/getAllParticipants.md) + - [Send Message](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/sendMessage.md) + - [Send Whisper](https://github.com/igorwessel/valclient.js/tree/master/docs/Chat/sendWhisper.md) +- Loadout + - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/current.md) + - [Change Gun Skin](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/changeGunSkin.md) + - [Change Spray](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/changeSpray.md) + - [Add Skin Buddy](https://github.com/igorwessel/valclient.js/tree/master/docs/Loadout/addSkinBuddy.md) +- LiveGame + - [Current Live-Game](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/current.md) + - [Details](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/details.md) + - [Loadout](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/loadout.md) + - [Disconnect](https://github.com/igorwessel/valclient.js/tree/master/docs/LiveGame/disconnect.md) +- PreGame + - [Current Pre-Game](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/current.md) + - [Details](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/details.md) + - [Loadout](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/loadout.md) + - [Lock Character](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/lockCharacter.md) + - [Select Character](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/selectCharacter.md) + - [Quit Match](https://github.com/igorwessel/valclient.js/tree/master/docs/PreGame/quitMatch.md) +- Contracts + - [All](https://github.com/igorwessel/valclient.js/tree/master/docs/Contracts/all.md) + - [Activate](https://github.com/igorwessel/valclient.js/tree/master/docs/Contracts/activate.md) + - [Item Upgrades](https://github.com/igorwessel/valclient.js/tree/master/docs/Contracts/upgrades.md) +- Valorant + - [Client Settings](https://github.com/igorwessel/valclient.js/tree/master/docs/Valorant/clientSettings.md) + - [Crosshair](https://github.com/igorwessel/valclient.js/tree/master/docs/Valorant/crossHair.md) + - [Process](https://github.com/igorwessel/valclient.js/tree/master/docs/Valorant/process.md) +- Store + - [Your Items](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/yourItems.md) + - [Wallet](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/wallet.md) + - [Offers](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/offers.md) + - [Current Offers](https://github.com/igorwessel/valclient.js/tree/master/docs/Store/currentOffers.md) +- Session + - [Current](https://github.com/igorwessel/valclient.js/tree/master/docs/Session/current.md) + - [Reconnect](https://github.com/igorwessel/valclient.js/tree/master/docs/Session/reconnect.md) diff --git a/docs/Valorant/changeSettings.md b/docs/Valorant/changeSettings.md new file mode 100644 index 0000000..83a4937 --- /dev/null +++ b/docs/Valorant/changeSettings.md @@ -0,0 +1,42 @@ +# Change client Settings + +Update client settings need to reopen game to see modifications. + +Example: + +```js +const actualSettings = await client.valorant.clientSettings(); + +const newSettings = { + ...actualSettings.data, + floatSettings: actualSettings.data.floatSettings.map((setting) => + setting.settingEnum.includes("MouseSensitivity") ? { ...setting, value: 0.5 } : setting, + ), +}; + +await client.valorant.changeSettings(newSettings); +``` + +Param + +```ts +export interface ClientSettings { + actionMappings: ActionMap[]; + axisMapping: Record[]; + floatSettings: SettingsNumber[]; + intSettings: SettingsNumber[]; + roamingSetttingsVersion: number; + stringSettings: SettingsString[]; + settingsProfiles: string[]; +} +``` + +Returns + +```ts +interface ClientSettingsResponse { + data: string; + modified: number; + type: string; +} +``` diff --git a/jest.config.js b/jest.config.js index 3ab3f05..7aa6044 100644 --- a/jest.config.js +++ b/jest.config.js @@ -8,5 +8,7 @@ module.exports = { preset: "ts-jest", testEnvironment: "node", coverageReporters: ["json-summary"], + setupFiles: ["dotenv/config"], + setupFilesAfterEnv: ["./__tests__/__setup__/jest-extended.ts"], moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: "/src" }), }; diff --git a/jest.integration.config.js b/jest.integration.config.js new file mode 100644 index 0000000..aa49179 --- /dev/null +++ b/jest.integration.config.js @@ -0,0 +1,20 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +// jest.config.js +const { pathsToModuleNameMapper } = require("ts-jest/utils"); +const { compilerOptions } = require("./tsconfig.json"); + +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: "ts-jest", + globals: { + "ts-jest": { + tsconfig: "./tsconfig-test.json", + }, + }, + testEnvironment: "node", + coverageReporters: ["json-summary"], + setupFiles: ["dotenv/config"], + setupFilesAfterEnv: ["./__tests__/__setup__/integration.ts", "./__tests__/__setup__/jest-extended.ts"], + testPathIgnorePatterns: ["/node_modules/", "/__setup__/"], + moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: "/src" }), +}; diff --git a/package.json b/package.json index 17f0887..c6c3abc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "valclient.js", - "version": "1.1.1", + "version": "1.2.0", "description": "Valorant Client API Wrapper in NodeJS", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -19,7 +19,9 @@ ], "scripts": { "lint": "eslint src/**/*.ts --quiet --fix", - "test": "jest", + "test": "yarn test:integration && yarn test:unit", + "test:integration": "jest integration -c=jest.integration.config.js", + "test:unit": "jest unit -c=jest.config.js", "prepare": "husky install", "start": "cross-env NODE_ENV=development nodemon --watch src -r tsconfig-paths/register src/index.ts", "update:types": "ts-node -r tsconfig-paths/register src/utils/updateTypes.ts && yarn lint", @@ -56,6 +58,7 @@ "husky": "7.0.2", "istanbul-badges-readme": "1.4.0", "jest": "27.1.1", + "jest-extended": "^1.2.0", "jest-mock-extended": "2.0.2-beta2", "lint-staged": "11.1.2", "nodemon": "2.0.12", diff --git a/src/chat.ts b/src/chat.ts new file mode 100644 index 0000000..9b987ad --- /dev/null +++ b/src/chat.ts @@ -0,0 +1,158 @@ +import { IChat, Message, ChatInfoResponse, ParticipantsResponse, MessageResponse } from "@interfaces/chat"; +import { IHttp } from "@interfaces/http"; + +class Chat implements IChat { + private readonly _http: IHttp; + + constructor(http: IHttp) { + this._http = http; + } + + /** + * GET Party Chat Info + * + * Get information about the party chat + * + * @returns {ChatInfoResponse} + */ + async getPartyChat(): Promise { + const data = await this._http.fetch("/chat/v6/conversations/ares-parties", "local"); + + return data; + } + + /** + * GET Pregame Chat Info + * + * Get information about the pregame chat + * + * @returns {ChatInfoResponse} + */ + async getPreGameChat(): Promise { + const data = await this._http.fetch("/chat/v6/conversations/ares-pregame", "local"); + + return data; + } + + /** + * GET Game Chat Info + * + * Get information about the game chat + * + * @returns {ChatInfoResponse} + */ + async getLiveGameChat(): Promise { + const data = await this._http.fetch("/chat/v6/conversations/ares-coregame", "local"); + + return data; + } + + /** + * GET All Chat Info + * + * Get information about all active conversations (party, pregame and livegame) + * + * @returns {ChatInfoResponse} + */ + async getAllChat(): Promise { + const data = await this._http.fetch("/chat/v6/conversations/", "local"); + + return data; + } + + /** + * GET TEXT_CHAT_RNet_FetchParticipants + * + * Get information about the participants of a chat + * + * @param cid e.g: "cid-{1, blue, red, all}@server" + * @returns {ParticipantsResponse} + */ + async getParticipants(cid: string): Promise { + const data = await this._http.fetch(`/chat/v5/participants/?cid=${cid}`, "local"); + + return data; + } + + /** + * GET All Chat Participants + * + * Get information about all the participants of every active conversation + * + * @returns {ParticipantsResponse} + */ + async getAllParticipants(): Promise { + const data = await this._http.fetch("/chat/v5/participants/", "local"); + + return data; + } + + /** + * GET All Chat History + * + * Get chat history for all conversations + * + * @returns {MessageResponse} + */ + async getAllHistory(): Promise { + const data = await this._http.fetch("/chat/v6/messages", "local"); + + return data; + } + + /** + * GET Specific Chat History + * + * Get chat history for a specific conversation + * + * @param cid e.g: "cid-{1, blue, red, all}@server" + */ + async getHistory(cid: string): Promise { + const data = await this._http.fetch(`/chat/v6/messages?cid=${cid}`, "local"); + + return data; + } + + /** + * POST Send Whisper + * + * Send a whisper to the specified player + * + * @param pid - You can get in player.allFriends + * @param message + * @returns {MessageResponse} + */ + async sendWhisper(pid: string, message: string): Promise { + const messageBody: Message = { + cid: pid, + message, + type: "chat", + }; + + const data = await this._http.post("/chat/v6/messages/", "local", messageBody); + + return data; + } + + /** + * POST Send Chat + * + * Send a message to the specified group + * + * @param cid - You can get in chat.getAllChat() + * @param message + */ + async sendMessage(cid: string, message: string): Promise { + const messageBody: Message = { + cid, + message, + type: "groupchat", + }; + + const data = await this._http.post("/chat/v6/messages/", "local", messageBody); + + return data; + } +} + +export { Chat }; diff --git a/src/client.ts b/src/client.ts index 64aa89e..333cf88 100644 --- a/src/client.ts +++ b/src/client.ts @@ -30,6 +30,7 @@ import { IPvp } from "@interfaces/pvp"; import { IStore } from "@interfaces/store"; import { IContracts } from "@interfaces/contracts"; import { ILoadout } from "@interfaces/loadout"; +import { IChat } from "@interfaces/chat"; import { Player } from "@app/player"; import { Valorant } from "@app/valorant"; @@ -41,6 +42,7 @@ import { Pvp } from "@app/pvp"; import { Store } from "@app/store"; import { Contracts } from "@app/contracts"; import { Loadout } from "@app/loadout"; +import { Chat } from "@app/chat"; export const addAuthHeaders = (headers: Partial) => @@ -63,8 +65,6 @@ export const addLocalHeaders = }; config.withCredentials = true; - - return config; } return config; @@ -88,6 +88,7 @@ class ValClient implements IValClient { public _http_service: HttpService; public player: IPlayer | null = null; + public chat: IChat | null = null; public valorant: IValorant | null = null; public group: IGroup | null = null; public live_game: ILiveGame | null = null; @@ -133,6 +134,7 @@ class ValClient implements IValClient { this.player = new Player(this._http_service, this._puuid); this.valorant = new Valorant(this._http_service); + this.chat = new Chat(this._http_service); } else { await this._getAuthHeaders(); } diff --git a/src/index.ts b/src/index.ts index 55213a4..9f4acc9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,7 @@ export * from "@interfaces/store"; export * from "@interfaces/valorant"; export * from "@interfaces/auth"; export * from "@interfaces/client"; +export * from "@interfaces/chat"; export * from "@interfaces/contracts"; export * from "@resources"; diff --git a/src/interfaces/chat.ts b/src/interfaces/chat.ts new file mode 100644 index 0000000..aa50867 --- /dev/null +++ b/src/interfaces/chat.ts @@ -0,0 +1,71 @@ +export interface IChat { + getPartyChat(): Promise; + getPreGameChat(): Promise; + getLiveGameChat(): Promise; + getAllChat(): Promise; + getParticipants(cid: string): Promise; + getAllParticipants(): Promise; + getAllHistory(): Promise; + getHistory(cid: string): Promise; + sendWhisper(pid: string, message: string): Promise; + sendMessage(cid: string, message: string): Promise; +} + +export type ChatTypes = "chat" | "groupchat"; + +export interface Message { + cid: string; + message: string; + type: ChatTypes; +} + +export interface ChatInfo { + cid: string; + direct_messages: boolean; + global_readership: boolean; + message_history: boolean; + mid: string; + muted: boolean; + mutedRestriction: boolean; + type: ChatTypes; + uiState: { changedSinceHidden: boolean; hidden: boolean }; + unread_count: number; +} + +export interface ChatInfoResponse { + conversations: ChatInfo[]; +} + +export interface ParticipantInfo { + cid: string; + game_name: string; + game_tag: string; + muted: boolean; + name: string; + pid: string; + puuid: string; + region: string; +} +export interface ParticipantsResponse { + participants: ParticipantInfo[]; +} + +export interface MessageInfo { + body: string; + cid: string; + game_name: string; + game_tag: string; + id: string; + mid: string; + name: string; + pid: string; + puuid: string; + read: boolean; + region: string; + time: string; + type: string; +} + +export interface MessageResponse { + messages: MessageInfo[]; +} diff --git a/src/interfaces/preGame.ts b/src/interfaces/preGame.ts index 0b6e97a..6eb907c 100644 --- a/src/interfaces/preGame.ts +++ b/src/interfaces/preGame.ts @@ -1,5 +1,5 @@ import { CoreGameItem, CoreGameResponse, CoreGameSpraySelection } from "@interfaces/liveGame"; -import { Agents } from "@type/resources"; +import { Agents } from "@type/agents"; export interface IPreGame { current(): Promise; diff --git a/src/interfaces/pvp.ts b/src/interfaces/pvp.ts index fa50d2e..612c7b6 100644 --- a/src/interfaces/pvp.ts +++ b/src/interfaces/pvp.ts @@ -27,30 +27,13 @@ export interface PvpSeasonsItem { Type: string; StartTime: string; EndTime: string; - IsEnabled: boolean; IsActive: boolean; DevelopmentOnly: boolean; } export interface PvpContents { - Characters: PvpContentItem[]; - Maps: PvpContentItem[]; - Chromas: PvpContentItem[]; - Skins: PvpContentItem[]; - SkinLevels: PvpContentItem[]; - Attachments: PvpContentItem[]; - Equips: PvpContentItem[]; - Themes: PvpContentItem[]; - GameModes: PvpContentItem[]; - Sprays: PvpContentItem[]; - SprayLevels: PvpContentItem[]; - Charms: PvpContentItem[]; - CharmLevels: PvpContentItem[]; - PlayerCards: PvpContentItem[]; - PlayerTitles: PvpContentItem[]; - StorefrontItems: PvpContentItem[]; + DisabledIDs: unknown[]; Seasons: PvpSeasonsItem[]; - CompetitiveSeasons: PvpCompetitiveSeason[]; Events: PvpEventItem[]; } diff --git a/src/interfaces/valorant.ts b/src/interfaces/valorant.ts index f4a48eb..0f4a3c5 100644 --- a/src/interfaces/valorant.ts +++ b/src/interfaces/valorant.ts @@ -4,6 +4,7 @@ import { Locale } from "@type/resources"; export interface IValorant { process(): Promise>; clientSettings(): Promise; + changeSettings(data: ClientSettings): Promise; crossHair(): Promise>; } @@ -40,15 +41,19 @@ export type SettingsEnumFloat = | "EAresFloatSettingName::CharacterSelectMusicVolume" | "EAresFloatSettingName::CrosshairOutlineOpacity" | "EAresFloatSettingName::CrosshairCenterDotSize" + | "EAresFloatSettingName::CrosshairCenterDotOpacity" | "EAresFloatSettingName::CrosshairInnerLinesLineThickness" | "EAresFloatSettingName::CrosshairInnerLinesLineLength" | "EAresFloatSettingName::CrosshairInnerLinesLineOffset" - | "EAresFloatSettingName::CrosshairOuterLinesOpacity"; + | "EAresFloatSettingName::CrosshairInnerLinesOpacity" + | "EAresFloatSettingName::AimToolingRadialFrictionBaseSpeedMultiplierX"; export type SettingsEnumBool = + | "EAresBoolSettingName::MinimapRotates" | "EAresBoolSettingName::MinimapTranslates" | "EAresBoolSettingName::PushToTalkEnabled" - | "EAresBoolSettingName::ShootingRangeBotArmorEnabled" + | "EAresBoolSettingName::FadeCrosshairWithFiringError" + | "EAresBoolSettingName::ShowCorpses" | "EAresBoolSettingName::CrosshairHasOutline" | "EAresBoolSettingName::CrosshairInnerLinesShowShootingError" | "EAresBoolSettingName::CrosshairOuterLinesShowMovementError" @@ -63,29 +68,27 @@ export type SettingsEnumBool = | "EAresBoolSettingName::PlayerBehavior_MuteEnemyTextChat" | "EAresBoolSettingName::HasEverAppliedRoamingSettings"; -export interface SettingsNumber { - settingEnum: string; - value: number; -} - -export interface SettingsString { - settingEnum: SettingsEnumString; - value: string; -} - +export type SettingsValue = { + settingEnum: SettingEnum; + value: Value; +}; export interface ClientSettingsResponse { - data: { - actionMappings: ActionMap[]; - axisMapping: Record[]; - floatSettings: SettingsNumber[]; - intSettings: SettingsNumber[]; - roamingSetttingsVersion: number; - stringSettings: SettingsString[]; - }; + data: ClientSettings; modified: number; type: string; } +export interface ClientSettings { + actionMappings: ActionMap[]; + axisMapping: Record[]; + floatSettings: SettingsValue[]; + intSettings: SettingsValue[]; + boolSettings: SettingsValue[]; + roamingSetttingsVersion: number; + stringSettings: SettingsValue[]; + settingsProfiles: string[]; +} + export interface ValorantProcessLaunchConfiguration { arguments: string[]; executable: string; diff --git a/src/pvp.ts b/src/pvp.ts index 69f4338..5c9a68a 100644 --- a/src/pvp.ts +++ b/src/pvp.ts @@ -33,10 +33,10 @@ class Pvp implements IPvp { /** * Content_FetchContent * - * Get names and ids for game content such as agents, maps, guns, etc. + * Get all PVP content e.g: battleplass, events, acts, etc... */ async contents(): Promise { - const data = await this._http.fetch("/content-service/v2/content", "shared"); + const data = await this._http.fetch("/content-service/v3/content", "shared"); return data; } diff --git a/src/types/pvp.ts b/src/types/pvp.ts index 3e20ee6..6ba1fcf 100644 --- a/src/types/pvp.ts +++ b/src/types/pvp.ts @@ -6,7 +6,7 @@ export type PvpCompetitiveSeason = Pick; export type PvpItemProgressDefinitionsRewards = PvpItemProgressDefinitionsItem & { Amount: number }; diff --git a/src/valorant.ts b/src/valorant.ts index 82da352..c48febc 100644 --- a/src/valorant.ts +++ b/src/valorant.ts @@ -1,7 +1,7 @@ import { CrossHair, CrossHairProfileData } from "@interfaces/crosshair"; import { IHttp } from "@interfaces/http"; -import { ClientSettingsResponse, IValorant, ValorantProcessResponse } from "@interfaces/valorant"; +import { ClientSettingsResponse, IValorant, ValorantProcessResponse, ClientSettings } from "@interfaces/valorant"; class Valorant implements IValorant { private readonly _http: IHttp; @@ -36,6 +36,21 @@ class Valorant implements IValorant { return data; } + /** + * RiotKV_RNet_PutSettings + * + * Update client settings + */ + async changeSettings(settings: ClientSettings): Promise { + const data = await this._http.put( + "/player-preferences/v1/data-json/Ares.PlayerSettings", + "local", + settings, + ); + + return data; + } + /** * Get crosshair settings * @returns Profile name with crosshair settings diff --git a/tsconfig-test.json b/tsconfig-test.json new file mode 100644 index 0000000..f3a3582 --- /dev/null +++ b/tsconfig-test.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["./__tests__/__setup__/integration.ts"] +} diff --git a/tsconfig.json b/tsconfig.json index c1b4787..f47add0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,7 +18,8 @@ "@resources/*": ["./resources/*"], "@errors/*": ["./errors/*"], "@interfaces/*": ["./interfaces/*"], - "@app/*": ["./*"] + "@app/*": ["./*"], + "@tests/*": ["../__tests__/*"] }, "plugins": [ { @@ -33,6 +34,6 @@ }, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "include": ["src/**/*.ts", "__tests__/**/*.test.ts"], + "include": ["src/**/*.ts", "__tests__/**/*.ts"], "exclude": ["node_modules", "dist"] } diff --git a/yarn.lock b/yarn.lock index c0be9b5..0a732b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -524,6 +524,17 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@jest/types@^27.1.1": version "27.1.1" resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.1.1.tgz#77a3fc014f906c65752d12123a0134359707c0ad" @@ -719,6 +730,13 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + "@types/yargs@^16.0.0": version "16.0.4" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" @@ -916,6 +934,11 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -1465,11 +1488,21 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + diff-sequences@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ== +diff-sequences@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" + integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -1744,6 +1777,18 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= +expect@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== + dependencies: + "@jest/types" "^26.6.2" + ansi-styles "^4.0.0" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + expect@^27.1.1: version "27.1.1" resolved "https://registry.yarnpkg.com/expect/-/expect-27.1.1.tgz#020215da67d41cd6ad805fa00bd030985ca7c093" @@ -2381,6 +2426,16 @@ jest-config@^27.1.1: micromatch "^4.0.4" pretty-format "^27.1.1" +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + jest-diff@^27.0.0, jest-diff@^27.1.1: version "27.1.1" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.1.1.tgz#1d1629ca2e3933b10cb27dc260e28e3dba182684" @@ -2391,6 +2446,16 @@ jest-diff@^27.0.0, jest-diff@^27.1.1: jest-get-type "^27.0.6" pretty-format "^27.1.1" +jest-diff@^27.2.5, jest-diff@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.6.tgz#93815774d2012a2cbb6cf23f84d48c7a2618f98d" + integrity sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.4.0" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" + jest-docblock@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3" @@ -2434,11 +2499,31 @@ jest-environment-node@^27.1.1: jest-mock "^27.1.1" jest-util "^27.1.1" +jest-extended@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/jest-extended/-/jest-extended-1.2.0.tgz#6ef87d806bd9501a0aeae56fe8c7af73777987ed" + integrity sha512-KYc5DgD+/8viJSEKBzb1vRXe/rEEQUxEovBTdNEer9A6lzvHvhuyslM5tQFBz8TbLEkicCmsEcQF+4N7GiPTLg== + dependencies: + expect "^26.6.2" + jest-diff "^27.2.5" + jest-get-type "^27.0.6" + jest-matcher-utils "^27.2.4" + +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + jest-get-type@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.6.tgz#0eb5c7f755854279ce9b68a9f1a4122f69047cfe" integrity sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg== +jest-get-type@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" + integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== + jest-haste-map@^27.1.1: version "27.1.1" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.1.1.tgz#f7c646b0e417ec29b80b96cf785b57b581384adf" @@ -2491,6 +2576,16 @@ jest-leak-detector@^27.1.1: jest-get-type "^27.0.6" pretty-format "^27.1.1" +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== + dependencies: + chalk "^4.0.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + jest-matcher-utils@^27.1.1: version "27.1.1" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.1.1.tgz#1f444d7491ccf9edca746336b056178789a59651" @@ -2501,6 +2596,31 @@ jest-matcher-utils@^27.1.1: jest-get-type "^27.0.6" pretty-format "^27.1.1" +jest-matcher-utils@^27.2.4: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.4.6.tgz#53ca7f7b58170638590e946f5363b988775509b8" + integrity sha512-XD4PKT3Wn1LQnRAq7ZsTI0VRuEc9OrCPFiO1XL7bftTGmfNF0DcEwMHRgqiu7NGf8ZoZDREpGrCniDkjt79WbA== + dependencies: + chalk "^4.0.0" + jest-diff "^27.4.6" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" + +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/types" "^26.6.2" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.2" + pretty-format "^26.6.2" + slash "^3.0.0" + stack-utils "^2.0.2" + jest-message-util@^27.1.1: version "27.1.1" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.1.1.tgz#980110fb72fcfa711cd9a95e8f10d335207585c6" @@ -2536,6 +2656,11 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== + jest-regex-util@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5" @@ -2979,7 +3104,7 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.4: +micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== @@ -3290,6 +3415,16 @@ prettier@2.3.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + pretty-format@^27.0.0, pretty-format@^27.1.1: version "27.1.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.1.1.tgz#cbaf9ec6cd7cfc3141478b6f6293c0ccdbe968e0" @@ -3300,6 +3435,15 @@ pretty-format@^27.0.0, pretty-format@^27.1.1: ansi-styles "^5.0.0" react-is "^17.0.1" +pretty-format@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.6.tgz#1b784d2f53c68db31797b2348fa39b49e31846b7" + integrity sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -3584,6 +3728,13 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +stack-utils@^2.0.2: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + dependencies: + escape-string-regexp "^2.0.0" + stack-utils@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277"