def get_latest_messages(group_name: str, count: int = 10) -> list[dict]:
"""
Получить заданное количество последних сообщений из указанной группы.
Возвращает список словарей с полями: Msg-Num, Message-ID, Subject, Date, Name, Mail.
Сообщения строго отсортированы от самых новых к старым.
This commit is contained in:
1 parent
8d36a62ca2
commit
8b4659cffb
1 file changed
+66
@@ -362,6 +362,72 @@ def save_text_to_file(filename: str, content: str) -> str:
|
|||||||
return f"ERROR: {str(e)}"
|
return f"ERROR: {str(e)}"
|
||||||
|
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def get_latest_messages(group_name: str, count: int = 10) -> list[dict]:
|
||||||
|
"""
|
||||||
|
Получить заданное количество последних сообщений из указанной группы.
|
||||||
|
|
||||||
|
Возвращает список словарей с полями: Msg-Num, Message-ID, Subject, Date, Name, Mail.
|
||||||
|
Сообщения строго отсортированы от самых новых к старым.
|
||||||
|
"""
|
||||||
|
from email.utils import parseaddr
|
||||||
|
|
||||||
|
try:
|
||||||
|
latest_messages = []
|
||||||
|
with nntplib.NNTP(NNTP_SERVER, port=PORT, timeout=15) as s:
|
||||||
|
# Получаем информацию о группе и номера сообщений
|
||||||
|
resp, total_count, first, last, name = s.group(group_name)
|
||||||
|
first_num = int(first)
|
||||||
|
last_num = int(last)
|
||||||
|
|
||||||
|
if first_num > last_num or total_count == 0:
|
||||||
|
return []
|
||||||
|
|
||||||
|
# Берем диапазон с запасом, чтобы гарантированно набрать count живых сообщений
|
||||||
|
# (на случай, если часть постов между first и last были удалены)
|
||||||
|
start_msg = max(first_num, last_num - (count * 2) + 1)
|
||||||
|
|
||||||
|
# Получаем овервью (заголовки) сообщений в выбранном диапазоне
|
||||||
|
resp, overviews = s.over((str(start_msg), str(last_num)))
|
||||||
|
|
||||||
|
# СТРОГАЯ СОРТИРОВКА: переводим ключи в int и сортируем по убыванию (от новых к старым)
|
||||||
|
sorted_overviews = sorted(overviews, key=lambda x: int(x[0]), reverse=True)
|
||||||
|
|
||||||
|
# Обходим сообщения уже в гарантированно правильном порядке
|
||||||
|
for msg_num, over in sorted_overviews:
|
||||||
|
# Извлекаем message-id из овервью или генерируем запасной
|
||||||
|
raw_msg_id = over.get('message-id', f"<{msg_num}@{NNTP_SERVER}>")
|
||||||
|
|
||||||
|
raw_author = over.get('from', '')
|
||||||
|
raw_subject = over.get('subject', '')
|
||||||
|
raw_date = over.get('date', '')
|
||||||
|
|
||||||
|
# Декодируем MIME-заголовки с помощью существующих функций проекта
|
||||||
|
author = decode_mime_header(raw_author)
|
||||||
|
subject = decode_mime_header(raw_subject)
|
||||||
|
date = decode_mime_header(raw_date)
|
||||||
|
|
||||||
|
# Разделяем From на Имя и Почту
|
||||||
|
name_part, mail_part = parseaddr(author)
|
||||||
|
|
||||||
|
latest_messages.append({
|
||||||
|
"Msg-Num": str(msg_num), # Локальный порядковый номер в группе
|
||||||
|
"Message-ID": raw_msg_id, # Глобальный уникальный идентификатор
|
||||||
|
"Subject": subject if subject else "[Без темы]",
|
||||||
|
"Date": date,
|
||||||
|
"Name": name_part if name_part else "[Без имени]",
|
||||||
|
"Mail": mail_part if mail_part else "[Без почты]"
|
||||||
|
})
|
||||||
|
|
||||||
|
# Прерываем цикл, как только набрали нужное количество
|
||||||
|
if len(latest_messages) >= count:
|
||||||
|
break
|
||||||
|
|
||||||
|
return latest_messages
|
||||||
|
except Exception as e:
|
||||||
|
return [{"error": f"Ошибка NNTP при получении последних сообщений: {e}"}]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Для современного пакета MCPServer (MCP v2.x)
|
# Для современного пакета MCPServer (MCP v2.x)
|
||||||
|
|||||||
Reference in new issue
Block a user