mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-29 00:18:43 +00:00
update name in bot address
This commit is contained in:
@@ -422,7 +422,18 @@ export class ChatApi {
|
||||
const r = await this.sendChatCmd(CC.APISetAddressSettings.cmdString({userId, settings}))
|
||||
if (r.type !== "userContactLinkUpdated") {
|
||||
throw new ChatCommandError("error changing user contact address settings", r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async apiSetUserDomain(userId: number, simplexDomain?: string): Promise<T.User> {
|
||||
const r = await this.sendChatCmd(CC.APISetUserDomain.cmdString({userId, simplexDomain}))
|
||||
switch (r.type) {
|
||||
case "userProfileUpdated":
|
||||
case "userProfileNoChange":
|
||||
return r.user
|
||||
default:
|
||||
throw new ChatCommandError("error setting SimpleX name", r)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@ const defaultOpts: Required<BotOptions> = {
|
||||
|
||||
export interface BotConfig {
|
||||
profile: T.Profile,
|
||||
simplexName?: string,
|
||||
dbOpts: BotDbOpts,
|
||||
options: BotOptions,
|
||||
onMessage?: (chatItem: T.AChatItem, content: T.MsgContent, chat: api.ChatApi) => void | Promise<void>,
|
||||
@@ -45,7 +46,7 @@ export interface BotConfig {
|
||||
events?: api.EventSubscribers
|
||||
}
|
||||
|
||||
export async function run({profile, dbOpts, options = defaultOpts, onMessage, onCommands = {}, events = {}}: BotConfig): Promise<[api.ChatApi, T.User, T.UserContactLink | undefined]> {
|
||||
export async function run({profile, simplexName, dbOpts, options = defaultOpts, onMessage, onCommands = {}, events = {}}: BotConfig): Promise<[api.ChatApi, T.User, T.UserContactLink | undefined]> {
|
||||
const bot = await api.ChatApi.init(dbOpts, dbOpts.confirmMigrations || core.MigrationConfirmation.YesUp, dbOpts.queueSize)
|
||||
const opts = fullOptions(options)
|
||||
if (onMessage || Object.keys(onCommands).length > 0) subscribeChatItems(bot, onMessage, onCommands)
|
||||
@@ -60,7 +61,8 @@ export async function run({profile, dbOpts, options = defaultOpts, onMessage, on
|
||||
console.log(`Bot address: ${addressLink}`)
|
||||
if (opts.useBotProfile) botProfile.contactLink = addressLink
|
||||
}
|
||||
await updateBotUserProfile(bot, user, botProfile, opts)
|
||||
const namedUser = await updateBotSimplexName(bot, user, simplexName, opts)
|
||||
await updateBotUserProfile(bot, namedUser, botProfile, opts)
|
||||
return [bot, user, address]
|
||||
}
|
||||
|
||||
@@ -180,15 +182,32 @@ async function createOrUpdateAddress(bot: api.ChatApi, user: T.User, opts: Requi
|
||||
}
|
||||
}
|
||||
|
||||
return address
|
||||
return address
|
||||
}
|
||||
|
||||
async function updateBotSimplexName(bot: api.ChatApi, user: T.User, simplexName: string | undefined, opts: Required<BotOptions>): Promise<T.User> {
|
||||
const name = simplexName?.toLowerCase()
|
||||
if (user.profile.contactDomain?.domain === name) return user
|
||||
if (!opts.updateAddress) {
|
||||
console.log("Bot SimpleX name changed")
|
||||
return user
|
||||
}
|
||||
console.log("Bot SimpleX name changed, updating...")
|
||||
try {
|
||||
return await bot.apiSetUserDomain(user.userId, name)
|
||||
} catch (e) {
|
||||
console.log("Error updating bot SimpleX name", e)
|
||||
return user
|
||||
}
|
||||
}
|
||||
|
||||
async function updateBotUserProfile(bot: api.ChatApi, user: T.User, profile: T.Profile, opts: Required<BotOptions>): Promise<void> {
|
||||
const {userId} = user
|
||||
if (!equal(util.fromLocalProfile(user.profile), profile)) {
|
||||
const {contactDomain, ...currentProfile} = util.fromLocalProfile(user.profile)
|
||||
if (!equal(currentProfile, profile)) {
|
||||
if (opts.updateProfile) {
|
||||
console.log("Bot profile changed, updating...")
|
||||
const summary = await bot.apiUpdateProfile(userId, profile)
|
||||
const summary = await bot.apiUpdateProfile(userId, {...profile, contactDomain})
|
||||
console.log(
|
||||
summary
|
||||
? `Bot profile updated: ${summary.updateSuccesses} updated contact(s), ${summary.updateFailures} failed contact update(s).`
|
||||
|
||||
@@ -53,8 +53,8 @@ export function botAddressSettings({addressSettings}: T.UserContactLink): BotAdd
|
||||
}
|
||||
}
|
||||
|
||||
export function fromLocalProfile({displayName, fullName, shortDescr, image, contactLink, preferences, peerType}: T.LocalProfile): T.Profile {
|
||||
const profile = {displayName, fullName, shortDescr, image, contactLink, preferences, peerType}
|
||||
export function fromLocalProfile({displayName, fullName, shortDescr, image, contactLink, preferences, peerType, contactDomain}: T.LocalProfile): T.Profile {
|
||||
const profile = {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, contactDomain: contactDomain && {domain: contactDomain.domain}}
|
||||
for (const key in profile) {
|
||||
if (typeof (profile as any)[key] === "undefined") delete (profile as any)[key]
|
||||
}
|
||||
|
||||
@@ -30,6 +30,13 @@ describe("documented success responses", () => {
|
||||
await expect(chat.apiSetProfileAddress(1, true)).resolves.toEqual({updateSuccesses: 0, updateFailures: 0, changedContacts: []})
|
||||
})
|
||||
|
||||
it("apiSetUserDomain sets and removes the name", async () => {
|
||||
const chat = await chatWithResponse({type: "userProfileNoChange", user})
|
||||
await expect(chat.apiSetUserDomain(1, "calc.simplex")).resolves.toEqual(user)
|
||||
await expect(chat.apiSetUserDomain(1)).resolves.toEqual(user)
|
||||
expect(jest.mocked(core.chatSendCmd).mock.calls.map(([, cmd]) => cmd)).toEqual(["/_set domain 1 calc.simplex", "/_set domain 1"])
|
||||
})
|
||||
|
||||
it("apiReceiveFile reports a file cancelled by sender", async () => {
|
||||
const chat = await chatWithResponse({type: "rcvFileAcceptedSndCancelled", user, rcvFileTransfer: {}})
|
||||
await expect(chat.apiReceiveFile(3)).rejects.toThrow("file cancelled by sender")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {ChatEvent, T} from "@simplex-chat/types"
|
||||
import * as api from "../src/api"
|
||||
import {subscribeChatItems} from "../src/bot"
|
||||
import {run, subscribeChatItems} from "../src/bot"
|
||||
|
||||
type Handler = (evt: ChatEvent) => Promise<void>
|
||||
|
||||
@@ -56,3 +56,68 @@ describe("subscribeChatItems", () => {
|
||||
expect(calls).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe("run", () => {
|
||||
const address = {
|
||||
connLinkContact: {connFullLink: "full", connShortLink: "short"},
|
||||
addressSettings: {businessAddress: false, autoAccept: {acceptIncognito: false}},
|
||||
} as unknown as T.UserContactLink
|
||||
|
||||
function fakeChat(contactDomain?: T.SimplexDomainClaim) {
|
||||
const user = {userId: 1, profile: {displayName: "Old", fullName: "", contactDomain}} as unknown as T.User
|
||||
const chat = {
|
||||
on: jest.fn(),
|
||||
apiGetActiveUser: jest.fn().mockResolvedValue(user),
|
||||
startChat: jest.fn(),
|
||||
apiGetUserAddress: jest.fn().mockResolvedValue(address),
|
||||
apiSetAddressSettings: jest.fn(),
|
||||
apiSetUserDomain: jest.fn(async (_userId: number, domain?: string) => ({...user, profile: {...user.profile, contactDomain: domain && {domain}}})),
|
||||
apiUpdateProfile: jest.fn().mockResolvedValue({updateSuccesses: 0, updateFailures: 0}),
|
||||
}
|
||||
jest.spyOn(api.ChatApi, "init").mockResolvedValue(chat as unknown as api.ChatApi)
|
||||
return chat
|
||||
}
|
||||
|
||||
const runBot = (simplexName?: string, options = {}) =>
|
||||
run({profile: {displayName: "Calculator", fullName: ""}, simplexName, dbOpts: {type: "sqlite", filePrefix: "unused"}, options})
|
||||
|
||||
const updatedProfile = (chat: ReturnType<typeof fakeChat>) => chat.apiUpdateProfile.mock.calls[0][1]
|
||||
|
||||
beforeEach(() => jest.spyOn(console, "log").mockImplementation(() => {}))
|
||||
afterEach(() => jest.restoreAllMocks())
|
||||
|
||||
it("sets the configured SimpleX name", async () => {
|
||||
const chat = fakeChat()
|
||||
await runBot("Calc.simplex")
|
||||
expect(chat.apiSetUserDomain).toHaveBeenCalledWith(1, "calc.simplex")
|
||||
expect(updatedProfile(chat).contactDomain).toEqual({domain: "calc.simplex"})
|
||||
})
|
||||
|
||||
it("removes the SimpleX name that is not configured", async () => {
|
||||
const chat = fakeChat({domain: "calc.simplex"})
|
||||
await runBot()
|
||||
expect(chat.apiSetUserDomain).toHaveBeenCalledWith(1, undefined)
|
||||
expect(updatedProfile(chat).contactDomain).toBeUndefined()
|
||||
})
|
||||
|
||||
it("keeps the SimpleX name when updating the profile", async () => {
|
||||
const chat = fakeChat({domain: "calc.simplex", proof: {presHeader: "header", signature: "signature"}})
|
||||
await runBot("calc.simplex")
|
||||
expect(chat.apiSetUserDomain).not.toHaveBeenCalled()
|
||||
expect(updatedProfile(chat).displayName).toBe("Calculator")
|
||||
expect(updatedProfile(chat).contactDomain).toEqual({domain: "calc.simplex"})
|
||||
})
|
||||
|
||||
it("continues when the SimpleX name cannot be set", async () => {
|
||||
const chat = fakeChat()
|
||||
chat.apiSetUserDomain.mockRejectedValue(new Error("simplexDomainNotReady"))
|
||||
await expect(runBot("calc.simplex")).resolves.toBeDefined()
|
||||
expect(updatedProfile(chat).contactDomain).toBeUndefined()
|
||||
})
|
||||
|
||||
it("does not change the SimpleX name without updateAddress", async () => {
|
||||
const chat = fakeChat()
|
||||
await runBot("calc.simplex", {updateAddress: false})
|
||||
expect(chat.apiSetUserDomain).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user