Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

## Не выпущено

### Что нового

- **Карточка контакта в сообщении (`CONTACT`) читается как контакт: у вложения есть `contact` с именем, `first_name`, `last_name` и `user_id`.**
Раньше такое вложение приходило только с видом `contact`, без имени. Что учесть: MAX не присылает телефон в карточке,
поэтому поля `phone` нет.

### Исправлено

- **Поиск по названию чата и по имени контакта не зависит от регистра в любом алфавите (cli-core 0.484.0).** Раньше
Expand Down
21 changes: 21 additions & 0 deletions src/domain/map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,27 @@ describe("toMessage", () => {
])
})

it("maps a shared contact card to Attachment.contact, without its avatar link or a phone MAX does not send", () => {
const card = {
_type: "CONTACT",
contactId: 40000001,
firstName: "Ivan",
lastName: "Testov",
name: "Ivan Testov",
photoUrl: "https://example.test/a.webp",
}
expect(toMessage({ ...messageWire, attaches: [card] }, "7268926").attachments).toEqual([
{
kind: "contact",
name: "Ivan Testov",
contact: { name: "Ivan Testov", first_name: "Ivan", last_name: "Testov", user_id: "40000001" },
},
])
expect(
toMessage({ ...messageWire, attaches: [{ _type: "CONTACT", firstName: "Ivan" }] }, "7268926").attachments,
).toEqual([{ kind: "contact", contact: { name: "Ivan", first_name: "Ivan" } }])
})

it("gives a quoted poll the chat and message that carry it", () => {
const poll = { _type: "POLL", pollId: 900, title: "Lunch?", answers: [{ answerId: 1, text: "Yes" }] }
const quoted = { id: 9, sender: 3260455, time: 1789776000000, attaches: [poll] }
Expand Down
19 changes: 18 additions & 1 deletion src/domain/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,23 @@ export const toReactions = (raw: Payload): Reactions => {
* `pnpm probe:attachments` measured on 2026-09-22: `baseUrl` on a photo, `url` on a share. A file
* and a video have no link, only `fileId` and `videoId` (measured 2026-09-23). A service message is
* `CONTROL` with `event`, and `userIds` for `new`/`add` but a single `userId` for `remove`
* (`pnpm probe:control`, 2026-09-27). MAX's `audio` is a recorded voice message; music goes as a file.
* (`pnpm probe:control`, 2026-09-27). A shared contact is `CONTACT` with `contactId`, `firstName`, `lastName`,
* `name` and `photoUrl`, and no phone number (`pnpm probe:attachments`, 2026-10-30). MAX's `audio` is a recorded voice message; music goes as a file.
*/
const toSharedContact = (entry: Payload): Attachment["contact"] => {
const firstName = text(entry.firstName)
const lastName = text(entry.lastName)
const name = text(entry.name) ?? ([firstName, lastName].filter(Boolean).join(" ") || null)
const userId = asId(entry.contactId)
if (!name) return undefined
return {
name,
...(firstName ? { first_name: firstName } : {}),
...(lastName ? { last_name: lastName } : {}),
...(userId ? { user_id: userId } : {}),
}
}

const attachments = (value: unknown, chatId: Id, messageId: Id): Attachment[] => {
if (!Array.isArray(value)) return []
return value
Expand All @@ -420,6 +435,7 @@ const attachments = (value: unknown, chatId: Id, messageId: Id): Attachment[] =>
const userIds = people?.map(asId).filter((id): id is Id => id !== undefined)
const poll = entry._type === "POLL" ? toPoll(entry, chatId, messageId) : undefined
const buttons = entry._type === "INLINE_KEYBOARD" ? toButtons(entry) : undefined
const contact = entry._type === "CONTACT" ? toSharedContact(entry) : undefined
const kind = typeof entry._type === "string" ? entry._type.toLowerCase() : "unknown"
const ref: ProviderMetadata = {
...(fileId ? { fileId } : {}),
Expand All @@ -438,6 +454,7 @@ const attachments = (value: unknown, chatId: Id, messageId: Id): Attachment[] =>
...(Object.keys(ref).length > 0 ? { providerRef: ref } : {}),
...(poll ? { poll } : {}),
...(buttons ? { buttons } : {}),
...(contact ? { contact } : {}),
}
})
}
Expand Down
Loading