feat(core): searchHashtag/iterHashtag methods

This commit is contained in:
alina 🌸 2024-06-01 16:03:53 +03:00
parent 260de0db7f
commit 260e87a5f8
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
3 changed files with 173 additions and 0 deletions

View file

@ -151,6 +151,7 @@ import { pinMessage } from './methods/messages/pin-message.js'
import { readHistory } from './methods/messages/read-history.js' import { readHistory } from './methods/messages/read-history.js'
import { readReactions } from './methods/messages/read-reactions.js' import { readReactions } from './methods/messages/read-reactions.js'
import { searchGlobal, SearchGlobalOffset } from './methods/messages/search-global.js' import { searchGlobal, SearchGlobalOffset } from './methods/messages/search-global.js'
import { iterSearchHashtag, searchHashtag, SearchHashtagOffset } from './methods/messages/search-hashtag.js'
import { searchMessages, SearchMessagesOffset } from './methods/messages/search-messages.js' import { searchMessages, SearchMessagesOffset } from './methods/messages/search-messages.js'
import { answerMedia, answerMediaGroup, answerText } from './methods/messages/send-answer.js' import { answerMedia, answerMediaGroup, answerText } from './methods/messages/send-answer.js'
import { commentMedia, commentMediaGroup, commentText } from './methods/messages/send-comment.js' import { commentMedia, commentMediaGroup, commentText } from './methods/messages/send-comment.js'
@ -3687,6 +3688,53 @@ export interface TelegramClient extends ITelegramClient {
*/ */
onlyChannels?: boolean onlyChannels?: boolean
}): Promise<ArrayPaginated<Message, SearchGlobalOffset>> }): Promise<ArrayPaginated<Message, SearchGlobalOffset>>
/**
* Perform a global hashtag search, across the entire Telegram
*
* **Available**: 👤 users only
*
* @param hashtag Hashtag to search for
* @param params Additional parameters
*/
searchHashtag(
hashtag: string,
params?: {
/** Offset for the search */
offset?: SearchHashtagOffset
/** Limit the number of results */
limit?: number
},
): Promise<ArrayPaginated<Message, SearchHashtagOffset>>
/**
* Perform a global hashtag search, across the entire Telegram
*
* Iterable version of {@link searchHashtag}
*
* **Available**: both users and bots
*
* @param hashtag Hashtag to search for
* @param params Additional parameters
*/
iterSearchHashtag(
hashtag: string,
params?: Parameters<typeof searchHashtag>[2] & {
/**
* Limits the number of messages to be retrieved.
*
* @default `Infinity`, i.e. all messages are returned
*/
limit?: number
/**
* Chunk size, which will be passed as `limit` parameter
* for `messages.search`. Usually you shouldn't care about this.
*
* @default 100
*/
chunkSize?: number
},
): AsyncIterableIterator<Message>
/** /**
* Search for messages inside a specific chat * Search for messages inside a specific chat
* *
@ -5916,6 +5964,12 @@ TelegramClient.prototype.readReactions = function (...args) {
TelegramClient.prototype.searchGlobal = function (...args) { TelegramClient.prototype.searchGlobal = function (...args) {
return searchGlobal(this._client, ...args) return searchGlobal(this._client, ...args)
} }
TelegramClient.prototype.searchHashtag = function (...args) {
return searchHashtag(this._client, ...args)
}
TelegramClient.prototype.iterSearchHashtag = function (...args) {
return iterSearchHashtag(this._client, ...args)
}
TelegramClient.prototype.searchMessages = function (...args) { TelegramClient.prototype.searchMessages = function (...args) {
return searchMessages(this._client, ...args) return searchMessages(this._client, ...args)
} }

View file

@ -153,6 +153,9 @@ export { readHistory } from './methods/messages/read-history.js'
export { readReactions } from './methods/messages/read-reactions.js' export { readReactions } from './methods/messages/read-reactions.js'
export type { SearchGlobalOffset } from './methods/messages/search-global.js' export type { SearchGlobalOffset } from './methods/messages/search-global.js'
export { searchGlobal } from './methods/messages/search-global.js' export { searchGlobal } from './methods/messages/search-global.js'
export type { SearchHashtagOffset } from './methods/messages/search-hashtag.js'
export { searchHashtag } from './methods/messages/search-hashtag.js'
export { iterSearchHashtag } from './methods/messages/search-hashtag.js'
export type { SearchMessagesOffset } from './methods/messages/search-messages.js' export type { SearchMessagesOffset } from './methods/messages/search-messages.js'
export { searchMessages } from './methods/messages/search-messages.js' export { searchMessages } from './methods/messages/search-messages.js'
export { answerText } from './methods/messages/send-answer.js' export { answerText } from './methods/messages/send-answer.js'

View file

@ -0,0 +1,116 @@
import { tl } from '@mtcute/tl'
import { assertTypeIsNot } from '../../../utils/type-assertions.js'
import { ITelegramClient } from '../../client.types.js'
import { Message, PeersIndex } from '../../types/index.js'
import { ArrayPaginated } from '../../types/utils.js'
import { makeArrayPaginated } from '../../utils/misc-utils.js'
// @exported
export interface SearchHashtagOffset {
rate: number
peer: tl.TypeInputPeer
id: number
}
const defaultOffset: SearchHashtagOffset = {
rate: 0,
peer: { _: 'inputPeerEmpty' },
id: 0,
}
// @available=user
/**
* Perform a global hashtag search, across the entire Telegram
*
* @param hashtag Hashtag to search for
* @param params Additional parameters
*/
export async function searchHashtag(
client: ITelegramClient,
hashtag: string,
params?: {
/** Offset for the search */
offset?: SearchHashtagOffset
/** Limit the number of results */
limit?: number
},
): Promise<ArrayPaginated<Message, SearchHashtagOffset>> {
const { offset: { rate: offsetRate, peer: offsetPeer, id: offsetId } = defaultOffset, limit = 100 } = params ?? {}
const res = await client.call({
_: 'channels.searchPosts',
hashtag,
offsetId,
offsetRate,
offsetPeer,
limit,
})
assertTypeIsNot('searchHashtag', res, 'messages.messagesNotModified')
const peers = PeersIndex.from(res)
const msgs = res.messages.filter((msg) => msg._ !== 'messageEmpty').map((msg) => new Message(msg, peers))
const last = msgs[msgs.length - 1]
const next = last ?
{
rate: (res as tl.messages.RawMessagesSlice).nextRate ?? last.raw.date,
peer: last.chat.inputPeer,
id: last.id,
} :
undefined
return makeArrayPaginated(msgs, (res as tl.messages.RawMessagesSlice).count ?? msgs.length, next)
}
/**
* Perform a global hashtag search, across the entire Telegram
*
* Iterable version of {@link searchHashtag}
*
* @param hashtag Hashtag to search for
* @param params Additional parameters
*/
export async function* iterSearchHashtag(
client: ITelegramClient,
hashtag: string,
params?: Parameters<typeof searchHashtag>[2] & {
/**
* Limits the number of messages to be retrieved.
*
* @default `Infinity`, i.e. all messages are returned
*/
limit?: number
/**
* Chunk size, which will be passed as `limit` parameter
* for `messages.search`. Usually you shouldn't care about this.
*
* @default 100
*/
chunkSize?: number
},
): AsyncIterableIterator<Message> {
if (!params) params = {}
const { limit = Infinity, chunkSize = 100 } = params
let { offset } = params
let current = 0
for (;;) {
const res = await searchHashtag(client, hashtag, {
offset,
limit: Math.min(chunkSize, limit - current),
})
if (!res.length) return
for (const msg of res) {
yield msg
if (++current >= limit) return
}
if (!res.next) return
offset = res.next
}
}