2022-11-13 16:25:57 +00:00
|
|
|
from datetime import datetime, timedelta
|
2022-11-17 20:33:03 +00:00
|
|
|
import sqlalchemy as sa
|
2022-09-17 18:12:14 +00:00
|
|
|
from sqlalchemy.orm import selectinload
|
2022-11-20 03:41:05 +00:00
|
|
|
from sqlalchemy.sql.expression import desc, asc, select, case
|
2022-09-17 18:12:14 +00:00
|
|
|
from base.orm import local_session
|
2022-11-21 08:13:57 +00:00
|
|
|
from base.resolvers import query
|
2022-11-20 03:41:05 +00:00
|
|
|
from orm.shout import Shout
|
2022-11-18 00:38:29 +00:00
|
|
|
from orm.reaction import Reaction, ReactionKind
|
2022-09-17 18:12:14 +00:00
|
|
|
from services.zine.shoutauthor import ShoutAuthorStorage
|
2022-11-15 02:36:30 +00:00
|
|
|
from services.stat.reacted import ReactedStorage
|
|
|
|
|
|
|
|
|
2022-11-22 03:11:26 +00:00
|
|
|
def apply_filters(q, filters, user=None):
|
|
|
|
filters = {} if filters is None else filters
|
2022-11-21 08:13:57 +00:00
|
|
|
if filters.get("reacted") and user:
|
|
|
|
q.join(Reaction, Reaction.createdBy == user.slug)
|
|
|
|
if filters.get("visibility"):
|
|
|
|
q = q.filter(Shout.visibility == filters.get("visibility"))
|
|
|
|
if filters.get("layout"):
|
|
|
|
q = q.filter(Shout.layout == filters.get("layout"))
|
|
|
|
if filters.get("author"):
|
|
|
|
q = q.filter(Shout.authors.any(slug=filters.get("author")))
|
|
|
|
if filters.get("topic"):
|
|
|
|
q = q.filter(Shout.topics.any(slug=filters.get("topic")))
|
|
|
|
if filters.get("title"):
|
|
|
|
q = q.filter(Shout.title.ilike(f'%{filters.get("title")}%'))
|
|
|
|
if filters.get("body"):
|
|
|
|
q = q.filter(Shout.body.ilike(f'%{filters.get("body")}%s'))
|
|
|
|
if filters.get("days"):
|
|
|
|
before = datetime.now() - timedelta(days=int(filters.get("days")) or 30)
|
|
|
|
q = q.filter(Shout.createdAt > before)
|
|
|
|
return q
|
|
|
|
|
|
|
|
|
|
|
|
def extract_order(o, q):
|
|
|
|
if o:
|
|
|
|
q = q.add_columns(sa.func.count(Reaction.id).label(o))
|
|
|
|
if o == 'comments':
|
|
|
|
q = q.join(Reaction, Shout.slug == Reaction.shout)
|
|
|
|
q = q.filter(Reaction.body.is_not(None))
|
|
|
|
elif o == 'reacted':
|
|
|
|
q = q.join(
|
|
|
|
Reaction
|
|
|
|
).add_columns(
|
|
|
|
sa.func.max(Reaction.createdAt).label(o)
|
|
|
|
)
|
|
|
|
elif o == "rating":
|
|
|
|
q = q.join(Reaction).add_columns(sa.func.sum(case(
|
|
|
|
(Reaction.kind == ReactionKind.AGREE, 1),
|
|
|
|
(Reaction.kind == ReactionKind.DISAGREE, -1),
|
|
|
|
(Reaction.kind == ReactionKind.PROOF, 1),
|
|
|
|
(Reaction.kind == ReactionKind.DISPROOF, -1),
|
|
|
|
(Reaction.kind == ReactionKind.ACCEPT, 1),
|
|
|
|
(Reaction.kind == ReactionKind.REJECT, -1),
|
|
|
|
(Reaction.kind == ReactionKind.LIKE, 1),
|
|
|
|
(Reaction.kind == ReactionKind.DISLIKE, -1),
|
|
|
|
else_=0
|
|
|
|
)).label(o))
|
|
|
|
return o
|
|
|
|
else:
|
|
|
|
return 'createdAt'
|
|
|
|
|
|
|
|
|
2022-11-18 00:38:29 +00:00
|
|
|
@query.field("loadShout")
|
|
|
|
async def load_shout(_, info, slug):
|
2022-11-18 02:19:10 +00:00
|
|
|
with local_session() as session:
|
|
|
|
shout = session.query(Shout).options(
|
|
|
|
# TODO add cation
|
|
|
|
selectinload(Shout.authors),
|
|
|
|
selectinload(Shout.topics),
|
|
|
|
).filter(
|
|
|
|
Shout.slug == slug
|
|
|
|
).filter(
|
|
|
|
Shout.deletedAt.is_(None)
|
|
|
|
).one()
|
2022-11-18 00:38:29 +00:00
|
|
|
|
2022-11-18 02:19:10 +00:00
|
|
|
return shout
|
2022-11-18 00:38:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
@query.field("loadShouts")
|
|
|
|
async def load_shouts_by(_, info, options):
|
2022-11-15 02:36:30 +00:00
|
|
|
"""
|
2022-11-18 00:38:29 +00:00
|
|
|
:param options: {
|
|
|
|
filters: {
|
|
|
|
layout: 'audio',
|
|
|
|
visibility: "public",
|
|
|
|
author: 'discours',
|
|
|
|
topic: 'culture',
|
|
|
|
title: 'something',
|
|
|
|
body: 'something else',
|
|
|
|
days: 30
|
|
|
|
}
|
|
|
|
offset: 0
|
|
|
|
limit: 50
|
|
|
|
order_by: 'createdAt'
|
2022-11-21 08:13:57 +00:00
|
|
|
order_by_desc: true
|
2022-11-18 00:38:29 +00:00
|
|
|
|
2022-11-15 02:36:30 +00:00
|
|
|
}
|
|
|
|
:return: Shout[]
|
|
|
|
"""
|
|
|
|
|
2022-11-17 20:33:03 +00:00
|
|
|
q = select(Shout).options(
|
2022-11-20 03:41:05 +00:00
|
|
|
# TODO add caption
|
2022-11-15 02:36:30 +00:00
|
|
|
selectinload(Shout.authors),
|
|
|
|
selectinload(Shout.topics),
|
|
|
|
).where(
|
|
|
|
Shout.deletedAt.is_(None)
|
|
|
|
)
|
2022-11-21 08:13:57 +00:00
|
|
|
user = info.context["request"].user
|
2022-11-22 03:11:26 +00:00
|
|
|
q = apply_filters(q, options.get("filters"), user)
|
2022-11-21 16:01:09 +00:00
|
|
|
|
2022-11-21 11:52:04 +00:00
|
|
|
order_by = extract_order(options.get("order_by"), q)
|
2022-11-21 16:01:09 +00:00
|
|
|
|
|
|
|
order_by_desc = True if options.get('order_by_desc') is None else options.get('order_by_desc')
|
|
|
|
|
|
|
|
query_order_by = desc(order_by) if order_by_desc else asc(order_by)
|
2022-11-21 04:47:59 +00:00
|
|
|
offset = options.get("offset", 0)
|
|
|
|
limit = options.get("limit", 10)
|
2022-11-20 03:41:05 +00:00
|
|
|
q = q.group_by(Shout.id).order_by(query_order_by).limit(limit).offset(offset)
|
2022-11-18 00:38:29 +00:00
|
|
|
|
|
|
|
with local_session() as session:
|
|
|
|
shouts = list(map(lambda r: r.Shout, session.execute(q)))
|
|
|
|
for s in shouts:
|
|
|
|
s.stat = await ReactedStorage.get_shout_stat(s.slug)
|
|
|
|
for a in s.authors:
|
|
|
|
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
|
|
|
|
|
|
|
|
return shouts
|