161 lines
5.0 KiB
Python
161 lines
5.0 KiB
Python
from sqlalchemy import and_, distinct, func, join, select
|
|
|
|
from orm.author import Author
|
|
from orm.shout import Shout, ShoutAuthor, ShoutTopic
|
|
from orm.topic import Topic
|
|
from resolvers.stat import get_with_stat
|
|
from services.auth import login_required
|
|
from services.cache import get_cached_topic_authors, get_cached_topic_followers
|
|
from services.db import local_session
|
|
from services.logger import root_logger as logger
|
|
from services.memorycache import cache_region
|
|
from services.schema import mutation, query
|
|
|
|
|
|
@query.field("get_topics_all")
|
|
def get_topics_all(_, _info):
|
|
cache_key = "get_topics_all"
|
|
|
|
@cache_region.cache_on_arguments(cache_key)
|
|
def _get_topics_all():
|
|
topics_query = select(Topic)
|
|
return get_with_stat(topics_query)
|
|
|
|
return _get_topics_all()
|
|
|
|
|
|
@query.field("get_topics_by_community")
|
|
def get_topics_by_community(_, _info, community_id: int):
|
|
cache_key = f"get_topics_by_community_{community_id}"
|
|
|
|
@cache_region.cache_on_arguments(cache_key)
|
|
def _get_topics_by_community():
|
|
topics_by_community_query = select(Topic).where(Topic.community == community_id)
|
|
return get_with_stat(topics_by_community_query)
|
|
|
|
return _get_topics_by_community()
|
|
|
|
|
|
@query.field("get_topics_by_author")
|
|
async def get_topics_by_author(_, _info, author_id=0, slug="", user=""):
|
|
topics_by_author_query = select(Topic)
|
|
if author_id:
|
|
topics_by_author_query = topics_by_author_query.join(Author).where(
|
|
Author.id == author_id
|
|
)
|
|
elif slug:
|
|
topics_by_author_query = topics_by_author_query.join(Author).where(
|
|
Author.slug == slug
|
|
)
|
|
elif user:
|
|
topics_by_author_query = topics_by_author_query.join(Author).where(
|
|
Author.user == user
|
|
)
|
|
|
|
return get_with_stat(topics_by_author_query)
|
|
|
|
|
|
@query.field("get_topic")
|
|
def get_topic(_, _info, slug: str):
|
|
topic_query = select(Topic).filter(Topic.slug == slug)
|
|
result = get_with_stat(topic_query)
|
|
for topic in result:
|
|
return topic
|
|
|
|
|
|
@mutation.field("create_topic")
|
|
@login_required
|
|
async def create_topic(_, _info, inp):
|
|
with local_session() as session:
|
|
# TODO: check user permissions to create topic for exact community
|
|
# and actor is permitted to craete it
|
|
new_topic = Topic(**inp)
|
|
session.add(new_topic)
|
|
session.commit()
|
|
|
|
return {"topic": new_topic}
|
|
|
|
|
|
@mutation.field("update_topic")
|
|
@login_required
|
|
async def update_topic(_, _info, inp):
|
|
slug = inp["slug"]
|
|
with local_session() as session:
|
|
topic = session.query(Topic).filter(Topic.slug == slug).first()
|
|
if not topic:
|
|
return {"error": "topic not found"}
|
|
else:
|
|
Topic.update(topic, inp)
|
|
session.add(topic)
|
|
session.commit()
|
|
|
|
return {"topic": topic}
|
|
|
|
|
|
@mutation.field("delete_topic")
|
|
@login_required
|
|
async def delete_topic(_, info, slug: str):
|
|
user_id = info.context["user_id"]
|
|
with local_session() as session:
|
|
t: Topic = session.query(Topic).filter(Topic.slug == slug).first()
|
|
if not t:
|
|
return {"error": "invalid topic slug"}
|
|
author = session.query(Author).filter(Author.user == user_id).first()
|
|
if author:
|
|
if t.created_by != author.id:
|
|
return {"error": "access denied"}
|
|
|
|
session.delete(t)
|
|
session.commit()
|
|
|
|
return {}
|
|
return {"error": "access denied"}
|
|
|
|
|
|
@query.field("get_topics_random")
|
|
def get_topics_random(_, _info, amount=12):
|
|
q = select(Topic)
|
|
q = q.join(ShoutTopic)
|
|
q = q.group_by(Topic.id)
|
|
q = q.having(func.count(distinct(ShoutTopic.shout)) > 2)
|
|
q = q.order_by(func.random()).limit(amount)
|
|
|
|
topics = []
|
|
with local_session() as session:
|
|
for [topic] in session.execute(q):
|
|
topics.append(topic)
|
|
|
|
return topics
|
|
|
|
|
|
@query.field("get_topic_followers")
|
|
async def get_topic_followers(_, _info, slug: str):
|
|
logger.debug(f"getting followers for @{slug}")
|
|
topic_query = select(Topic.id).filter(Topic.slug == slug).first()
|
|
topic_id_result = local_session().execute(topic_query)
|
|
topic_id = topic_id_result[0] if topic_id_result else None
|
|
followers = await get_cached_topic_followers(topic_id)
|
|
return followers
|
|
|
|
|
|
@query.field("get_topic_authors")
|
|
async def get_topic_authors(_, _info, slug: str):
|
|
logger.debug(f"getting authors for @{slug}")
|
|
topic_query = select(Topic.id).filter(Topic.slug == slug).first()
|
|
topic_id_result = local_session().execute(topic_query)
|
|
topic_id = topic_id_result[0] if topic_id_result else None
|
|
topic_authors_query = (
|
|
select(ShoutAuthor.author)
|
|
.select_from(join(ShoutTopic, Shout, ShoutTopic.shout == Shout.id))
|
|
.join(ShoutAuthor, ShoutAuthor.shout == Shout.id)
|
|
.filter(
|
|
and_(
|
|
ShoutTopic.topic == topic_id,
|
|
Shout.published_at.is_not(None),
|
|
Shout.deleted_at.is_(None),
|
|
)
|
|
)
|
|
)
|
|
authors = await get_cached_topic_authors(topic_id, topic_authors_query)
|
|
return authors
|