feat(core): searchHashtag/iterHashtag methods
This commit is contained in:
parent
260de0db7f
commit
260e87a5f8
3 changed files with 173 additions and 0 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'
|
||||||
|
|
116
packages/core/src/highlevel/methods/messages/search-hashtag.ts
Normal file
116
packages/core/src/highlevel/methods/messages/search-hashtag.ts
Normal 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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue