feat(core): support Telegram Business and some other new features
This commit is contained in:
parent
a414ea9425
commit
756b99e12f
21 changed files with 1124 additions and 33 deletions
|
@ -177,10 +177,15 @@ import { cancelPasswordEmail, resendPasswordEmail, verifyPasswordEmail } from '.
|
||||||
import { removeCloudPassword } from './methods/password/remove-cloud-password.js'
|
import { removeCloudPassword } from './methods/password/remove-cloud-password.js'
|
||||||
import { applyBoost } from './methods/premium/apply-boost.js'
|
import { applyBoost } from './methods/premium/apply-boost.js'
|
||||||
import { canApplyBoost, CanApplyBoostResult } from './methods/premium/can-apply-boost.js'
|
import { canApplyBoost, CanApplyBoostResult } from './methods/premium/can-apply-boost.js'
|
||||||
|
import { createBusinessChatLink } from './methods/premium/create-business-chat-link.js'
|
||||||
|
import { deleteBusinessChatLink, editBusinessChatLink } from './methods/premium/edit-business-chat-link.js'
|
||||||
import { getBoostStats } from './methods/premium/get-boost-stats.js'
|
import { getBoostStats } from './methods/premium/get-boost-stats.js'
|
||||||
import { getBoosts } from './methods/premium/get-boosts.js'
|
import { getBoosts } from './methods/premium/get-boosts.js'
|
||||||
|
import { getBusinessChatLinks } from './methods/premium/get-business-chat-links.js'
|
||||||
import { getMyBoostSlots } from './methods/premium/get-my-boost-slots.js'
|
import { getMyBoostSlots } from './methods/premium/get-my-boost-slots.js'
|
||||||
import { iterBoosters } from './methods/premium/iter-boosters.js'
|
import { iterBoosters } from './methods/premium/iter-boosters.js'
|
||||||
|
import { setBusinessIntro } from './methods/premium/set-business-intro.js'
|
||||||
|
import { setBusinessWorkHours } from './methods/premium/set-business-work-hours.js'
|
||||||
import { addStickerToSet } from './methods/stickers/add-sticker-to-set.js'
|
import { addStickerToSet } from './methods/stickers/add-sticker-to-set.js'
|
||||||
import { createStickerSet } from './methods/stickers/create-sticker-set.js'
|
import { createStickerSet } from './methods/stickers/create-sticker-set.js'
|
||||||
import { deleteStickerFromSet } from './methods/stickers/delete-sticker-from-set.js'
|
import { deleteStickerFromSet } from './methods/stickers/delete-sticker-from-set.js'
|
||||||
|
@ -225,6 +230,7 @@ import { iterProfilePhotos } from './methods/users/iter-profile-photos.js'
|
||||||
import { resolveChannel, resolvePeer, resolveUser } from './methods/users/resolve-peer.js'
|
import { resolveChannel, resolvePeer, resolveUser } from './methods/users/resolve-peer.js'
|
||||||
import { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
import { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
||||||
import { setGlobalTtl } from './methods/users/set-global-ttl.js'
|
import { setGlobalTtl } from './methods/users/set-global-ttl.js'
|
||||||
|
import { setMyBirthday } from './methods/users/set-my-birthday.js'
|
||||||
import { setMyEmojiStatus } from './methods/users/set-my-emoji-status.js'
|
import { setMyEmojiStatus } from './methods/users/set-my-emoji-status.js'
|
||||||
import { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
import { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
||||||
import { setMyUsername } from './methods/users/set-my-username.js'
|
import { setMyUsername } from './methods/users/set-my-username.js'
|
||||||
|
@ -245,6 +251,8 @@ import {
|
||||||
BotReactionCountUpdate,
|
BotReactionCountUpdate,
|
||||||
BotReactionUpdate,
|
BotReactionUpdate,
|
||||||
BotStoppedUpdate,
|
BotStoppedUpdate,
|
||||||
|
BusinessChatLink,
|
||||||
|
BusinessWorkHoursDay,
|
||||||
CallbackQuery,
|
CallbackQuery,
|
||||||
Chat,
|
Chat,
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
|
@ -271,6 +279,7 @@ import {
|
||||||
InputFileLike,
|
InputFileLike,
|
||||||
InputInlineResult,
|
InputInlineResult,
|
||||||
InputMediaLike,
|
InputMediaLike,
|
||||||
|
InputMediaSticker,
|
||||||
InputMessageId,
|
InputMessageId,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
InputPrivacyRule,
|
InputPrivacyRule,
|
||||||
|
@ -4161,6 +4170,47 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
*/
|
*/
|
||||||
canApplyBoost(): Promise<CanApplyBoostResult>
|
canApplyBoost(): Promise<CanApplyBoostResult>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new business chat link
|
||||||
|
*
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
* @param text Text to be inserted into the message input
|
||||||
|
*/
|
||||||
|
createBusinessChatLink(
|
||||||
|
text: InputText,
|
||||||
|
params?: {
|
||||||
|
/** Custom title for the link */
|
||||||
|
title?: string
|
||||||
|
},
|
||||||
|
): Promise<BusinessChatLink>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit an existing business chat link
|
||||||
|
*
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
* @param link The link to edit
|
||||||
|
*/
|
||||||
|
editBusinessChatLink(
|
||||||
|
link: string | BusinessChatLink,
|
||||||
|
params: {
|
||||||
|
/** Text to be inserted in the message input */
|
||||||
|
text: InputText
|
||||||
|
/** Custom title for the link */
|
||||||
|
title?: string
|
||||||
|
},
|
||||||
|
): Promise<BusinessChatLink>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a business chat link
|
||||||
|
*
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
* @param link The link to delete
|
||||||
|
*/
|
||||||
|
deleteBusinessChatLink(link: string | BusinessChatLink): Promise<void>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about boosts in a channel
|
* Get information about boosts in a channel
|
||||||
*
|
*
|
||||||
|
@ -4190,6 +4240,13 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
limit?: number
|
limit?: number
|
||||||
},
|
},
|
||||||
): Promise<ArrayPaginated<Boost, string>>
|
): Promise<ArrayPaginated<Boost, string>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current user's business chat links
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getBusinessChatLinks(): Promise<BusinessChatLink[]>
|
||||||
/**
|
/**
|
||||||
* Get boost slots information of the current user.
|
* Get boost slots information of the current user.
|
||||||
*
|
*
|
||||||
|
@ -4227,6 +4284,57 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
chunkSize?: number
|
chunkSize?: number
|
||||||
},
|
},
|
||||||
): AsyncIterableIterator<Boost>
|
): AsyncIterableIterator<Boost>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set current user's business introduction.
|
||||||
|
*
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
* @param intro Introduction parameters, or `null` to remove
|
||||||
|
*/
|
||||||
|
setBusinessIntro(
|
||||||
|
intro: {
|
||||||
|
/**
|
||||||
|
* Title of the introduction
|
||||||
|
*/
|
||||||
|
title?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the introduction
|
||||||
|
*/
|
||||||
|
description?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sticker to show beneath the introduction
|
||||||
|
*/
|
||||||
|
sticker?: InputMediaSticker | InputFileLike | tl.TypeInputDocument
|
||||||
|
} | null,
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set current user's business work hours.
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
setBusinessWorkHours(
|
||||||
|
params:
|
||||||
|
| ({
|
||||||
|
/** Timezone in which the hours are defined */
|
||||||
|
timezone: string
|
||||||
|
} & (
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* Business work intervals, per-day (like available in {@link BusinessWorkHours.days})
|
||||||
|
*/
|
||||||
|
hours: ReadonlyArray<BusinessWorkHoursDay>
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
/** Business work intervals, raw intervals */
|
||||||
|
intervals: tl.TypeBusinessWeeklyOpen[]
|
||||||
|
}
|
||||||
|
))
|
||||||
|
| null,
|
||||||
|
): Promise<void>
|
||||||
/**
|
/**
|
||||||
* Add a sticker to a sticker set.
|
* Add a sticker to a sticker set.
|
||||||
*
|
*
|
||||||
|
@ -5062,6 +5170,22 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
* @param period New TTL period, in seconds (or 0 to disable)
|
* @param period New TTL period, in seconds (or 0 to disable)
|
||||||
*/
|
*/
|
||||||
setGlobalTtl(period: number): Promise<void>
|
setGlobalTtl(period: number): Promise<void>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or remove current user's birthday.
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
setMyBirthday(
|
||||||
|
birthday: {
|
||||||
|
/** Birthday day */
|
||||||
|
day: number
|
||||||
|
/** Birthday month */
|
||||||
|
month: number
|
||||||
|
/** Birthday year (optional) */
|
||||||
|
year?: number
|
||||||
|
} | null,
|
||||||
|
): Promise<void>
|
||||||
/**
|
/**
|
||||||
* Set an emoji status for the current user
|
* Set an emoji status for the current user
|
||||||
*
|
*
|
||||||
|
@ -5742,18 +5866,36 @@ TelegramClient.prototype.applyBoost = function (...args) {
|
||||||
TelegramClient.prototype.canApplyBoost = function (...args) {
|
TelegramClient.prototype.canApplyBoost = function (...args) {
|
||||||
return canApplyBoost(this._client, ...args)
|
return canApplyBoost(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
TelegramClient.prototype.createBusinessChatLink = function (...args) {
|
||||||
|
return createBusinessChatLink(this._client, ...args)
|
||||||
|
}
|
||||||
|
TelegramClient.prototype.editBusinessChatLink = function (...args) {
|
||||||
|
return editBusinessChatLink(this._client, ...args)
|
||||||
|
}
|
||||||
|
TelegramClient.prototype.deleteBusinessChatLink = function (...args) {
|
||||||
|
return deleteBusinessChatLink(this._client, ...args)
|
||||||
|
}
|
||||||
TelegramClient.prototype.getBoostStats = function (...args) {
|
TelegramClient.prototype.getBoostStats = function (...args) {
|
||||||
return getBoostStats(this._client, ...args)
|
return getBoostStats(this._client, ...args)
|
||||||
}
|
}
|
||||||
TelegramClient.prototype.getBoosts = function (...args) {
|
TelegramClient.prototype.getBoosts = function (...args) {
|
||||||
return getBoosts(this._client, ...args)
|
return getBoosts(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
TelegramClient.prototype.getBusinessChatLinks = function (...args) {
|
||||||
|
return getBusinessChatLinks(this._client, ...args)
|
||||||
|
}
|
||||||
TelegramClient.prototype.getMyBoostSlots = function (...args) {
|
TelegramClient.prototype.getMyBoostSlots = function (...args) {
|
||||||
return getMyBoostSlots(this._client, ...args)
|
return getMyBoostSlots(this._client, ...args)
|
||||||
}
|
}
|
||||||
TelegramClient.prototype.iterBoosters = function (...args) {
|
TelegramClient.prototype.iterBoosters = function (...args) {
|
||||||
return iterBoosters(this._client, ...args)
|
return iterBoosters(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
TelegramClient.prototype.setBusinessIntro = function (...args) {
|
||||||
|
return setBusinessIntro(this._client, ...args)
|
||||||
|
}
|
||||||
|
TelegramClient.prototype.setBusinessWorkHours = function (...args) {
|
||||||
|
return setBusinessWorkHours(this._client, ...args)
|
||||||
|
}
|
||||||
TelegramClient.prototype.addStickerToSet = function (...args) {
|
TelegramClient.prototype.addStickerToSet = function (...args) {
|
||||||
return addStickerToSet(this._client, ...args)
|
return addStickerToSet(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
@ -5900,6 +6042,9 @@ TelegramClient.prototype.resolveChannel = function (...args) {
|
||||||
TelegramClient.prototype.setGlobalTtl = function (...args) {
|
TelegramClient.prototype.setGlobalTtl = function (...args) {
|
||||||
return setGlobalTtl(this._client, ...args)
|
return setGlobalTtl(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
TelegramClient.prototype.setMyBirthday = function (...args) {
|
||||||
|
return setMyBirthday(this._client, ...args)
|
||||||
|
}
|
||||||
TelegramClient.prototype.setMyEmojiStatus = function (...args) {
|
TelegramClient.prototype.setMyEmojiStatus = function (...args) {
|
||||||
return setMyEmojiStatus(this._client, ...args)
|
return setMyEmojiStatus(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,10 +192,16 @@ export { removeCloudPassword } from './methods/password/remove-cloud-password.js
|
||||||
export { applyBoost } from './methods/premium/apply-boost.js'
|
export { applyBoost } from './methods/premium/apply-boost.js'
|
||||||
export type { CanApplyBoostResult } from './methods/premium/can-apply-boost.js'
|
export type { CanApplyBoostResult } from './methods/premium/can-apply-boost.js'
|
||||||
export { canApplyBoost } from './methods/premium/can-apply-boost.js'
|
export { canApplyBoost } from './methods/premium/can-apply-boost.js'
|
||||||
|
export { createBusinessChatLink } from './methods/premium/create-business-chat-link.js'
|
||||||
|
export { editBusinessChatLink } from './methods/premium/edit-business-chat-link.js'
|
||||||
|
export { deleteBusinessChatLink } from './methods/premium/edit-business-chat-link.js'
|
||||||
export { getBoostStats } from './methods/premium/get-boost-stats.js'
|
export { getBoostStats } from './methods/premium/get-boost-stats.js'
|
||||||
export { getBoosts } from './methods/premium/get-boosts.js'
|
export { getBoosts } from './methods/premium/get-boosts.js'
|
||||||
|
export { getBusinessChatLinks } from './methods/premium/get-business-chat-links.js'
|
||||||
export { getMyBoostSlots } from './methods/premium/get-my-boost-slots.js'
|
export { getMyBoostSlots } from './methods/premium/get-my-boost-slots.js'
|
||||||
export { iterBoosters } from './methods/premium/iter-boosters.js'
|
export { iterBoosters } from './methods/premium/iter-boosters.js'
|
||||||
|
export { setBusinessIntro } from './methods/premium/set-business-intro.js'
|
||||||
|
export { setBusinessWorkHours } from './methods/premium/set-business-work-hours.js'
|
||||||
export { addStickerToSet } from './methods/stickers/add-sticker-to-set.js'
|
export { addStickerToSet } from './methods/stickers/add-sticker-to-set.js'
|
||||||
export { createStickerSet } from './methods/stickers/create-sticker-set.js'
|
export { createStickerSet } from './methods/stickers/create-sticker-set.js'
|
||||||
export { deleteStickerFromSet } from './methods/stickers/delete-sticker-from-set.js'
|
export { deleteStickerFromSet } from './methods/stickers/delete-sticker-from-set.js'
|
||||||
|
@ -245,6 +251,7 @@ export { resolveUser } from './methods/users/resolve-peer.js'
|
||||||
export { resolveChannel } from './methods/users/resolve-peer.js'
|
export { resolveChannel } from './methods/users/resolve-peer.js'
|
||||||
export { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
export { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
||||||
export { setGlobalTtl } from './methods/users/set-global-ttl.js'
|
export { setGlobalTtl } from './methods/users/set-global-ttl.js'
|
||||||
|
export { setMyBirthday } from './methods/users/set-my-birthday.js'
|
||||||
export { setMyEmojiStatus } from './methods/users/set-my-emoji-status.js'
|
export { setMyEmojiStatus } from './methods/users/set-my-emoji-status.js'
|
||||||
export { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
export { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
||||||
export { setMyUsername } from './methods/users/set-my-username.js'
|
export { setMyUsername } from './methods/users/set-my-username.js'
|
||||||
|
|
|
@ -26,6 +26,8 @@ import {
|
||||||
BotReactionCountUpdate,
|
BotReactionCountUpdate,
|
||||||
BotReactionUpdate,
|
BotReactionUpdate,
|
||||||
BotStoppedUpdate,
|
BotStoppedUpdate,
|
||||||
|
BusinessChatLink,
|
||||||
|
BusinessWorkHoursDay,
|
||||||
CallbackQuery,
|
CallbackQuery,
|
||||||
Chat,
|
Chat,
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
|
@ -52,6 +54,7 @@ import {
|
||||||
InputFileLike,
|
InputFileLike,
|
||||||
InputInlineResult,
|
InputInlineResult,
|
||||||
InputMediaLike,
|
InputMediaLike,
|
||||||
|
InputMediaSticker,
|
||||||
InputMessageId,
|
InputMessageId,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
InputPrivacyRule,
|
InputPrivacyRule,
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { ITelegramClient } from '../../client.types.js'
|
||||||
|
import { InputText } from '../../types/index.js'
|
||||||
|
import { BusinessChatLink } from '../../types/premium/business-chat-link.js'
|
||||||
|
import { _normalizeInputText } from '../misc/normalize-text.js'
|
||||||
|
|
||||||
|
// @available=user
|
||||||
|
/**
|
||||||
|
* Create a new business chat link
|
||||||
|
*
|
||||||
|
* @param text Text to be inserted into the message input
|
||||||
|
*/
|
||||||
|
export async function createBusinessChatLink(
|
||||||
|
client: ITelegramClient,
|
||||||
|
text: InputText,
|
||||||
|
params?: {
|
||||||
|
/** Custom title for the link */
|
||||||
|
title?: string
|
||||||
|
},
|
||||||
|
): Promise<BusinessChatLink> {
|
||||||
|
const [message, entities] = await _normalizeInputText(client, text)
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'account.createBusinessChatLink',
|
||||||
|
link: {
|
||||||
|
_: 'inputBusinessChatLink',
|
||||||
|
message,
|
||||||
|
entities,
|
||||||
|
title: params?.title,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return new BusinessChatLink(res)
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { assertTrue } from '../../../utils/type-assertions.js'
|
||||||
|
import { ITelegramClient } from '../../client.types.js'
|
||||||
|
import { InputText } from '../../types/index.js'
|
||||||
|
import { BusinessChatLink } from '../../types/premium/business-chat-link.js'
|
||||||
|
import { _normalizeInputText } from '../misc/normalize-text.js'
|
||||||
|
|
||||||
|
// @available=user
|
||||||
|
/**
|
||||||
|
* Edit an existing business chat link
|
||||||
|
*
|
||||||
|
* @param link The link to edit
|
||||||
|
*/
|
||||||
|
export async function editBusinessChatLink(
|
||||||
|
client: ITelegramClient,
|
||||||
|
link: string | BusinessChatLink,
|
||||||
|
params: {
|
||||||
|
/** Text to be inserted in the message input */
|
||||||
|
text: InputText
|
||||||
|
/** Custom title for the link */
|
||||||
|
title?: string
|
||||||
|
},
|
||||||
|
): Promise<BusinessChatLink> {
|
||||||
|
const [message, entities] = await _normalizeInputText(client, params.text)
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'account.editBusinessChatLink',
|
||||||
|
slug: link instanceof BusinessChatLink ? link.link : link,
|
||||||
|
link: {
|
||||||
|
_: 'inputBusinessChatLink',
|
||||||
|
message,
|
||||||
|
entities,
|
||||||
|
title: params?.title,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return new BusinessChatLink(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @available=user
|
||||||
|
/**
|
||||||
|
* Delete a business chat link
|
||||||
|
*
|
||||||
|
* @param link The link to delete
|
||||||
|
*/
|
||||||
|
export async function deleteBusinessChatLink(client: ITelegramClient, link: string | BusinessChatLink): Promise<void> {
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'account.deleteBusinessChatLink',
|
||||||
|
slug: typeof link === 'string' ? link : link.link,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertTrue('account.deleteBusinessChatLink', res)
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { ITelegramClient } from '../../client.types.js'
|
||||||
|
import { BusinessChatLink } from '../../types/premium/business-chat-link.js'
|
||||||
|
|
||||||
|
// @available=user
|
||||||
|
/**
|
||||||
|
* Get current user's business chat links
|
||||||
|
*/
|
||||||
|
export async function getBusinessChatLinks(client: ITelegramClient): Promise<BusinessChatLink[]> {
|
||||||
|
const res = await client.call({ _: 'account.getBusinessChatLinks' })
|
||||||
|
|
||||||
|
return res.links.map((x) => new BusinessChatLink(x))
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import { assertTrue, assertTypeIs } from '../../../utils/type-assertions.js'
|
||||||
|
import { ITelegramClient } from '../../client.types.js'
|
||||||
|
import { InputFileLike, InputMediaSticker } from '../../types/index.js'
|
||||||
|
import { _normalizeFileToDocument } from '../files/normalize-file-to-document.js'
|
||||||
|
import { _normalizeInputMedia } from '../files/normalize-input-media.js'
|
||||||
|
|
||||||
|
const isInputMediaSticker = (media: unknown): media is InputMediaSticker =>
|
||||||
|
typeof media === 'object' && media !== null && 'type' in media && media.type === 'sticker'
|
||||||
|
|
||||||
|
// @available=user
|
||||||
|
/**
|
||||||
|
* Set current user's business introduction.
|
||||||
|
*
|
||||||
|
* @param intro Introduction parameters, or `null` to remove
|
||||||
|
*/
|
||||||
|
export async function setBusinessIntro(
|
||||||
|
client: ITelegramClient,
|
||||||
|
intro: {
|
||||||
|
/**
|
||||||
|
* Title of the introduction
|
||||||
|
*/
|
||||||
|
title?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the introduction
|
||||||
|
*/
|
||||||
|
description?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sticker to show beneath the introduction
|
||||||
|
*/
|
||||||
|
sticker?: InputMediaSticker | InputFileLike | tl.TypeInputDocument
|
||||||
|
} | null,
|
||||||
|
): Promise<void> {
|
||||||
|
let tlIntro: tl.TypeInputBusinessIntro | undefined = undefined
|
||||||
|
|
||||||
|
if (intro) {
|
||||||
|
let sticker: tl.TypeInputDocument | undefined
|
||||||
|
|
||||||
|
if (intro.sticker) {
|
||||||
|
if (isInputMediaSticker(intro.sticker)) {
|
||||||
|
const media = await _normalizeInputMedia(client, intro.sticker, undefined, true)
|
||||||
|
|
||||||
|
assertTypeIs('_normalizeInputMedia', media, 'inputMediaDocument')
|
||||||
|
sticker = media.id
|
||||||
|
} else {
|
||||||
|
sticker = await _normalizeFileToDocument(client, intro.sticker, {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlIntro = {
|
||||||
|
_: 'inputBusinessIntro',
|
||||||
|
title: intro.title ?? '',
|
||||||
|
description: intro.description ?? '',
|
||||||
|
sticker,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'account.updateBusinessIntro',
|
||||||
|
intro: tlIntro,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertTrue('account.updateBusinessIntro', res)
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import { assertTrue } from '../../../utils/type-assertions.js'
|
||||||
|
import { ITelegramClient } from '../../client.types.js'
|
||||||
|
import { BusinessWorkHoursDay, businessWorkHoursDaysToRaw } from '../../types/premium/business-work-hours.js'
|
||||||
|
|
||||||
|
// @available=user
|
||||||
|
/**
|
||||||
|
* Set current user's business work hours.
|
||||||
|
*/
|
||||||
|
export async function setBusinessWorkHours(
|
||||||
|
client: ITelegramClient,
|
||||||
|
params:
|
||||||
|
| ({
|
||||||
|
/** Timezone in which the hours are defined */
|
||||||
|
timezone: string
|
||||||
|
} & (
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* Business work intervals, per-day (like available in {@link BusinessWorkHours.days})
|
||||||
|
*/
|
||||||
|
hours: ReadonlyArray<BusinessWorkHoursDay>
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
/** Business work intervals, raw intervals */
|
||||||
|
intervals: tl.TypeBusinessWeeklyOpen[]
|
||||||
|
}
|
||||||
|
))
|
||||||
|
| null,
|
||||||
|
): Promise<void> {
|
||||||
|
let businessWorkHours: tl.TypeBusinessWorkHours | undefined = undefined
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
let weeklyOpen: tl.TypeBusinessWeeklyOpen[]
|
||||||
|
|
||||||
|
if ('hours' in params) {
|
||||||
|
weeklyOpen = businessWorkHoursDaysToRaw(params.hours)
|
||||||
|
} else {
|
||||||
|
weeklyOpen = params.intervals
|
||||||
|
}
|
||||||
|
|
||||||
|
businessWorkHours = {
|
||||||
|
_: 'businessWorkHours',
|
||||||
|
timezoneId: params.timezone,
|
||||||
|
weeklyOpen,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'account.updateBusinessWorkHours',
|
||||||
|
businessWorkHours,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertTrue('account.updateBusinessWorkHours', res)
|
||||||
|
}
|
30
packages/core/src/highlevel/methods/users/set-my-birthday.ts
Normal file
30
packages/core/src/highlevel/methods/users/set-my-birthday.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { assertTrue } from '../../../utils/type-assertions.js'
|
||||||
|
import { ITelegramClient } from '../../client.types.js'
|
||||||
|
|
||||||
|
// @available=user
|
||||||
|
/**
|
||||||
|
* Set or remove current user's birthday.
|
||||||
|
*/
|
||||||
|
export async function setMyBirthday(
|
||||||
|
client: ITelegramClient,
|
||||||
|
birthday: {
|
||||||
|
/** Birthday day */
|
||||||
|
day: number
|
||||||
|
/** Birthday month */
|
||||||
|
month: number
|
||||||
|
/** Birthday year (optional) */
|
||||||
|
year?: number
|
||||||
|
} | null,
|
||||||
|
): Promise<void> {
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'account.updateBirthday',
|
||||||
|
birthday: birthday ?
|
||||||
|
{
|
||||||
|
_: 'birthday',
|
||||||
|
...birthday,
|
||||||
|
} :
|
||||||
|
undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertTrue('account.updateBirthday', res)
|
||||||
|
}
|
|
@ -372,7 +372,24 @@ export interface ActionPhotoSuggested {
|
||||||
photo: Photo
|
photo: Photo
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A peer was chosen by the user after clicking on a RequestPeer button */
|
/**
|
||||||
|
* A peer was chosen by the user after clicking on a RequestPeer button.
|
||||||
|
* The user-side version of {@link ActionPeerChosen}
|
||||||
|
*/
|
||||||
|
export interface ActionPeerSent {
|
||||||
|
readonly type: 'peer_sent'
|
||||||
|
|
||||||
|
/** ID of the button passed earlier by the bot */
|
||||||
|
buttonId: number
|
||||||
|
|
||||||
|
/** Brief information about the chosen peers */
|
||||||
|
peers: tl.TypeRequestedPeer[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A peer was chosen by the user after clicking on a RequestPeer button
|
||||||
|
* The bot-side version of {@link ActionPeerSent}
|
||||||
|
*/
|
||||||
export interface ActionPeerChosen {
|
export interface ActionPeerChosen {
|
||||||
readonly type: 'peer_chosen'
|
readonly type: 'peer_chosen'
|
||||||
|
|
||||||
|
@ -472,6 +489,7 @@ export type MessageAction =
|
||||||
| ActionWebviewDataReceived
|
| ActionWebviewDataReceived
|
||||||
| ActionPremiumGifted
|
| ActionPremiumGifted
|
||||||
| ActionPhotoSuggested
|
| ActionPhotoSuggested
|
||||||
|
| ActionPeerSent
|
||||||
| ActionPeerChosen
|
| ActionPeerChosen
|
||||||
| ActionWallpaperChanged
|
| ActionWallpaperChanged
|
||||||
| ActionGiftCode
|
| ActionGiftCode
|
||||||
|
@ -696,6 +714,12 @@ export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction):
|
||||||
type: 'photo_suggested',
|
type: 'photo_suggested',
|
||||||
photo: new Photo(act.photo as tl.RawPhoto),
|
photo: new Photo(act.photo as tl.RawPhoto),
|
||||||
}
|
}
|
||||||
|
case 'messageActionRequestedPeerSentMe':
|
||||||
|
return {
|
||||||
|
type: 'peer_sent',
|
||||||
|
buttonId: act.buttonId,
|
||||||
|
peers: act.peers,
|
||||||
|
}
|
||||||
case 'messageActionRequestedPeer':
|
case 'messageActionRequestedPeer':
|
||||||
return {
|
return {
|
||||||
type: 'peer_chosen',
|
type: 'peer_chosen',
|
||||||
|
|
|
@ -79,6 +79,14 @@ export class Message {
|
||||||
return this.raw._ === 'message' && this.raw.noforwards!
|
return this.raw._ === 'message' && this.raw.noforwards!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the message was sent by an implicit action, for example,
|
||||||
|
* as an away or a greeting business message, or as a scheduled message
|
||||||
|
*/
|
||||||
|
get isFromOffline(): boolean {
|
||||||
|
return this.raw._ === 'message' && this.raw.offline!
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiple media messages with the same grouped ID
|
* Multiple media messages with the same grouped ID
|
||||||
* indicate an album or media group
|
* indicate an album or media group
|
||||||
|
@ -126,6 +134,15 @@ export class Message {
|
||||||
return parsePeer(from, this._peers)
|
return parsePeer(from, this._peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of boosts applied to this {@link chat} by the sender
|
||||||
|
*/
|
||||||
|
get senderBoostCount(): number {
|
||||||
|
if (this.raw._ !== 'message') return 0
|
||||||
|
|
||||||
|
return this.raw.fromBoostsApplied ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conversation the message belongs to
|
* Conversation the message belongs to
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -138,6 +138,13 @@ export class StickerSet {
|
||||||
return this.brief.official!
|
return this.brief.official!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this sticker set was created by the current user
|
||||||
|
*/
|
||||||
|
get isCreator(): boolean {
|
||||||
|
return this.brief.creator!
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of the stickers in this set
|
* Type of the stickers in this set
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,8 +4,12 @@ import { MtTypeAssertionError } from '../../../types/errors.js'
|
||||||
import { makeInspectable } from '../../utils/inspectable.js'
|
import { makeInspectable } from '../../utils/inspectable.js'
|
||||||
import { memoizeGetters } from '../../utils/memoize.js'
|
import { memoizeGetters } from '../../utils/memoize.js'
|
||||||
import { Photo } from '../media/photo.js'
|
import { Photo } from '../media/photo.js'
|
||||||
|
import { StickerSet } from '../misc/sticker-set.js'
|
||||||
|
import { BusinessAccount } from '../premium/business-account.js'
|
||||||
import { Chat } from './chat.js'
|
import { Chat } from './chat.js'
|
||||||
|
import { ChatInviteLink } from './chat-invite-link.js'
|
||||||
import { ChatLocation } from './chat-location.js'
|
import { ChatLocation } from './chat-location.js'
|
||||||
|
import { PeersIndex } from './peers-index.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complete information about a particular chat.
|
* Complete information about a particular chat.
|
||||||
|
@ -20,32 +24,33 @@ export class FullChat extends Chat {
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
static _parse(full: tl.messages.RawChatFull | tl.users.TypeUserFull): FullChat {
|
static _parse(full: tl.messages.RawChatFull | tl.users.TypeUserFull): FullChat {
|
||||||
|
const peers = PeersIndex.from(full)
|
||||||
|
|
||||||
if (full._ === 'users.userFull') {
|
if (full._ === 'users.userFull') {
|
||||||
const user = full.users.find((it) => it.id === full.fullUser.id)
|
const { fullUser } = full
|
||||||
|
const user = peers.user(full.fullUser.id)
|
||||||
|
|
||||||
if (!user || user._ === 'userEmpty') {
|
if (!user || user._ === 'userEmpty') {
|
||||||
throw new MtTypeAssertionError('Chat._parseFull', 'user', user?._ ?? 'undefined')
|
throw new MtTypeAssertionError('Chat._parseFull', 'user', user?._ ?? 'undefined')
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FullChat(user, full.fullUser)
|
const ret = new FullChat(user, fullUser)
|
||||||
|
|
||||||
|
if (fullUser.personalChannelId) {
|
||||||
|
ret._linkedChat = new Chat(peers.chat(fullUser.personalChannelId))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullChat = full.fullChat
|
const { fullChat } = full
|
||||||
let chat: tl.TypeChat | undefined = undefined
|
|
||||||
let linked: tl.TypeChat | undefined = undefined
|
|
||||||
|
|
||||||
for (const c of full.chats) {
|
const ret = new FullChat(peers.chat(fullChat.id), fullChat)
|
||||||
if (fullChat.id === c.id) {
|
|
||||||
chat = c
|
if (fullChat._ === 'channelFull' && fullChat.linkedChatId) {
|
||||||
}
|
ret._linkedChat = new Chat(peers.chat(fullChat.linkedChatId))
|
||||||
if (fullChat._ === 'channelFull' && fullChat.linkedChatId === c.id) {
|
|
||||||
linked = c
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ret = new FullChat(chat!, fullChat)
|
|
||||||
ret._linkedChat = linked ? new Chat(linked) : undefined
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,15 +137,15 @@ export class FullChat extends Chat {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chat's permanent invite link, for groups, supergroups and channels.
|
* Chat's primary invite link, for groups, supergroups and channels.
|
||||||
*/
|
*/
|
||||||
get inviteLink(): string | null {
|
get inviteLink(): ChatInviteLink | null {
|
||||||
if (this.fullPeer && this.fullPeer._ !== 'userFull') {
|
if (this.fullPeer && this.fullPeer._ !== 'userFull') {
|
||||||
switch (this.fullPeer.exportedInvite?._) {
|
switch (this.fullPeer.exportedInvite?._) {
|
||||||
case 'chatInvitePublicJoinRequests':
|
case 'chatInvitePublicJoinRequests':
|
||||||
return null
|
return null
|
||||||
case 'chatInviteExported':
|
case 'chatInviteExported':
|
||||||
return this.fullPeer.exportedInvite.link
|
return new ChatInviteLink(this.fullPeer.exportedInvite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,10 +153,21 @@ export class FullChat extends Chat {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For supergroups, name of the group sticker set.
|
* For supergroups, information about the group sticker set.
|
||||||
*/
|
*/
|
||||||
get stickerSetName(): string | null {
|
get stickerSet(): StickerSet | null {
|
||||||
return this.fullPeer && this.fullPeer._ === 'channelFull' ? this.fullPeer.stickerset?.shortName ?? null : null
|
if (this.fullPeer?._ !== 'channelFull' || !this.fullPeer.stickerset) return null
|
||||||
|
|
||||||
|
return new StickerSet(this.fullPeer.stickerset)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For supergroups, information about the group emoji set.
|
||||||
|
*/
|
||||||
|
get emojiSet(): StickerSet | null {
|
||||||
|
if (this.fullPeer?._ !== 'channelFull' || !this.fullPeer.emojiset) return null
|
||||||
|
|
||||||
|
return new StickerSet(this.fullPeer.emojiset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,19 +177,40 @@ export class FullChat extends Chat {
|
||||||
return this.fullPeer && this.fullPeer._ === 'channelFull' ? this.fullPeer.canSetStickers ?? null : null
|
return this.fullPeer && this.fullPeer._ === 'channelFull' ? this.fullPeer.canSetStickers ?? null : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of boosts applied by the current user to this chat.
|
||||||
|
*/
|
||||||
|
get boostsApplied(): number {
|
||||||
|
if (!this.fullPeer || this.fullPeer._ !== 'channelFull') return 0
|
||||||
|
|
||||||
|
return this.fullPeer?.boostsApplied ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of boosts required for the user to be unrestricted in this chat.
|
||||||
|
*/
|
||||||
|
get boostsForUnrestrict(): number {
|
||||||
|
if (!this.fullPeer || this.fullPeer._ !== 'channelFull') return 0
|
||||||
|
|
||||||
|
return this.fullPeer?.boostsUnrestrict ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chat members count, for groups, supergroups and channels only.
|
* Chat members count, for groups, supergroups and channels only.
|
||||||
*/
|
*/
|
||||||
get membersCount(): number | null {
|
get membersCount(): number | null {
|
||||||
if (this.fullPeer && this.fullPeer._ !== 'userFull') {
|
switch (this.fullPeer._) {
|
||||||
if (this.fullPeer._ === 'chatFull' && this.fullPeer.participants._ === 'chatParticipants') {
|
case 'userFull':
|
||||||
return this.fullPeer.participants.participants.length
|
return null
|
||||||
} else if (this.fullPeer._ === 'channelFull') {
|
case 'chatFull':
|
||||||
return this.fullPeer.participantsCount ?? null
|
if (this.fullPeer.participants._ !== 'chatParticipants') {
|
||||||
}
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return this.fullPeer.participants.participants.length
|
||||||
|
case 'channelFull':
|
||||||
|
return this.fullPeer.participantsCount ?? null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,8 +226,10 @@ export class FullChat extends Chat {
|
||||||
|
|
||||||
private _linkedChat?: Chat
|
private _linkedChat?: Chat
|
||||||
/**
|
/**
|
||||||
* The linked discussion group (in case of channels)
|
* Information about a linked chat:
|
||||||
* or the linked channel (in case of supergroups).
|
* - for channels: the discussion group
|
||||||
|
* - for supergroups: the linked channel
|
||||||
|
* - for users: the personal channel
|
||||||
*/
|
*/
|
||||||
get linkedChat(): Chat | null {
|
get linkedChat(): Chat | null {
|
||||||
return this._linkedChat ?? null
|
return this._linkedChat ?? null
|
||||||
|
@ -202,7 +241,25 @@ export class FullChat extends Chat {
|
||||||
get ttlPeriod(): number | null {
|
get ttlPeriod(): number | null {
|
||||||
return this.fullPeer?.ttlPeriod ?? null
|
return this.fullPeer?.ttlPeriod ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is a business account, information about the business.
|
||||||
|
*/
|
||||||
|
get business(): BusinessAccount | null {
|
||||||
|
if (!this.fullPeer || this.fullPeer._ !== 'userFull') return null
|
||||||
|
|
||||||
|
return new BusinessAccount(this.fullPeer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memoizeGetters(FullChat, ['fullPhoto', 'personalPhoto', 'realPhoto', 'publicPhoto', 'location'])
|
memoizeGetters(FullChat, [
|
||||||
|
'fullPhoto',
|
||||||
|
'personalPhoto',
|
||||||
|
'realPhoto',
|
||||||
|
'publicPhoto',
|
||||||
|
'location',
|
||||||
|
'stickerSet',
|
||||||
|
'emojiSet',
|
||||||
|
'business',
|
||||||
|
])
|
||||||
makeInspectable(FullChat)
|
makeInspectable(FullChat)
|
||||||
|
|
|
@ -108,6 +108,14 @@ export class User {
|
||||||
return this.raw.bot!
|
return this.raw.bot!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this user is a bot that can be connected to a
|
||||||
|
* Telegram Business account to receive its messages
|
||||||
|
*/
|
||||||
|
get isBusinessBot(): boolean {
|
||||||
|
return this.raw.botBusiness!
|
||||||
|
}
|
||||||
|
|
||||||
/** Whether this user is a bot that has access to all messages */
|
/** Whether this user is a bot that has access to all messages */
|
||||||
get isBotWithHistory(): boolean {
|
get isBotWithHistory(): boolean {
|
||||||
return this.raw.botChatHistory!
|
return this.raw.botChatHistory!
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import { makeInspectable } from '../../utils/inspectable.js'
|
||||||
|
import { memoizeGetters } from '../../utils/memoize.js'
|
||||||
|
import { BusinessIntro } from './business-intro.js'
|
||||||
|
import { BusinessLocation } from './business-location.js'
|
||||||
|
import { BusinessWorkHours } from './business-work-hours.js'
|
||||||
|
|
||||||
|
/** Information about a business account */
|
||||||
|
export class BusinessAccount {
|
||||||
|
constructor(readonly info: tl.RawUserFull) {}
|
||||||
|
|
||||||
|
/** Introduction of the business account */
|
||||||
|
get intro(): BusinessIntro | null {
|
||||||
|
if (!this.info.businessIntro) return null
|
||||||
|
|
||||||
|
return new BusinessIntro(this.info.businessIntro)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Work hours of the business */
|
||||||
|
get workHours(): BusinessWorkHours | null {
|
||||||
|
if (!this.info.businessWorkHours) return null
|
||||||
|
|
||||||
|
return new BusinessWorkHours(this.info.businessWorkHours)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Location of the business */
|
||||||
|
get location(): BusinessLocation | null {
|
||||||
|
if (!this.info.businessLocation) return null
|
||||||
|
|
||||||
|
return new BusinessLocation(this.info.businessLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Information about a greeting message */
|
||||||
|
get greetingMessage(): tl.TypeBusinessGreetingMessage | null {
|
||||||
|
return this.info.businessGreetingMessage ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Information about an "away" message */
|
||||||
|
get awayMessage(): tl.TypeBusinessAwayMessage | null {
|
||||||
|
return this.info.businessAwayMessage ?? null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memoizeGetters(BusinessAccount, ['intro', 'workHours', 'location'])
|
||||||
|
makeInspectable(BusinessAccount)
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import { makeInspectable } from '../../utils/inspectable.js'
|
||||||
|
import { memoizeGetters } from '../../utils/memoize.js'
|
||||||
|
import { MessageEntity } from '../messages/message-entity.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A business chat link, i.e. a link to start a chat with a pre-filled message.
|
||||||
|
*/
|
||||||
|
export class BusinessChatLink {
|
||||||
|
constructor(readonly raw: tl.RawBusinessChatLink) {}
|
||||||
|
|
||||||
|
/** The link itself */
|
||||||
|
get link(): string {
|
||||||
|
return this.raw.link
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Text to be inserted into the message input */
|
||||||
|
get text(): string {
|
||||||
|
return this.raw.message
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Entities for the text */
|
||||||
|
get entities(): MessageEntity[] {
|
||||||
|
return this.raw.entities?.map((x) => new MessageEntity(x)) ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Custom title for the link */
|
||||||
|
get title(): string | null {
|
||||||
|
return this.raw.title ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Number of clicks on the link */
|
||||||
|
get clicks(): number {
|
||||||
|
return this.raw.views
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeInspectable(BusinessChatLink)
|
||||||
|
memoizeGetters(BusinessChatLink, ['entities'])
|
43
packages/core/src/highlevel/types/premium/business-intro.ts
Normal file
43
packages/core/src/highlevel/types/premium/business-intro.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import { makeInspectable } from '../../utils/inspectable.js'
|
||||||
|
import { memoizeGetters } from '../../utils/memoize.js'
|
||||||
|
import { parseDocument } from '../media/document-utils.js'
|
||||||
|
import { Sticker } from '../media/sticker.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about a "business intro" – text that is displayed
|
||||||
|
* when a user opens a chat with a business account for the first time.
|
||||||
|
*/
|
||||||
|
export class BusinessIntro {
|
||||||
|
constructor(readonly raw: tl.RawBusinessIntro) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Title of the intro.
|
||||||
|
*/
|
||||||
|
get title(): string {
|
||||||
|
return this.raw.title
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the intro.
|
||||||
|
*/
|
||||||
|
get description(): string {
|
||||||
|
return this.raw.description
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sticker of the intro.
|
||||||
|
*/
|
||||||
|
get sticker(): Sticker | null {
|
||||||
|
if (!this.raw.sticker || this.raw.sticker._ === 'documentEmpty') return null
|
||||||
|
|
||||||
|
const doc = parseDocument(this.raw.sticker)
|
||||||
|
if (doc.type !== 'sticker') return null
|
||||||
|
|
||||||
|
return doc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeInspectable(BusinessIntro)
|
||||||
|
memoizeGetters(BusinessIntro, ['sticker'])
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import { makeInspectable } from '../../utils/inspectable.js'
|
||||||
|
import { memoizeGetters } from '../../utils/memoize.js'
|
||||||
|
import { Location } from '../media/location.js'
|
||||||
|
|
||||||
|
/** Location of a business */
|
||||||
|
export class BusinessLocation {
|
||||||
|
constructor(readonly raw: tl.RawBusinessLocation) {}
|
||||||
|
|
||||||
|
/** Address of the business */
|
||||||
|
get address(): string {
|
||||||
|
return this.raw.address
|
||||||
|
}
|
||||||
|
|
||||||
|
get location(): Location | null {
|
||||||
|
if (!this.raw.geoPoint || this.raw.geoPoint._ === 'geoPointEmpty') return null
|
||||||
|
|
||||||
|
return new Location(this.raw.geoPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeInspectable(BusinessLocation)
|
||||||
|
memoizeGetters(BusinessLocation, ['location'])
|
|
@ -0,0 +1,228 @@
|
||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
|
import { createStub } from '@mtcute/test'
|
||||||
|
|
||||||
|
import { BusinessWorkHours, businessWorkHoursDaysToRaw } from './business-work-hours.js'
|
||||||
|
|
||||||
|
describe('BusinessWorkHours', () => {
|
||||||
|
describe('days', () => {
|
||||||
|
const mkHours = (intervals: [number, number][]) =>
|
||||||
|
createStub('businessWorkHours', {
|
||||||
|
weeklyOpen: intervals.map(([start, end]) =>
|
||||||
|
createStub('businessWeeklyOpen', {
|
||||||
|
startMinute: start,
|
||||||
|
endMinute: end,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle a single interval on Monday', () => {
|
||||||
|
const it = new BusinessWorkHours(mkHours([[0, 60]]))
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: false, intervals: [{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 0 }] },
|
||||||
|
{ day: 1, is24h: false, intervals: [] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle a single interval on Tuesday', () => {
|
||||||
|
const it = new BusinessWorkHours(mkHours([[1440, 1500]]))
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: false, intervals: [] },
|
||||||
|
{ day: 1, is24h: false, intervals: [{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 0 }] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle multiple intervals within a day', () => {
|
||||||
|
const it = new BusinessWorkHours(
|
||||||
|
mkHours([
|
||||||
|
[0, 60],
|
||||||
|
[120, 180],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{
|
||||||
|
day: 0,
|
||||||
|
is24h: false,
|
||||||
|
intervals: [
|
||||||
|
{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 0 },
|
||||||
|
{ startHour: 2, startMinute: 0, endHour: 3, endMinute: 0 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ day: 1, is24h: false, intervals: [] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle multiple intervals across different days', () => {
|
||||||
|
const it = new BusinessWorkHours(
|
||||||
|
mkHours([
|
||||||
|
[0, 60],
|
||||||
|
[25 * 60 + 30, 26 * 60 + 30],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: false, intervals: [{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 0 }] },
|
||||||
|
{ day: 1, is24h: false, intervals: [{ startHour: 1, startMinute: 30, endHour: 2, endMinute: 30 }] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle a single interval spanning multiple days', () => {
|
||||||
|
const it = new BusinessWorkHours(mkHours([[0, 1500]]))
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 1, is24h: false, intervals: [{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 0 }] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle a single 7-day interval', () => {
|
||||||
|
const it = new BusinessWorkHours(mkHours([[0, 7 * 24 * 60]]))
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 1, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 2, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 3, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 4, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 5, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 6, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle multiple intervals each spanning multiple days', () => {
|
||||||
|
const it = new BusinessWorkHours(
|
||||||
|
mkHours([
|
||||||
|
[0, 2 * 24 * 60],
|
||||||
|
[4 * 24 * 60, 6 * 24 * 60],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 1, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 5, is24h: true, intervals: [{ startHour: 0, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle overlapping intervals', () => {
|
||||||
|
const it = new BusinessWorkHours(
|
||||||
|
mkHours([
|
||||||
|
[0, 60],
|
||||||
|
[30, 90],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: false, intervals: [{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 30 }] },
|
||||||
|
{ day: 1, is24h: false, intervals: [] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle adjascent intervals', () => {
|
||||||
|
const it = new BusinessWorkHours(
|
||||||
|
mkHours([
|
||||||
|
[0, 60],
|
||||||
|
[60, 90],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{ day: 0, is24h: false, intervals: [{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 30 }] },
|
||||||
|
{ day: 1, is24h: false, intervals: [] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle magic 8th day', () => {
|
||||||
|
const it = new BusinessWorkHours(
|
||||||
|
mkHours([
|
||||||
|
// Mon 12:00 - 14:00
|
||||||
|
[12 * 60, 14 * 60],
|
||||||
|
// Sun 0:00 - Mon (next week) 2:00
|
||||||
|
[6 * 24 * 60 + 20 * 60, 7 * 24 * 60 + 2 * 60],
|
||||||
|
// Mon (next week) 3:00 - Mon (next week) 4:00
|
||||||
|
[7 * 24 * 60 + 3 * 60, 7 * 24 * 60 + 4 * 60],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(it.days).toEqual([
|
||||||
|
{
|
||||||
|
day: 0,
|
||||||
|
is24h: false,
|
||||||
|
intervals: [
|
||||||
|
{ startHour: 0, startMinute: 0, endHour: 2, endMinute: 0 },
|
||||||
|
{ startHour: 3, startMinute: 0, endHour: 4, endMinute: 0 },
|
||||||
|
{ startHour: 12, startMinute: 0, endHour: 14, endMinute: 0 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ day: 1, is24h: false, intervals: [] },
|
||||||
|
{ day: 2, is24h: false, intervals: [] },
|
||||||
|
{ day: 3, is24h: false, intervals: [] },
|
||||||
|
{ day: 4, is24h: false, intervals: [] },
|
||||||
|
{ day: 5, is24h: false, intervals: [] },
|
||||||
|
{ day: 6, is24h: false, intervals: [{ startHour: 20, startMinute: 0, endHour: 24, endMinute: 0 }] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('businessWorkHoursDaysToRaw', () => {
|
||||||
|
it('should handle 24-hour days', () => {
|
||||||
|
expect(businessWorkHoursDaysToRaw([{ day: 0, is24h: true, intervals: [] }])).toEqual([
|
||||||
|
{ _: 'businessWeeklyOpen', startMinute: 0, endMinute: 1440 },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle intervals', () => {
|
||||||
|
expect(
|
||||||
|
businessWorkHoursDaysToRaw([
|
||||||
|
{ day: 0, is24h: false, intervals: [{ startHour: 0, startMinute: 0, endHour: 1, endMinute: 0 }] },
|
||||||
|
{ day: 3, is24h: false, intervals: [{ startHour: 12, startMinute: 0, endHour: 14, endMinute: 0 }] },
|
||||||
|
]),
|
||||||
|
).toEqual([
|
||||||
|
{ _: 'businessWeeklyOpen', startMinute: 0, endMinute: 60 },
|
||||||
|
{ _: 'businessWeeklyOpen', startMinute: 3 * 24 * 60 + 12 * 60, endMinute: 3 * 24 * 60 + 14 * 60 },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
191
packages/core/src/highlevel/types/premium/business-work-hours.ts
Normal file
191
packages/core/src/highlevel/types/premium/business-work-hours.ts
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import { MtArgumentError } from '../../../types/errors.js'
|
||||||
|
import { makeInspectable } from '../../utils/inspectable.js'
|
||||||
|
import { memoizeGetters } from '../../utils/memoize.js'
|
||||||
|
|
||||||
|
export interface BusinessWorkHoursInterval {
|
||||||
|
/** Start hour of the interval (0-23) */
|
||||||
|
readonly startHour: number
|
||||||
|
/** Start minute of the interval (0-59) */
|
||||||
|
readonly startMinute: number
|
||||||
|
|
||||||
|
/** End hour of the interval (0-23) */
|
||||||
|
readonly endHour: number
|
||||||
|
/** End minute of the interval (0-59) */
|
||||||
|
readonly endMinute: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BusinessWorkHoursDay {
|
||||||
|
/** Day of the week, 0-6, where 0 is Monday and 6 is Sunday */
|
||||||
|
readonly day: number
|
||||||
|
|
||||||
|
/** Whether this day is open 24 hours */
|
||||||
|
readonly is24h: boolean
|
||||||
|
|
||||||
|
/** Open intervals for this day */
|
||||||
|
readonly intervals: BusinessWorkHoursInterval[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const DAYS_IN_WEEK = 7
|
||||||
|
const MINUTES_IN_DAY = 24 * 60
|
||||||
|
|
||||||
|
export function businessWorkHoursDaysToRaw(day: ReadonlyArray<BusinessWorkHoursDay>): tl.TypeBusinessWeeklyOpen[] {
|
||||||
|
const res: tl.TypeBusinessWeeklyOpen[] = []
|
||||||
|
|
||||||
|
for (const d of day) {
|
||||||
|
const dayStart = d.day * MINUTES_IN_DAY
|
||||||
|
|
||||||
|
if (d.is24h) {
|
||||||
|
res.push({
|
||||||
|
_: 'businessWeeklyOpen',
|
||||||
|
startMinute: dayStart,
|
||||||
|
endMinute: dayStart + MINUTES_IN_DAY,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const interval of d.intervals) {
|
||||||
|
const start = dayStart + interval.startHour * 60 + interval.startMinute
|
||||||
|
const end = dayStart + interval.endHour * 60 + interval.endMinute
|
||||||
|
|
||||||
|
if (start >= end) {
|
||||||
|
throw new MtArgumentError('startMinute >= endMinute')
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push({
|
||||||
|
_: 'businessWeeklyOpen',
|
||||||
|
startMinute: start,
|
||||||
|
endMinute: end,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about business work hours.
|
||||||
|
*/
|
||||||
|
export class BusinessWorkHours {
|
||||||
|
constructor(readonly raw: tl.RawBusinessWorkHours) {}
|
||||||
|
|
||||||
|
/** Whether the business is open right now */
|
||||||
|
get isOpenNow(): boolean {
|
||||||
|
return this.raw.openNow!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier of the time zone in which the {@link hours} are defined,
|
||||||
|
* in the IANA format.
|
||||||
|
*/
|
||||||
|
get timezoneId(): string {
|
||||||
|
return this.raw.timezoneId
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Raw "open" intervals */
|
||||||
|
get intervals(): tl.TypeBusinessWeeklyOpen[] {
|
||||||
|
return this.raw.weeklyOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parsed business hours intervals per week day.
|
||||||
|
*
|
||||||
|
* @returns Array of 7 elements, each representing a day of the week (starting from Monday = 0)
|
||||||
|
*/
|
||||||
|
get days(): ReadonlyArray<BusinessWorkHoursDay> {
|
||||||
|
const days: BusinessWorkHoursDay[] = Array.from({ length: DAYS_IN_WEEK }, (_, i) => ({
|
||||||
|
day: i,
|
||||||
|
is24h: false,
|
||||||
|
intervals: [],
|
||||||
|
}))
|
||||||
|
|
||||||
|
// sort intervals by start time
|
||||||
|
const sorted = [...this.raw.weeklyOpen].sort((a, b) => a.startMinute - b.startMinute)
|
||||||
|
|
||||||
|
// merge overlapping/consecutive intervals
|
||||||
|
for (let i = 1; i < sorted.length; i++) {
|
||||||
|
const prev = sorted[i - 1]
|
||||||
|
const cur = sorted[i]
|
||||||
|
|
||||||
|
if (prev.endMinute >= cur.startMinute) {
|
||||||
|
prev.endMinute = cur.endMinute
|
||||||
|
sorted.splice(i, 1)
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mondayPrepend: BusinessWorkHoursInterval[] = []
|
||||||
|
|
||||||
|
// process intervals
|
||||||
|
for (const interval of sorted) {
|
||||||
|
if (interval.startMinute > interval.endMinute) {
|
||||||
|
throw new MtArgumentError('startMinute is greater than endMinute')
|
||||||
|
}
|
||||||
|
|
||||||
|
const startDay = Math.floor(interval.startMinute / MINUTES_IN_DAY)
|
||||||
|
const endDay = Math.floor(interval.endMinute / MINUTES_IN_DAY)
|
||||||
|
|
||||||
|
if (endDay > DAYS_IN_WEEK + 1) {
|
||||||
|
throw new MtArgumentError('interval spans more than a week')
|
||||||
|
}
|
||||||
|
|
||||||
|
for (
|
||||||
|
let day = startDay, dayStart = startDay * MINUTES_IN_DAY;
|
||||||
|
day <= endDay;
|
||||||
|
day++, dayStart += MINUTES_IN_DAY
|
||||||
|
) {
|
||||||
|
const startWithin = Math.max(interval.startMinute, dayStart) - dayStart
|
||||||
|
const endWithin = Math.min(interval.endMinute, dayStart + MINUTES_IN_DAY) - dayStart
|
||||||
|
|
||||||
|
const startHour = Math.floor(startWithin / 60)
|
||||||
|
const startMinute = startWithin % 60
|
||||||
|
const endHour = Math.floor(endWithin / 60)
|
||||||
|
const endMinute = endWithin % 60
|
||||||
|
|
||||||
|
if (startHour === 0 && startMinute === 0 && endHour === 0 && endMinute === 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj: BusinessWorkHoursInterval = {
|
||||||
|
startHour,
|
||||||
|
startMinute,
|
||||||
|
endHour,
|
||||||
|
endMinute,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (day === DAYS_IN_WEEK) {
|
||||||
|
// prepend to Monday
|
||||||
|
mondayPrepend.push(obj)
|
||||||
|
} else {
|
||||||
|
days[day].intervals.push(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mondayPrepend.length > 0) {
|
||||||
|
// we do this like this to keep everything sorted
|
||||||
|
days[0].intervals.unshift(...mondayPrepend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up 24h days
|
||||||
|
for (const day of days) {
|
||||||
|
if (day.intervals.length !== 1) continue
|
||||||
|
const interval = day.intervals[0]
|
||||||
|
|
||||||
|
if (
|
||||||
|
interval.startHour === 0 &&
|
||||||
|
interval.startMinute === 0 &&
|
||||||
|
((interval.endHour === 24 && interval.endMinute === 0) ||
|
||||||
|
(interval.endHour === 23 && interval.endMinute === 59))
|
||||||
|
) {
|
||||||
|
(day as tl.Mutable<BusinessWorkHoursDay>).is24h = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return days
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeInspectable(BusinessWorkHours, undefined, ['intervals'])
|
||||||
|
memoizeGetters(BusinessWorkHours, ['days'])
|
|
@ -1,3 +1,7 @@
|
||||||
export * from './boost.js'
|
export * from './boost.js'
|
||||||
export * from './boost-slot.js'
|
export * from './boost-slot.js'
|
||||||
export * from './boost-stats.js'
|
export * from './boost-stats.js'
|
||||||
|
export * from './business-account.js'
|
||||||
|
export * from './business-chat-link.js'
|
||||||
|
export * from './business-intro.js'
|
||||||
|
export * from './business-work-hours.js'
|
||||||
|
|
Loading…
Reference in a new issue