core/resolvers/zine.py

258 lines
8.6 KiB
Python
Raw Normal View History

from sqlalchemy.orm import selectinload
from sqlalchemy.sql.expression import and_, select, desc
from auth.authenticate import login_required
from base.orm import local_session
from base.resolvers import mutation, query
from orm.collection import ShoutCollection
2022-10-01 10:19:13 +00:00
from orm.shout import Shout, ShoutTopic
from orm.topic import Topic
from resolvers.community import community_follow, community_unfollow
from resolvers.profile import author_follow, author_unfollow
from resolvers.reactions import reactions_follow, reactions_unfollow
from resolvers.topics import topic_follow, topic_unfollow
from services.stat.viewed import ViewedStorage
from services.zine.shoutauthor import ShoutAuthorStorage
from services.zine.shoutscache import ShoutsCache
2022-10-04 09:25:59 +00:00
from services.search import SearchService
2022-09-03 10:50:14 +00:00
2021-08-08 12:23:12 +00:00
2022-09-08 16:46:02 +00:00
@mutation.field("incrementView")
async def increment_view(_, _info, shout):
2022-09-20 07:11:22 +00:00
# TODO: use ackee to collect views
2022-09-08 16:46:02 +00:00
async with ViewedStorage.lock:
return ViewedStorage.increment(shout)
2021-10-31 14:50:55 +00:00
@query.field("topMonth")
2022-09-14 09:45:31 +00:00
async def top_month(_, _info, offset, limit):
async with ShoutsCache.lock:
2022-09-14 09:45:31 +00:00
return ShoutsCache.top_month[offset : offset + limit]
2021-10-31 14:50:55 +00:00
2022-09-03 10:50:14 +00:00
2022-09-20 13:32:04 +00:00
@query.field("topPublished")
async def top_published(_, _info, daysago, offset, limit):
async with ShoutsCache.lock:
return ShoutsCache.get_top_published_before(daysago, offset, limit)
@query.field("topCommented")
async def top_commented(_, _info, offset, limit):
async with ShoutsCache.lock:
return ShoutsCache.top_commented[offset : offset + limit]
2021-10-31 14:50:55 +00:00
@query.field("topOverall")
2022-09-14 09:45:31 +00:00
async def top_overall(_, _info, offset, limit):
async with ShoutsCache.lock:
2022-09-14 09:45:31 +00:00
return ShoutsCache.top_overall[offset : offset + limit]
2021-10-30 19:15:29 +00:00
2022-09-03 10:50:14 +00:00
2022-06-11 22:05:20 +00:00
@query.field("recentPublished")
2022-09-14 09:45:31 +00:00
async def recent_published(_, _info, offset, limit):
async with ShoutsCache.lock:
2022-09-14 15:56:49 +00:00
return ShoutsCache.recent_published[offset : offset + limit]
2021-09-01 16:03:00 +00:00
2022-09-03 10:50:14 +00:00
2022-06-11 22:05:20 +00:00
@query.field("recentAll")
2022-09-14 09:45:31 +00:00
async def recent_all(_, _info, offset, limit):
async with ShoutsCache.lock:
2022-09-14 09:45:31 +00:00
return ShoutsCache.recent_all[offset : offset + limit]
2022-06-11 22:05:20 +00:00
2022-09-03 10:50:14 +00:00
@query.field("recentReacted")
2022-09-14 09:45:31 +00:00
async def recent_reacted(_, _info, offset, limit):
async with ShoutsCache.lock:
2022-09-14 15:56:49 +00:00
return ShoutsCache.recent_reacted[offset : offset + limit]
2022-02-03 09:13:53 +00:00
2022-09-03 10:50:14 +00:00
2022-09-19 16:14:20 +00:00
@query.field("recentCommented")
async def recent_commented(_, _info, offset, limit):
async with ShoutsCache.lock:
return ShoutsCache.recent_commented[offset : offset + limit]
2021-09-24 14:39:37 +00:00
@query.field("getShoutBySlug")
2021-09-05 07:16:28 +00:00
async def get_shout_by_slug(_, info, slug):
2022-09-03 10:50:14 +00:00
all_fields = [
node.name.value for node in info.field_nodes[0].selection_set.selections
]
selected_fields = set(["authors", "topics"]).intersection(all_fields)
select_options = [selectinload(getattr(Shout, field)) for field in selected_fields]
with local_session() as session:
2022-09-04 17:20:38 +00:00
# s = text(open("src/queries/shout-by-slug.sql", "r").read() % slug)
2022-09-03 10:50:14 +00:00
shout = (
session.query(Shout)
.options(select_options)
.filter(Shout.slug == slug)
.first()
)
2022-08-17 09:07:04 +00:00
if not shout:
print(f"shout with slug {slug} not exist")
2022-09-03 10:50:14 +00:00
return {"error": "shout not found"}
2022-08-17 09:07:04 +00:00
else:
for a in shout.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(slug, a.slug)
return shout
2021-12-06 14:50:49 +00:00
2022-09-03 10:50:14 +00:00
2022-09-05 07:28:23 +00:00
@query.field("searchQuery")
2022-09-22 10:31:44 +00:00
async def get_search_results(_, _info, searchtext, offset, limit):
2022-10-04 00:32:29 +00:00
shouts = SearchService.search(searchtext)
# TODO: sort and filter types for search service
for s in shouts:
shout = s.dict()
for a in shout['authors']:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
s.stat.relevance = 1 # FIXME: expecting search engine rated relevance
return shouts[offset : offset + limit]
2022-09-05 07:28:23 +00:00
2022-10-01 10:19:13 +00:00
@query.field("shoutsByAuthors")
2022-10-05 12:22:56 +00:00
async def shouts_by_authors(_, _info, slugs, offset=0, limit=100):
2022-10-01 10:37:24 +00:00
async with ShoutsCache.lock:
2022-10-05 11:54:04 +00:00
shouts = {}
2022-10-01 10:37:24 +00:00
for author in slugs:
2022-10-05 12:22:56 +00:00
shouts_by_author = list(ShoutsCache.by_author.get(author, {}).values())
for s in shouts_by_author:
for a in s.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
if bool(s.publishedAt):
shouts[s.slug] = s
2022-10-05 12:06:55 +00:00
shouts_prepared = list(shouts.values())
2022-10-04 14:03:13 +00:00
shouts_prepared.sort(key=lambda s: s.publishedAt, reverse=True)
return shouts_prepared[offset : offset + limit]
2022-10-01 10:19:13 +00:00
2022-11-13 09:25:02 +00:00
@query.field("recentLayoutShouts")
@query.field("topLayoutShouts")
@query.field("topMonthLayoutShouts")
async def shouts_by_layout(param, info, layout, amount=100, offset=0):
print(param)
print(info)
2022-11-13 04:34:02 +00:00
async with ShoutsCache.lock:
shouts = {}
# for layout in ['image', 'audio', 'video', 'literature']:
shouts_by_layout = list(ShoutsCache.by_layout.get(layout, []))
for s in shouts_by_layout:
if s.visibility == 'public': # if bool(s.publishedAt):
shouts[s.slug] = s
for a in s.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
2022-11-13 04:34:02 +00:00
shouts_prepared = list(shouts.values())
2022-11-13 09:25:02 +00:00
# TODO: pick keyfunc according to kind of query
def keyfunc(s):
return s.createdAt
shouts_prepared.sort(key=keyfunc, reverse=True)
2022-11-13 04:34:02 +00:00
return shouts_prepared[offset : offset + amount]
2022-05-31 07:03:50 +00:00
@query.field("shoutsByTopics")
2022-10-05 11:54:04 +00:00
async def shouts_by_topics(_, _info, slugs, offset=0, limit=100):
2022-10-01 10:37:24 +00:00
async with ShoutsCache.lock:
2022-10-05 11:54:04 +00:00
shouts = {}
2022-10-01 10:37:24 +00:00
for topic in slugs:
2022-10-05 12:22:56 +00:00
shouts_by_topic = list(ShoutsCache.by_topic.get(topic, {}).values())
for s in shouts_by_topic:
for a in s.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
if bool(s.publishedAt):
shouts[s.slug] = s
2022-10-05 12:06:55 +00:00
shouts_prepared = list(shouts.values())
2022-10-05 11:54:04 +00:00
shouts_prepared.sort(key=lambda s: s.publishedAt, reverse=True)
return shouts_prepared[offset : offset + limit]
2022-09-03 10:50:14 +00:00
@query.field("shoutsByCollection")
2022-09-14 09:45:31 +00:00
async def shouts_by_collection(_, _info, collection, offset, limit):
with local_session() as session:
2022-09-14 11:09:28 +00:00
shouts = (
2022-09-03 10:50:14 +00:00
session.query(Shout)
.join(ShoutCollection, ShoutCollection.collection == collection)
2022-09-22 10:31:44 +00:00
.where(and_(ShoutCollection.shout == Shout.slug, Shout.publishedAt.is_not(None)))
.order_by(desc("publishedAt"))
2022-09-14 09:45:31 +00:00
.limit(limit)
.offset(offset)
2022-09-03 10:50:14 +00:00
)
for s in shouts:
for a in s.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
return shouts
2022-09-03 10:50:14 +00:00
2022-08-17 07:59:17 +00:00
SINGLE_COMMUNITY = True
2022-09-03 10:50:14 +00:00
2022-05-31 07:03:50 +00:00
@query.field("shoutsByCommunities")
2022-09-14 09:45:31 +00:00
async def shouts_by_communities(_, info, slugs, offset, limit):
2022-09-03 10:50:14 +00:00
if SINGLE_COMMUNITY:
2022-09-14 09:45:31 +00:00
return recent_published(_, info, offset, limit)
2022-08-17 07:59:17 +00:00
else:
with local_session() as session:
2022-09-03 10:50:14 +00:00
# TODO fix postgres high load
shouts = (
session.query(Shout)
.distinct()
.join(ShoutTopic)
.where(
and_(
2022-09-22 10:31:44 +00:00
Shout.publishedAt.is_not(None),
2022-09-03 10:50:14 +00:00
ShoutTopic.topic.in_(
select(Topic.slug).where(Topic.community.in_(slugs))
),
)
)
.order_by(desc("publishedAt"))
2022-09-14 09:45:31 +00:00
.limit(limit)
.offset(offset)
2022-09-03 10:50:14 +00:00
)
2022-08-17 07:59:17 +00:00
for s in shouts:
for a in s.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
return shouts
2022-01-30 11:28:27 +00:00
2022-09-03 10:50:14 +00:00
@mutation.field("follow")
@login_required
async def follow(_, info, what, slug):
user = info.context["request"].user
try:
if what == "AUTHOR":
author_follow(user, slug)
elif what == "TOPIC":
topic_follow(user, slug)
elif what == "COMMUNITY":
community_follow(user, slug)
elif what == "REACTIONS":
reactions_follow(user, slug)
except Exception as e:
2022-09-03 10:50:14 +00:00
return {"error": str(e)}
return {}
2022-09-03 10:50:14 +00:00
@mutation.field("unfollow")
@login_required
async def unfollow(_, info, what, slug):
user = info.context["request"].user
try:
if what == "AUTHOR":
author_unfollow(user, slug)
elif what == "TOPIC":
topic_unfollow(user, slug)
elif what == "COMMUNITY":
community_unfollow(user, slug)
elif what == "REACTIONS":
reactions_unfollow(user, slug)
except Exception as e:
2022-09-03 10:50:14 +00:00
return {"error": str(e)}
return {}