205 lines
5.7 KiB
TypeScript

import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs';
import type { ApiChat, ApiReaction } from '../../types';
import {
API_GENERAL_ID_LIMIT,
REACTION_LIST_LIMIT,
RECENT_REACTIONS_LIMIT,
TOP_REACTIONS_LIMIT,
} from '../../../config';
import { split } from '../../../util/iteratees';
import { buildApiChatFromPreview } from '../apiBuilders/chats';
import { buildApiAvailableReaction, buildApiReaction, buildMessagePeerReaction } from '../apiBuilders/reactions';
import { buildApiUser } from '../apiBuilders/users';
import { buildInputPeer, buildInputReaction } from '../gramjsBuilders';
import { addEntitiesToLocalDb } from '../helpers';
import localDb from '../localDb';
import { invokeRequest } from './client';
export function sendWatchingEmojiInteraction({
chat,
emoticon,
}: {
chat: ApiChat; emoticon: string;
}) {
return invokeRequest(new GramJs.messages.SetTyping({
peer: buildInputPeer(chat.id, chat.accessHash),
action: new GramJs.SendMessageEmojiInteractionSeen({
emoticon,
}),
}), {
abortControllerChatId: chat.id,
});
}
export function sendEmojiInteraction({
chat,
emoticon,
messageId,
timestamps,
}: {
chat: ApiChat; messageId: number; emoticon: string; timestamps: number[];
}) {
return invokeRequest(new GramJs.messages.SetTyping({
peer: buildInputPeer(chat.id, chat.accessHash),
action: new GramJs.SendMessageEmojiInteraction({
emoticon,
msgId: messageId,
interaction: new GramJs.DataJSON({
data: JSON.stringify({
v: 1,
a: timestamps.map((t: number) => ({
t,
i: 1,
})),
}),
}),
}),
}), {
abortControllerChatId: chat.id,
});
}
export async function getAvailableReactions() {
const result = await invokeRequest(new GramJs.messages.GetAvailableReactions({}));
if (!result || result instanceof GramJs.messages.AvailableReactionsNotModified) {
return undefined;
}
result.reactions.forEach((reaction) => {
if (reaction.staticIcon instanceof GramJs.Document) {
localDb.documents[String(reaction.staticIcon.id)] = reaction.staticIcon;
}
if (reaction.selectAnimation instanceof GramJs.Document) {
localDb.documents[String(reaction.selectAnimation.id)] = reaction.selectAnimation;
}
if (reaction.aroundAnimation instanceof GramJs.Document) {
localDb.documents[String(reaction.aroundAnimation.id)] = reaction.aroundAnimation;
}
if (reaction.appearAnimation instanceof GramJs.Document) {
localDb.documents[String(reaction.appearAnimation.id)] = reaction.appearAnimation;
}
if (reaction.centerIcon instanceof GramJs.Document) {
localDb.documents[String(reaction.centerIcon.id)] = reaction.centerIcon;
}
});
return result.reactions.map(buildApiAvailableReaction);
}
export function sendReaction({
chat, messageId, reactions, shouldAddToRecent,
}: {
chat: ApiChat;
messageId: number;
reactions?: ApiReaction[];
shouldAddToRecent?: boolean;
}) {
return invokeRequest(new GramJs.messages.SendReaction({
reaction: reactions?.map((r) => buildInputReaction(r)),
peer: buildInputPeer(chat.id, chat.accessHash),
msgId: messageId,
...(shouldAddToRecent && { addToRecent: true }),
}), {
shouldReturnTrue: true,
shouldThrow: true,
});
}
export function fetchMessageReactions({
ids, chat,
}: {
ids: number[]; chat: ApiChat;
}) {
const chunks = split(ids, API_GENERAL_ID_LIMIT);
chunks.forEach((chunkIds) => {
invokeRequest(new GramJs.messages.GetMessagesReactions({
id: chunkIds,
peer: buildInputPeer(chat.id, chat.accessHash),
}), {
shouldReturnTrue: true,
abortControllerChatId: chat.id,
});
});
}
export async function fetchMessageReactionsList({
chat, messageId, reaction, offset,
}: {
chat: ApiChat; messageId: number; reaction?: ApiReaction; offset?: string;
}) {
const result = await invokeRequest(new GramJs.messages.GetMessageReactionsList({
peer: buildInputPeer(chat.id, chat.accessHash),
id: messageId,
...(reaction && { reaction: buildInputReaction(reaction) }),
limit: REACTION_LIST_LIMIT,
...(offset && { offset }),
}));
if (!result) {
return undefined;
}
addEntitiesToLocalDb(result.users);
addEntitiesToLocalDb(result.chats);
const { nextOffset, reactions, count } = result;
return {
users: result.users.map(buildApiUser).filter(Boolean),
chats: result.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean),
nextOffset,
reactions: reactions.map(buildMessagePeerReaction).filter(Boolean),
count,
};
}
export function setDefaultReaction({
reaction,
}: {
reaction: ApiReaction;
}) {
return invokeRequest(new GramJs.messages.SetDefaultReaction({
reaction: buildInputReaction(reaction),
}));
}
export async function fetchTopReactions({ hash = '0' }: { hash?: string }) {
const result = await invokeRequest(new GramJs.messages.GetTopReactions({
limit: TOP_REACTIONS_LIMIT,
hash: BigInt(hash),
}));
if (!result || result instanceof GramJs.messages.ReactionsNotModified) {
return undefined;
}
return {
hash: String(result.hash),
reactions: result.reactions.map(buildApiReaction).filter(Boolean),
};
}
export async function fetchRecentReactions({ hash = '0' }: { hash?: string }) {
const result = await invokeRequest(new GramJs.messages.GetRecentReactions({
limit: RECENT_REACTIONS_LIMIT,
hash: BigInt(hash),
}));
if (!result || result instanceof GramJs.messages.ReactionsNotModified) {
return undefined;
}
return {
hash: String(result.hash),
reactions: result.reactions.map(buildApiReaction).filter(Boolean),
};
}
export function clearRecentReactions() {
return invokeRequest(new GramJs.messages.ClearRecentReactions());
}