Telegram

Язык поисковых запросов

Документация: v0.28.0

Все поля, операторы, пресеты и ограничения поиска сообщений Telegram: правила дат, регулярные выражения и JSON-ответ для скриптов и агентов.

Справочник по запросам tg messages search, tg messages stats и сохранённых поисков. Повседневные примеры — на странице Поиск сообщений.

Язык — строгое подмножество синтаксиса запросов Apache Lucene: слова, фразы, AND/OR/NOT, группы, поля, диапазоны, ограниченные подстановочные знаки и регулярные выражения. Полный справочник (на русском) содержит сгенерированные таблицы полей, операторов, пресетов и лимитов, а также выполняемые примеры; техническая спецификация описывает грамматику и компилятор.

Операторы

ОператорПримерЗначение
словаinvoice paidоба слова
фраза"invoice paid"слова в этом порядке
AND, &&alpha AND betaоба
OR, ||alpha OR betaлюбое из двух
NOT, !, -alpha NOT betaпервое без второго
++alpha OR betaalpha обязательно, beta необязательно
группа(alpha OR beta) gammaскобки задают порядок
группа поляfrom:(alice OR bob)поле применяется к каждому значению
диапазонdate:[2026-01-01 TO 2026-02-01}[ ] включают, { } исключают, * — открытая граница
сравнениеsize>10MB, date>=7dоткрытый диапазон
подстановкаinvo*, te?t* — любые символы, ? — один
регулярное выражениеtext:/pass(port)?/ограниченное регулярное выражение Lucene

alpha OR beta gamma означает (alpha OR beta) AND gamma; alpha OR beta AND gamma означает alpha OR (beta AND gamma). Для ясности используйте скобки. Строчные and, or, not — обычные слова. Запрос только из NOT ничего не находит: добавьте положительное условие, например kind:group NOT preset:secret. Нечёткий поиск ~, поиск по близости, усиление и интервалы отклоняются с ошибкой, а не игнорируются.

Поля

ПолеЧто находитПример
textслова сообщения (поле по умолчанию)text:invoice
bodyвесь исходный текст с учётом регистраbody:/.*invoice.*/
fromотправителя по имени, @username или идентификатору; me — это выfrom:"Alice Synthetic"
chatчат по названию, @username или идентификаторуchat:"Book club"
dateвремя отправкиdate:today, date:7d, date:[2026-01-01 TO 2026-02-01}
kindвид чата: private, group, channel, saved, bot, service, unknownkind:private
hasattachment, link, file, photo, image, video, audio, voice, sticker, contact, location, pollhas:file
topicодну тему форума; нужен один чатchat:"Book club" AND topic:42
inкакие аккаунты: провайдер или botsin:bots
presetтекст, похожий на секрет или контактные данныеpreset:secret
contentпроиндексированный текст вложенийcontent:invoice
filenameполное имя прикреплённого файлаfilename:*.pdf
mimeтип прикреплённого файла; значение без / сравнивается с первой частьюmime:image
sizeразмер прикреплённого файла в байтах или в KB/MB/GB по 1024size>10MB
tagваша локальная метка на сообщении, его чате или отправителеtag:work

Имена полей чувствительны к регистру. Неизвестное поле, значение или сочетание — ошибка, а не пустой ответ и не обычный текст. Имя, неизвестное архиву, в Telegram не ищется.

kind:bot выбирает чат с ботом; in:bots выбирает архивы аккаунтов tg bot. topic: требует ровно одного чата в chat: или --chat, поскольку номера тем в разных группах повторяются. filename, mime и size подходят сообщению, если подходит хотя бы один из его файлов. / начинает регулярное выражение, поэтому полный тип заключайте в кавычки: mime:"application/pdf".

Пресеты

ПресетКандидат — это
passwordподпись пароля, за которой следует значение
codeподпись кода подтверждения и 4–8 цифр
api-keyподпись ключа API и значение
secretподпись пароля, секрета, токена или ключа API и значение
card13–19 цифр, возможно с пробелами или дефисами
bankзначение в формате IBAN
passportзначение с подписью «паспорт» или российский формат 4+6 цифр
phoneмеждународный телефон, начинающийся с плюса
emailадрес электронной почты
telegram-linkссылка t.me или telegram.me
urlссылка HTTP(S)
contactвложение-контакт, либо адрес почты или телефон
locationвложение-место или ссылка geo:

Пресет сообщает о кандидате по его виду. Он не проверяет пароль, карту или документ и может совпасть с чем-то безобидным. Не удаляйте и не пересылайте сообщения автоматически на основании пресета.

Даты

--timezone принимает часовой пояс IANA, например Europe/Madrid; без него используется пояс компьютера, и он возвращается в ответе. Дата без времени — целый календарный день. Включающая верхняя граница охватывает весь этот день, исключающая — не включает его; день перевода часов может длиться 23 или 25 часов.

date:today и date:yesterday — календарные дни. date:7d означает от 7 дней назад до текущего момента (также 30m, 2h); date>=7d и date:[30d TO 7d} работают в сравнениях и диапазонах и отсчитываются от момента запуска запроса. Точное время заключайте в кавычки, с секундами и смещением: date>="2026-01-01T10:00:00+02:00".

Слова, подстановки и регулярные выражения

Перед индексацией и поиском текст нормализуется: нижний регистр, без диакритических знаков. Побочный эффект: некоторые разные слова становятся одинаковыми, например año и ano. Регулярные выражения и подстановки в text: нормализуются так же.

text:/pay/ находит целое слово pay, но не payment. body:/pay/ находит только сообщение, весь текст которого — pay, с учётом регистра; чтобы найти его в любом месте, используйте body:/.*pay.*/. Это синтаксис регулярных выражений Lucene, без проверок окружения JavaScript, обратных ссылок, якорей и флагов.

В большом архиве короткий префикс вроде a* может развернуться больше чем в 10 000 слов и будет отклонён; удлините его. Длинные запросы, глубокая вложенность, большие шаблоны и медленный перебор отклоняются с query_limit, а не обрезаются: сузьте чат, даты или шаблон.

Ответ

--json возвращает { items, page, limit, hasMore, corrections, completeness, wordsReady, query, coverage }, даже если совпадений нет. --jsonl выдаёт потоком только элементы.

  • query — версия языка, часовой пояс и использованный порядок.
  • coverage — в каких аккаунтах и чатах искали. lastSyncedAt — самое раннее время, когда чат из области поиска загружался через store fetch; null, если какой-то чат не загружался ни разу. inventoryComplete означает, что каждый аккаунт в области поиска хотя бы раз перечислил все свои чаты; полную историю это не обещает.
  • completeness — для каждого чата: доходит ли сохранённая история до начала и есть ли в ней пробелы.
  • wordsReady — готов ли словарный индекс. Пока он false, запрос со словами завершается ошибкой index_not_ready и называет команду, которая его достроит, — tg store migrate; запрос без слов выполняется.
  • hasMore относится к странице, а не к тому, есть ли ещё сообщения в Telegram.

Ошибка указывает место проблемы в запросе и даёт подсказку.

В MCP

tg_messages_search принимает запрос как text или как версионированное синтаксическое дерево в ast (не оба сразу); language выбирает lucene или legacy, timezone — часовой пояс календаря. chat принимает идентификатор или сохранённое название; source, newest, context и limit работают как параметры команды; saved запускает сохранённый поиск. История запросов следует настройке сервера: tg mcp --no-record или record со значением false исключает его вызовы. Ответ содержит те же поля, что и --json. tg_messages_stats считает по тем же запросам.

Прежние режимы

tg messages search 'from:alice after:7d invoice -draft' --language legacy --json
tg messages search --regex 'invoice\s+\d+' --json

--language legacy сохраняет прежние фильтры и исправление опечаток. --regex — отдельный режим: регулярное выражение JavaScript без учёта регистра по всему тексту, в изолированном рабочем потоке с ограничениями по времени и размеру. --regex нельзя сочетать с --language lucene.

ПрежнийСтрогий
after:2026-01-01date:[2026-01-01 TO *]
before:2026-02-01date:[* TO 2026-02-01}
after:7ddate:7d
автоматический поиск по префиксу и исправление опечатокinvo* явно; опечатки — только в --language legacy

--thread следует по сохранённому графу ответов; в messages context он заменяет соседние по времени сообщения. По умолчанию — 8 переходов, 50 сообщений, 65 536 байт и один день вокруг каждого совпадения. Это меняют --thread-hops, --thread-messages, --thread-bytes, --thread-within. Без графа используется контекст по времени; устаревшие связи отмечаются и не обходятся.

По умолчанию поиск читает локальный архив. --sync-first явно загружает новые сообщения перед поиском и ничего не отмечает прочитанным: не больше 5 чатов, 500 сообщений и 30 секунд. Эти границы меняют --max-chats, --max-messages, --sync-time. При неудачном или неполном обновлении остаются локальные результаты с устаревшим охватом и сведениями об обновлении.

MCP использует thread, thread_hops, thread_messages, thread_bytes, thread_within и sync_first. sync_first доступен только при messages.sync-first: allow. Обычный messages_context с offline: true читает сохранённые сообщения.