mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-13 07:36:10 +00:00
simplex-chat-nodejs: add member contact API methods (#6763)
* simplex-chat-nodejs: add apiCreateMemberContact and apiSendMemberContactInvitation * simplex-chat-nodejs: add integration test for apiCreateMemberContact and apiSendMemberContactInvitation Test creates a 3-user group with direct messages enabled, then verifies: - apiCreateMemberContact creates a DM contact between group members - apiSendMemberContactInvitation sends an invitation that the recipient receives * simplex-chat-nodejs: bump @simplex-chat/types to ^0.4.0
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
"docs": "typedoc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@simplex-chat/types": "^0.3.0",
|
||||
"@simplex-chat/types": "^0.4.0",
|
||||
"extract-zip": "^2.0.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"node-addon-api": "^8.5.0"
|
||||
|
||||
@@ -872,4 +872,34 @@ export class ChatApi {
|
||||
const r = await this.sendChatCmd(CC.APISetContactPrefs.cmdString({contactId, preferences}))
|
||||
if (r.type !== "contactPrefsUpdated") throw new ChatCommandError("error setting contact prefs", r)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a direct message contact with a group member.
|
||||
* Returns the created contact.
|
||||
* Network usage: interactive.
|
||||
*/
|
||||
async apiCreateMemberContact(groupId: number, groupMemberId: number): Promise<T.Contact> {
|
||||
const r: any = await this.sendChatCmd(`/_create member contact #${groupId} ${groupMemberId}`)
|
||||
if (r.type === "newMemberContact") return r.contact
|
||||
throw new ChatCommandError("error creating member contact", r)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a direct message invitation to a group member contact.
|
||||
* The contact must have been created with {@link apiCreateMemberContact}.
|
||||
* Network usage: interactive.
|
||||
*/
|
||||
async apiSendMemberContactInvitation(contactId: number, message?: T.MsgContent | string): Promise<T.Contact> {
|
||||
let cmd = `/_invite member contact @${contactId}`
|
||||
if (message !== undefined) {
|
||||
if (typeof message === "string") {
|
||||
cmd += ` text ${message}`
|
||||
} else {
|
||||
cmd += ` json ${JSON.stringify(message)}`
|
||||
}
|
||||
}
|
||||
const r: any = await this.sendChatCmd(cmd)
|
||||
if (r.type === "newMemberContactSentInv") return r.contact
|
||||
throw new ChatCommandError("error sending member contact invitation", r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,4 +64,89 @@ describe("API tests (use preset servers)", () => {
|
||||
expect(servers[0] !== servers[1]).toBe(true)
|
||||
expect(eventCount > 0).toBe(true)
|
||||
}, 30000)
|
||||
|
||||
it("should create member contact and send invitation", async () => {
|
||||
// create 3 users and start chat controllers
|
||||
const alice = await api.ChatApi.init(alicePath)
|
||||
const bob = await api.ChatApi.init(bobPath)
|
||||
const carolPath = path.join(tmpDir, "carol")
|
||||
const carol = await api.ChatApi.init(carolPath)
|
||||
const aliceUser = await alice.apiCreateActiveUser({displayName: "alice", fullName: ""})
|
||||
await bob.apiCreateActiveUser({displayName: "bob", fullName: ""})
|
||||
await carol.apiCreateActiveUser({displayName: "carol", fullName: ""})
|
||||
await alice.startChat()
|
||||
await bob.startChat()
|
||||
await carol.startChat()
|
||||
// connect alice <-> bob
|
||||
const aliceLink1 = await alice.apiCreateLink(aliceUser.userId)
|
||||
await expect(bob.apiConnectActiveUser(aliceLink1)).resolves.toBe(api.ConnReqType.Invitation)
|
||||
const [bobContact] = await Promise.all([
|
||||
(await alice.wait("contactConnected")).contact,
|
||||
(await bob.wait("contactConnected")).contact
|
||||
])
|
||||
// connect alice <-> carol
|
||||
const aliceLink2 = await alice.apiCreateLink(aliceUser.userId)
|
||||
await expect(carol.apiConnectActiveUser(aliceLink2)).resolves.toBe(api.ConnReqType.Invitation)
|
||||
const [carolContact] = await Promise.all([
|
||||
(await alice.wait("contactConnected")).contact,
|
||||
(await carol.wait("contactConnected")).contact
|
||||
])
|
||||
// create group with direct messages enabled
|
||||
const group = await alice.apiNewGroup(aliceUser.userId, {
|
||||
displayName: "test-group",
|
||||
fullName: "",
|
||||
groupPreferences: {
|
||||
directMessages: {enable: T.GroupFeatureEnabled.On},
|
||||
},
|
||||
})
|
||||
const groupId = group.groupId
|
||||
// add bob to the group
|
||||
const bobInvP = bob.wait("receivedGroupInvitation", 15000)
|
||||
await alice.apiAddMember(groupId, bobContact.contactId, T.GroupMemberRole.Member)
|
||||
const bobInvEvt = await bobInvP
|
||||
expect(bobInvEvt).toBeDefined()
|
||||
const aliceBobConnP = alice.wait("connectedToGroupMember", 15000)
|
||||
const bobAliceConnP = bob.wait("connectedToGroupMember", 15000)
|
||||
await bob.apiJoinGroup(bobInvEvt!.groupInfo.groupId)
|
||||
await Promise.all([aliceBobConnP, bobAliceConnP])
|
||||
// add carol to the group
|
||||
const carolInvP = carol.wait("receivedGroupInvitation", 30000)
|
||||
await alice.apiAddMember(groupId, carolContact.contactId, T.GroupMemberRole.Member)
|
||||
const carolInvEvt = await carolInvP
|
||||
expect(carolInvEvt).toBeDefined()
|
||||
// wait for carol to connect to both alice and bob (and vice versa)
|
||||
const bobCarolConnP = bob.wait("connectedToGroupMember",
|
||||
(evt: CEvt.ConnectedToGroupMember) => evt.member.memberProfile.displayName === "carol", 30000)
|
||||
const carolAliceConnP = carol.wait("connectedToGroupMember",
|
||||
(evt: CEvt.ConnectedToGroupMember) => evt.member.memberProfile.displayName === "alice", 30000)
|
||||
const carolBobConnP = carol.wait("connectedToGroupMember",
|
||||
(evt: CEvt.ConnectedToGroupMember) => evt.member.memberProfile.displayName === "bob", 30000)
|
||||
const aliceCarolConnP = alice.wait("connectedToGroupMember",
|
||||
(evt: CEvt.ConnectedToGroupMember) => evt.member.memberProfile.displayName === "carol", 30000)
|
||||
await carol.apiJoinGroup(carolInvEvt!.groupInfo.groupId)
|
||||
await Promise.all([bobCarolConnP, carolAliceConnP, carolBobConnP, aliceCarolConnP])
|
||||
// find carol's memberId from bob's perspective
|
||||
const members = await bob.apiListMembers(groupId)
|
||||
const carolMember = members.find(m => m.memberProfile.displayName === "carol")
|
||||
expect(carolMember).toBeDefined()
|
||||
// test apiCreateMemberContact
|
||||
const dmContact = await bob.apiCreateMemberContact(groupId, carolMember!.groupMemberId)
|
||||
expect(dmContact).toBeDefined()
|
||||
expect(dmContact.contactId).toBeDefined()
|
||||
// test apiSendMemberContactInvitation
|
||||
const carolDmP = carol.wait("newMemberContactReceivedInv" as CEvt.Tag, 30000)
|
||||
const invContact = await bob.apiSendMemberContactInvitation(dmContact.contactId, "hello from bob")
|
||||
expect(invContact).toBeDefined()
|
||||
// carol should receive the member contact invitation
|
||||
const carolDmEvt = await carolDmP
|
||||
expect(carolDmEvt).toBeDefined()
|
||||
expect((carolDmEvt as any).contact).toBeDefined()
|
||||
// cleanup
|
||||
await alice.stopChat()
|
||||
await bob.stopChat()
|
||||
await carol.stopChat()
|
||||
await alice.close()
|
||||
await bob.close()
|
||||
await carol.close()
|
||||
}, 90000)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user