2025-03-22 08:47:19 +00:00
|
|
|
|
from sqlalchemy import desc, select, text
|
2022-12-01 17:32:09 +00:00
|
|
|
|
|
2024-08-12 08:00:01 +00:00
|
|
|
|
from cache.cache import (
|
2025-03-22 06:31:53 +00:00
|
|
|
|
cache_topic,
|
2025-03-22 08:47:19 +00:00
|
|
|
|
cached_query,
|
2024-08-12 08:00:01 +00:00
|
|
|
|
get_cached_topic_authors,
|
|
|
|
|
get_cached_topic_by_slug,
|
|
|
|
|
get_cached_topic_followers,
|
2025-04-10 15:39:31 +00:00
|
|
|
|
invalidate_cache_by_prefix
|
2024-08-12 08:00:01 +00:00
|
|
|
|
)
|
2023-12-17 20:30:20 +00:00
|
|
|
|
from orm.author import Author
|
2025-03-22 08:47:19 +00:00
|
|
|
|
from orm.topic import Topic
|
2024-04-09 08:30:20 +00:00
|
|
|
|
from resolvers.stat import get_with_stat
|
2023-10-23 14:47:11 +00:00
|
|
|
|
from services.auth import login_required
|
2023-10-05 18:46:18 +00:00
|
|
|
|
from services.db import local_session
|
2025-03-22 06:31:53 +00:00
|
|
|
|
from services.redis import redis
|
2024-04-08 07:38:58 +00:00
|
|
|
|
from services.schema import mutation, query
|
2024-08-12 08:00:01 +00:00
|
|
|
|
from utils.logger import root_logger as logger
|
2024-01-25 19:41:27 +00:00
|
|
|
|
|
|
|
|
|
|
2025-03-22 06:31:53 +00:00
|
|
|
|
# Вспомогательная функция для получения всех тем без статистики
|
|
|
|
|
async def get_all_topics():
|
|
|
|
|
"""
|
|
|
|
|
Получает все темы без статистики.
|
|
|
|
|
Используется для случаев, когда нужен полный список тем без дополнительной информации.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
list: Список всех тем без статистики
|
|
|
|
|
"""
|
2025-03-22 08:47:19 +00:00
|
|
|
|
cache_key = "topics:all:basic"
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
2025-03-22 08:47:19 +00:00
|
|
|
|
# Функция для получения всех тем из БД
|
|
|
|
|
async def fetch_all_topics():
|
|
|
|
|
logger.debug("Получаем список всех тем из БД и кешируем результат")
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
2025-03-22 08:47:19 +00:00
|
|
|
|
with local_session() as session:
|
|
|
|
|
# Запрос на получение базовой информации о темах
|
|
|
|
|
topics_query = select(Topic)
|
|
|
|
|
topics = session.execute(topics_query).scalars().all()
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
2025-03-22 08:47:19 +00:00
|
|
|
|
# Преобразуем темы в словари
|
|
|
|
|
return [topic.dict() for topic in topics]
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
2025-03-22 08:47:19 +00:00
|
|
|
|
# Используем универсальную функцию для кеширования запросов
|
|
|
|
|
return await cached_query(cache_key, fetch_all_topics)
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Вспомогательная функция для получения тем со статистикой с пагинацией
|
2025-03-22 08:47:19 +00:00
|
|
|
|
async def get_topics_with_stats(limit=100, offset=0, community_id=None, by=None):
|
2025-03-22 06:31:53 +00:00
|
|
|
|
"""
|
|
|
|
|
Получает темы со статистикой с пагинацией.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
limit: Максимальное количество возвращаемых тем
|
|
|
|
|
offset: Смещение для пагинации
|
|
|
|
|
community_id: Опциональный ID сообщества для фильтрации
|
2025-03-22 08:47:19 +00:00
|
|
|
|
by: Опциональный параметр сортировки
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
list: Список тем с их статистикой
|
|
|
|
|
"""
|
2025-03-22 08:47:19 +00:00
|
|
|
|
# Формируем ключ кеша с помощью универсальной функции
|
|
|
|
|
cache_key = f"topics:stats:limit={limit}:offset={offset}:community_id={community_id}"
|
|
|
|
|
|
|
|
|
|
# Функция для получения тем из БД
|
|
|
|
|
async def fetch_topics_with_stats():
|
|
|
|
|
logger.debug(f"Выполняем запрос на получение тем со статистикой: limit={limit}, offset={offset}")
|
|
|
|
|
|
|
|
|
|
with local_session() as session:
|
|
|
|
|
# Базовый запрос для получения тем
|
|
|
|
|
base_query = select(Topic)
|
|
|
|
|
|
|
|
|
|
# Добавляем фильтр по сообществу, если указан
|
|
|
|
|
if community_id:
|
|
|
|
|
base_query = base_query.where(Topic.community == community_id)
|
|
|
|
|
|
|
|
|
|
# Применяем сортировку на основе параметра by
|
|
|
|
|
if by:
|
|
|
|
|
if isinstance(by, dict):
|
|
|
|
|
# Обработка словаря параметров сортировки
|
|
|
|
|
for field, direction in by.items():
|
|
|
|
|
column = getattr(Topic, field, None)
|
|
|
|
|
if column:
|
|
|
|
|
if direction.lower() == "desc":
|
|
|
|
|
base_query = base_query.order_by(desc(column))
|
|
|
|
|
else:
|
|
|
|
|
base_query = base_query.order_by(column)
|
|
|
|
|
elif by == "popular":
|
|
|
|
|
# Сортировка по популярности (количеству публикаций)
|
|
|
|
|
# Примечание: это требует дополнительного запроса или подзапроса
|
|
|
|
|
base_query = base_query.order_by(
|
|
|
|
|
desc(Topic.id)
|
|
|
|
|
) # Временно, нужно заменить на proper implementation
|
|
|
|
|
else:
|
|
|
|
|
# По умолчанию сортируем по ID в обратном порядке
|
|
|
|
|
base_query = base_query.order_by(desc(Topic.id))
|
|
|
|
|
else:
|
|
|
|
|
# По умолчанию сортируем по ID в обратном порядке
|
|
|
|
|
base_query = base_query.order_by(desc(Topic.id))
|
|
|
|
|
|
|
|
|
|
# Применяем лимит и смещение
|
|
|
|
|
base_query = base_query.limit(limit).offset(offset)
|
|
|
|
|
|
|
|
|
|
# Получаем темы
|
|
|
|
|
topics = session.execute(base_query).scalars().all()
|
|
|
|
|
topic_ids = [topic.id for topic in topics]
|
|
|
|
|
|
|
|
|
|
if not topic_ids:
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
# Запрос на получение статистики по публикациям для выбранных тем
|
|
|
|
|
shouts_stats_query = f"""
|
|
|
|
|
SELECT st.topic, COUNT(DISTINCT s.id) as shouts_count
|
|
|
|
|
FROM shout_topic st
|
|
|
|
|
JOIN shout s ON st.shout = s.id AND s.deleted_at IS NULL
|
|
|
|
|
WHERE st.topic IN ({",".join(map(str, topic_ids))})
|
|
|
|
|
GROUP BY st.topic
|
|
|
|
|
"""
|
|
|
|
|
shouts_stats = {row[0]: row[1] for row in session.execute(text(shouts_stats_query))}
|
|
|
|
|
|
|
|
|
|
# Запрос на получение статистики по подписчикам для выбранных тем
|
|
|
|
|
followers_stats_query = f"""
|
|
|
|
|
SELECT topic, COUNT(DISTINCT follower) as followers_count
|
|
|
|
|
FROM topic_followers
|
|
|
|
|
WHERE topic IN ({",".join(map(str, topic_ids))})
|
|
|
|
|
GROUP BY topic
|
|
|
|
|
"""
|
|
|
|
|
followers_stats = {row[0]: row[1] for row in session.execute(text(followers_stats_query))}
|
2025-04-10 15:39:31 +00:00
|
|
|
|
|
|
|
|
|
# Запрос на получение статистики авторов для выбранных тем
|
|
|
|
|
authors_stats_query = f"""
|
|
|
|
|
SELECT st.topic, COUNT(DISTINCT sa.author) as authors_count
|
|
|
|
|
FROM shout_topic st
|
|
|
|
|
JOIN shout s ON st.shout = s.id AND s.deleted_at IS NULL AND s.published_at IS NOT NULL
|
|
|
|
|
JOIN shout_author sa ON sa.shout = s.id
|
|
|
|
|
WHERE st.topic IN ({",".join(map(str, topic_ids))})
|
|
|
|
|
GROUP BY st.topic
|
|
|
|
|
"""
|
|
|
|
|
authors_stats = {row[0]: row[1] for row in session.execute(text(authors_stats_query))}
|
2025-03-22 08:47:19 +00:00
|
|
|
|
|
2025-04-10 16:14:27 +00:00
|
|
|
|
# Запрос на получение статистики комментариев для выбранных тем
|
|
|
|
|
comments_stats_query = f"""
|
|
|
|
|
SELECT st.topic, COUNT(DISTINCT r.id) as comments_count
|
|
|
|
|
FROM shout_topic st
|
|
|
|
|
JOIN shout s ON st.shout = s.id AND s.deleted_at IS NULL AND s.published_at IS NOT NULL
|
|
|
|
|
JOIN reaction r ON r.shout = s.id
|
|
|
|
|
WHERE st.topic IN ({",".join(map(str, topic_ids))})
|
|
|
|
|
GROUP BY st.topic
|
|
|
|
|
"""
|
|
|
|
|
comments_stats = {row[0]: row[1] for row in session.execute(text(comments_stats_query))}
|
|
|
|
|
|
|
|
|
|
|
2025-03-22 08:47:19 +00:00
|
|
|
|
# Формируем результат с добавлением статистики
|
|
|
|
|
result = []
|
|
|
|
|
for topic in topics:
|
|
|
|
|
topic_dict = topic.dict()
|
|
|
|
|
topic_dict["stat"] = {
|
|
|
|
|
"shouts": shouts_stats.get(topic.id, 0),
|
|
|
|
|
"followers": followers_stats.get(topic.id, 0),
|
2025-04-10 16:14:27 +00:00
|
|
|
|
"authors": authors_stats.get(topic.id, 0),
|
|
|
|
|
"comments": comments_stats.get(topic.id, 0)
|
2025-03-22 08:47:19 +00:00
|
|
|
|
}
|
|
|
|
|
result.append(topic_dict)
|
|
|
|
|
|
|
|
|
|
# Кешируем каждую тему отдельно для использования в других функциях
|
|
|
|
|
await cache_topic(topic_dict)
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
# Используем универсальную функцию для кеширования запросов
|
|
|
|
|
return await cached_query(cache_key, fetch_topics_with_stats)
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Функция для инвалидации кеша тем
|
2025-03-22 08:47:19 +00:00
|
|
|
|
async def invalidate_topics_cache(topic_id=None):
|
2025-03-22 06:31:53 +00:00
|
|
|
|
"""
|
2025-03-22 08:47:19 +00:00
|
|
|
|
Инвалидирует кеши тем при изменении данных.
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
2025-03-22 08:47:19 +00:00
|
|
|
|
Args:
|
|
|
|
|
topic_id: Опциональный ID темы для точечной инвалидации.
|
|
|
|
|
Если не указан, инвалидируются все кеши тем.
|
|
|
|
|
"""
|
|
|
|
|
if topic_id:
|
|
|
|
|
# Точечная инвалидация конкретной темы
|
|
|
|
|
logger.debug(f"Инвалидация кеша для темы #{topic_id}")
|
|
|
|
|
specific_keys = [
|
|
|
|
|
f"topic:id:{topic_id}",
|
|
|
|
|
f"topic:authors:{topic_id}",
|
|
|
|
|
f"topic:followers:{topic_id}",
|
|
|
|
|
f"topic_shouts_{topic_id}",
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Получаем slug темы, если есть
|
|
|
|
|
with local_session() as session:
|
|
|
|
|
topic = session.query(Topic).filter(Topic.id == topic_id).first()
|
|
|
|
|
if topic and topic.slug:
|
|
|
|
|
specific_keys.append(f"topic:slug:{topic.slug}")
|
|
|
|
|
|
|
|
|
|
# Удаляем конкретные ключи
|
|
|
|
|
for key in specific_keys:
|
|
|
|
|
try:
|
|
|
|
|
await redis.execute("DEL", key)
|
|
|
|
|
logger.debug(f"Удален ключ кеша {key}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Ошибка при удалении ключа {key}: {e}")
|
|
|
|
|
|
|
|
|
|
# Также ищем и удаляем ключи коллекций, содержащих данные об этой теме
|
|
|
|
|
collection_keys = await redis.execute("KEYS", "topics:stats:*")
|
|
|
|
|
if collection_keys:
|
|
|
|
|
await redis.execute("DEL", *collection_keys)
|
|
|
|
|
logger.debug(f"Удалено {len(collection_keys)} коллекционных ключей тем")
|
|
|
|
|
else:
|
|
|
|
|
# Общая инвалидация всех кешей тем
|
|
|
|
|
logger.debug("Полная инвалидация кеша тем")
|
|
|
|
|
await invalidate_cache_by_prefix("topics")
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Запрос на получение всех тем
|
2024-04-17 15:32:23 +00:00
|
|
|
|
@query.field("get_topics_all")
|
2025-03-22 06:31:53 +00:00
|
|
|
|
async def get_topics_all(_, _info):
|
|
|
|
|
"""
|
|
|
|
|
Получает список всех тем без статистики.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
list: Список всех тем
|
|
|
|
|
"""
|
|
|
|
|
return await get_all_topics()
|
2024-03-12 14:26:52 +00:00
|
|
|
|
|
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Запрос на получение тем по сообществу
|
2024-04-17 15:32:23 +00:00
|
|
|
|
@query.field("get_topics_by_community")
|
2025-03-22 08:47:19 +00:00
|
|
|
|
async def get_topics_by_community(_, _info, community_id: int, limit=100, offset=0, by=None):
|
2025-03-22 06:31:53 +00:00
|
|
|
|
"""
|
|
|
|
|
Получает список тем, принадлежащих указанному сообществу с пагинацией и статистикой.
|
2024-03-12 14:26:52 +00:00
|
|
|
|
|
2025-03-22 06:31:53 +00:00
|
|
|
|
Args:
|
|
|
|
|
community_id: ID сообщества
|
|
|
|
|
limit: Максимальное количество возвращаемых тем
|
|
|
|
|
offset: Смещение для пагинации
|
2025-03-22 08:47:19 +00:00
|
|
|
|
by: Опциональные параметры сортировки
|
2024-03-12 14:26:52 +00:00
|
|
|
|
|
2025-03-22 06:31:53 +00:00
|
|
|
|
Returns:
|
|
|
|
|
list: Список тем с их статистикой
|
|
|
|
|
"""
|
2025-03-22 08:47:19 +00:00
|
|
|
|
return await get_topics_with_stats(limit, offset, community_id, by)
|
2024-03-12 14:26:52 +00:00
|
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Запрос на получение тем по автору
|
2024-04-17 15:32:23 +00:00
|
|
|
|
@query.field("get_topics_by_author")
|
|
|
|
|
async def get_topics_by_author(_, _info, author_id=0, slug="", user=""):
|
2024-05-18 11:15:05 +00:00
|
|
|
|
topics_by_author_query = select(Topic)
|
2023-11-28 07:53:48 +00:00
|
|
|
|
if author_id:
|
2024-05-30 04:12:00 +00:00
|
|
|
|
topics_by_author_query = topics_by_author_query.join(Author).where(Author.id == author_id)
|
2023-11-28 07:53:48 +00:00
|
|
|
|
elif slug:
|
2024-05-30 04:12:00 +00:00
|
|
|
|
topics_by_author_query = topics_by_author_query.join(Author).where(Author.slug == slug)
|
2023-11-28 07:53:48 +00:00
|
|
|
|
elif user:
|
2024-05-30 04:12:00 +00:00
|
|
|
|
topics_by_author_query = topics_by_author_query.join(Author).where(Author.user == user)
|
2022-11-28 20:29:02 +00:00
|
|
|
|
|
2024-05-18 11:15:05 +00:00
|
|
|
|
return get_with_stat(topics_by_author_query)
|
2022-09-03 10:50:14 +00:00
|
|
|
|
|
2021-10-28 10:42:34 +00:00
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Запрос на получение одной темы по её slug
|
2024-04-17 15:32:23 +00:00
|
|
|
|
@query.field("get_topic")
|
2024-06-05 14:45:55 +00:00
|
|
|
|
async def get_topic(_, _info, slug: str):
|
2024-06-06 06:23:45 +00:00
|
|
|
|
topic = await get_cached_topic_by_slug(slug, get_with_stat)
|
2024-06-05 14:45:55 +00:00
|
|
|
|
if topic:
|
2024-04-09 16:38:02 +00:00
|
|
|
|
return topic
|
2022-11-10 06:51:40 +00:00
|
|
|
|
|
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Мутация для создания новой темы
|
2024-04-17 15:32:23 +00:00
|
|
|
|
@mutation.field("create_topic")
|
2021-12-12 15:29:51 +00:00
|
|
|
|
@login_required
|
2025-02-11 09:00:35 +00:00
|
|
|
|
async def create_topic(_, _info, topic_input):
|
2022-09-22 10:31:44 +00:00
|
|
|
|
with local_session() as session:
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# TODO: проверить права пользователя на создание темы для конкретного сообщества
|
|
|
|
|
# и разрешение на создание
|
2025-02-11 09:00:35 +00:00
|
|
|
|
new_topic = Topic(**topic_input)
|
2022-09-22 10:31:44 +00:00
|
|
|
|
session.add(new_topic)
|
|
|
|
|
session.commit()
|
2022-11-28 20:29:02 +00:00
|
|
|
|
|
2025-03-22 06:31:53 +00:00
|
|
|
|
# Инвалидируем кеш всех тем
|
|
|
|
|
await invalidate_topics_cache()
|
|
|
|
|
|
2024-04-17 15:32:23 +00:00
|
|
|
|
return {"topic": new_topic}
|
2021-12-12 15:29:51 +00:00
|
|
|
|
|
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Мутация для обновления темы
|
2024-04-17 15:32:23 +00:00
|
|
|
|
@mutation.field("update_topic")
|
2021-12-12 15:29:51 +00:00
|
|
|
|
@login_required
|
2025-02-11 09:00:35 +00:00
|
|
|
|
async def update_topic(_, _info, topic_input):
|
|
|
|
|
slug = topic_input["slug"]
|
2022-09-18 14:29:21 +00:00
|
|
|
|
with local_session() as session:
|
|
|
|
|
topic = session.query(Topic).filter(Topic.slug == slug).first()
|
|
|
|
|
if not topic:
|
2024-04-17 15:32:23 +00:00
|
|
|
|
return {"error": "topic not found"}
|
2022-09-18 14:29:21 +00:00
|
|
|
|
else:
|
2025-03-22 08:47:19 +00:00
|
|
|
|
old_slug = topic.slug
|
2025-02-11 09:00:35 +00:00
|
|
|
|
Topic.update(topic, topic_input)
|
2023-11-22 16:38:39 +00:00
|
|
|
|
session.add(topic)
|
2022-09-18 14:29:21 +00:00
|
|
|
|
session.commit()
|
2022-11-28 20:29:02 +00:00
|
|
|
|
|
2025-03-22 08:47:19 +00:00
|
|
|
|
# Инвалидируем кеш только для этой конкретной темы
|
|
|
|
|
await invalidate_topics_cache(topic.id)
|
|
|
|
|
|
|
|
|
|
# Если slug изменился, удаляем старый ключ
|
|
|
|
|
if old_slug != topic.slug:
|
|
|
|
|
await redis.execute("DEL", f"topic:slug:{old_slug}")
|
|
|
|
|
logger.debug(f"Удален ключ кеша для старого slug: {old_slug}")
|
2025-03-22 06:31:53 +00:00
|
|
|
|
|
2024-04-17 15:32:23 +00:00
|
|
|
|
return {"topic": topic}
|
2021-12-12 15:29:51 +00:00
|
|
|
|
|
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Мутация для удаления темы
|
2024-04-17 15:32:23 +00:00
|
|
|
|
@mutation.field("delete_topic")
|
2023-11-28 07:53:48 +00:00
|
|
|
|
@login_required
|
2024-02-26 09:14:08 +00:00
|
|
|
|
async def delete_topic(_, info, slug: str):
|
2024-04-17 15:32:23 +00:00
|
|
|
|
user_id = info.context["user_id"]
|
2023-11-28 07:53:48 +00:00
|
|
|
|
with local_session() as session:
|
|
|
|
|
t: Topic = session.query(Topic).filter(Topic.slug == slug).first()
|
|
|
|
|
if not t:
|
2024-04-17 15:32:23 +00:00
|
|
|
|
return {"error": "invalid topic slug"}
|
2023-11-28 07:53:48 +00:00
|
|
|
|
author = session.query(Author).filter(Author.user == user_id).first()
|
|
|
|
|
if author:
|
|
|
|
|
if t.created_by != author.id:
|
2024-04-17 15:32:23 +00:00
|
|
|
|
return {"error": "access denied"}
|
2023-11-28 07:53:48 +00:00
|
|
|
|
|
|
|
|
|
session.delete(t)
|
|
|
|
|
session.commit()
|
|
|
|
|
|
2025-03-22 06:31:53 +00:00
|
|
|
|
# Инвалидируем кеш всех тем и конкретной темы
|
|
|
|
|
await invalidate_topics_cache()
|
|
|
|
|
await redis.execute("DEL", f"topic:slug:{slug}")
|
|
|
|
|
await redis.execute("DEL", f"topic:id:{t.id}")
|
|
|
|
|
|
2023-11-28 07:53:48 +00:00
|
|
|
|
return {}
|
2024-04-17 15:32:23 +00:00
|
|
|
|
return {"error": "access denied"}
|
2023-11-28 07:53:48 +00:00
|
|
|
|
|
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Запрос на получение подписчиков темы
|
2024-05-20 22:40:57 +00:00
|
|
|
|
@query.field("get_topic_followers")
|
|
|
|
|
async def get_topic_followers(_, _info, slug: str):
|
|
|
|
|
logger.debug(f"getting followers for @{slug}")
|
2024-06-06 06:23:45 +00:00
|
|
|
|
topic = await get_cached_topic_by_slug(slug, get_with_stat)
|
2024-06-05 14:45:55 +00:00
|
|
|
|
topic_id = topic.id if isinstance(topic, Topic) else topic.get("id")
|
2024-05-20 22:40:57 +00:00
|
|
|
|
followers = await get_cached_topic_followers(topic_id)
|
|
|
|
|
return followers
|
|
|
|
|
|
|
|
|
|
|
2024-08-07 14:45:22 +00:00
|
|
|
|
# Запрос на получение авторов темы
|
2024-05-20 22:40:57 +00:00
|
|
|
|
@query.field("get_topic_authors")
|
|
|
|
|
async def get_topic_authors(_, _info, slug: str):
|
|
|
|
|
logger.debug(f"getting authors for @{slug}")
|
2024-06-06 06:23:45 +00:00
|
|
|
|
topic = await get_cached_topic_by_slug(slug, get_with_stat)
|
2024-06-05 14:45:55 +00:00
|
|
|
|
topic_id = topic.id if isinstance(topic, Topic) else topic.get("id")
|
|
|
|
|
authors = await get_cached_topic_authors(topic_id)
|
2024-05-20 22:40:57 +00:00
|
|
|
|
return authors
|