format and lint orm
This commit is contained in:
@@ -1,76 +1,109 @@
|
||||
from resolvers.auth import login, sign_out, is_email_used, register, confirm, auth_forget, auth_reset
|
||||
from resolvers.zine import get_shout_by_slug, follow, unfollow, view_shout, \
|
||||
top_month, top_overall, recent_published, recent_all, top_viewed, \
|
||||
shouts_by_authors, shouts_by_topics, shouts_by_communities
|
||||
from resolvers.profile import get_users_by_slugs, get_current_user, get_user_reacted_shouts, get_user_roles
|
||||
from resolvers.topics import topic_follow, topic_unfollow, topics_by_author, topics_by_community, topics_all
|
||||
from resolvers.auth import (
|
||||
login,
|
||||
sign_out,
|
||||
is_email_used,
|
||||
register,
|
||||
confirm,
|
||||
auth_forget,
|
||||
auth_reset,
|
||||
)
|
||||
from resolvers.zine import (
|
||||
get_shout_by_slug,
|
||||
follow,
|
||||
unfollow,
|
||||
view_shout,
|
||||
top_month,
|
||||
top_overall,
|
||||
recent_published,
|
||||
recent_all,
|
||||
top_viewed,
|
||||
shouts_by_authors,
|
||||
shouts_by_topics,
|
||||
shouts_by_communities,
|
||||
)
|
||||
from resolvers.profile import (
|
||||
get_users_by_slugs,
|
||||
get_current_user,
|
||||
get_user_reacted_shouts,
|
||||
get_user_roles,
|
||||
)
|
||||
from resolvers.topics import (
|
||||
topic_follow,
|
||||
topic_unfollow,
|
||||
topics_by_author,
|
||||
topics_by_community,
|
||||
topics_all,
|
||||
)
|
||||
|
||||
# from resolvers.feed import shouts_for_feed, my_candidates
|
||||
from resolvers.reactions import create_reaction, delete_reaction, update_reaction, get_all_reactions
|
||||
from resolvers.reactions import (
|
||||
create_reaction,
|
||||
delete_reaction,
|
||||
update_reaction,
|
||||
get_all_reactions,
|
||||
)
|
||||
from resolvers.collab import invite_author, remove_author
|
||||
from resolvers.editor import create_shout, delete_shout, update_shout
|
||||
from resolvers.community import create_community, delete_community, get_community, get_communities
|
||||
from resolvers.community import (
|
||||
create_community,
|
||||
delete_community,
|
||||
get_community,
|
||||
get_communities,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"follow",
|
||||
"unfollow",
|
||||
|
||||
# auth
|
||||
"login",
|
||||
"register",
|
||||
"is_email_used",
|
||||
"confirm",
|
||||
"auth_forget",
|
||||
"auth_reset"
|
||||
"sign_out",
|
||||
|
||||
# profile
|
||||
"get_current_user",
|
||||
"get_users_by_slugs",
|
||||
|
||||
# zine
|
||||
"shouts_for_feed",
|
||||
"my_candidates",
|
||||
"recent_published",
|
||||
"recent_reacted",
|
||||
"recent_all",
|
||||
"shouts_by_topics",
|
||||
"shouts_by_authors",
|
||||
"shouts_by_communities",
|
||||
"get_user_reacted_shouts",
|
||||
"top_month",
|
||||
"top_overall",
|
||||
"top_viewed",
|
||||
"view_shout",
|
||||
"view_reaction",
|
||||
"get_shout_by_slug",
|
||||
|
||||
# editor
|
||||
"create_shout",
|
||||
"update_shout",
|
||||
"delete_shout",
|
||||
# collab
|
||||
"invite_author",
|
||||
"remove_author"
|
||||
|
||||
# topics
|
||||
"topics_all",
|
||||
"topics_by_community",
|
||||
"topics_by_author",
|
||||
"topic_follow",
|
||||
"topic_unfollow",
|
||||
|
||||
# communities
|
||||
"get_community",
|
||||
"get_communities",
|
||||
"create_community",
|
||||
"delete_community",
|
||||
|
||||
# reactions
|
||||
"get_shout_reactions",
|
||||
"reactions_follow",
|
||||
"reactions_unfollow",
|
||||
"create_reaction",
|
||||
"update_reaction",
|
||||
"delete_reaction",
|
||||
"get_all_reactions",
|
||||
]
|
||||
# auth
|
||||
"login",
|
||||
"register",
|
||||
"is_email_used",
|
||||
"confirm",
|
||||
"auth_forget",
|
||||
"auth_reset" "sign_out",
|
||||
# profile
|
||||
"get_current_user",
|
||||
"get_users_by_slugs",
|
||||
# zine
|
||||
"shouts_for_feed",
|
||||
"my_candidates",
|
||||
"recent_published",
|
||||
"recent_reacted",
|
||||
"recent_all",
|
||||
"shouts_by_topics",
|
||||
"shouts_by_authors",
|
||||
"shouts_by_communities",
|
||||
"get_user_reacted_shouts",
|
||||
"top_month",
|
||||
"top_overall",
|
||||
"top_viewed",
|
||||
"view_shout",
|
||||
"view_reaction",
|
||||
"get_shout_by_slug",
|
||||
# editor
|
||||
"create_shout",
|
||||
"update_shout",
|
||||
"delete_shout",
|
||||
# collab
|
||||
"invite_author",
|
||||
"remove_author"
|
||||
# topics
|
||||
"topics_all",
|
||||
"topics_by_community",
|
||||
"topics_by_author",
|
||||
"topic_follow",
|
||||
"topic_unfollow",
|
||||
# communities
|
||||
"get_community",
|
||||
"get_communities",
|
||||
"create_community",
|
||||
"delete_community",
|
||||
# reactions
|
||||
"get_shout_reactions",
|
||||
"reactions_follow",
|
||||
"reactions_unfollow",
|
||||
"create_reaction",
|
||||
"update_reaction",
|
||||
"delete_reaction",
|
||||
"get_all_reactions",
|
||||
]
|
||||
|
@@ -13,119 +13,126 @@ from resolvers.profile import get_user_info
|
||||
from base.exceptions import InvalidPassword, InvalidToken
|
||||
from settings import JWT_AUTH_HEADER
|
||||
|
||||
|
||||
@mutation.field("confirmEmail")
|
||||
async def confirm(*_, confirm_token):
|
||||
''' confirm owning email address '''
|
||||
auth_token, user = await Authorize.confirm(confirm_token)
|
||||
if auth_token:
|
||||
user.emailConfirmed = True
|
||||
user.save()
|
||||
return { "token": auth_token, "user" : user}
|
||||
else:
|
||||
return { "error": "email not confirmed"}
|
||||
"""confirm owning email address"""
|
||||
auth_token, user = await Authorize.confirm(confirm_token)
|
||||
if auth_token:
|
||||
user.emailConfirmed = True
|
||||
user.save()
|
||||
return {"token": auth_token, "user": user}
|
||||
else:
|
||||
return {"error": "email not confirmed"}
|
||||
|
||||
|
||||
@mutation.field("registerUser")
|
||||
async def register(*_, email: str, password: str = ""):
|
||||
''' creates new user account '''
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.email == email).first()
|
||||
if user:
|
||||
return {"error" : "user already exist"}
|
||||
"""creates new user account"""
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.email == email).first()
|
||||
if user:
|
||||
return {"error": "user already exist"}
|
||||
|
||||
user_dict = { "email": email }
|
||||
username = email.split('@')[0]
|
||||
user_dict["username"] = username
|
||||
user_dict["slug"] = quote_plus(translit(username, 'ru', reversed=True).replace('.', '-').lower())
|
||||
if password:
|
||||
user_dict["password"] = Password.encode(password)
|
||||
user = User(**user_dict)
|
||||
user.roles.append(Role.default_role)
|
||||
with local_session() as session:
|
||||
session.add(user)
|
||||
session.commit()
|
||||
user_dict = {"email": email}
|
||||
username = email.split("@")[0]
|
||||
user_dict["username"] = username
|
||||
user_dict["slug"] = quote_plus(
|
||||
translit(username, "ru", reversed=True).replace(".", "-").lower()
|
||||
)
|
||||
if password:
|
||||
user_dict["password"] = Password.encode(password)
|
||||
user = User(**user_dict)
|
||||
user.roles.append(Role.default_role)
|
||||
with local_session() as session:
|
||||
session.add(user)
|
||||
session.commit()
|
||||
|
||||
await send_confirm_email(user)
|
||||
await send_confirm_email(user)
|
||||
|
||||
return {"user": user}
|
||||
|
||||
return { "user": user }
|
||||
|
||||
@mutation.field("requestPasswordUpdate")
|
||||
async def auth_forget(_, info, email):
|
||||
''' send email to recover account '''
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.email == email).first()
|
||||
if not user:
|
||||
return {"error" : "user not exist"}
|
||||
"""send email to recover account"""
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.email == email).first()
|
||||
if not user:
|
||||
return {"error": "user not exist"}
|
||||
|
||||
await send_reset_password_email(user)
|
||||
await send_reset_password_email(user)
|
||||
|
||||
return {}
|
||||
|
||||
return {}
|
||||
|
||||
@mutation.field("updatePassword")
|
||||
async def auth_reset(_, info, password, resetToken):
|
||||
''' set the new password '''
|
||||
try:
|
||||
user_id = await ResetPassword.verify(resetToken)
|
||||
except InvalidToken as e:
|
||||
return {"error" : e.message}
|
||||
"""set the new password"""
|
||||
try:
|
||||
user_id = await ResetPassword.verify(resetToken)
|
||||
except InvalidToken as e:
|
||||
return {"error": e.message}
|
||||
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter_by(id = user_id).first()
|
||||
if not user:
|
||||
return {"error" : "user not exist"}
|
||||
user.password = Password.encode(password)
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter_by(id=user_id).first()
|
||||
if not user:
|
||||
return {"error": "user not exist"}
|
||||
user.password = Password.encode(password)
|
||||
session.commit()
|
||||
|
||||
return {}
|
||||
|
||||
return {}
|
||||
|
||||
@query.field("signIn")
|
||||
async def login(_, info: GraphQLResolveInfo, email: str, password: str = ""):
|
||||
|
||||
with local_session() as session:
|
||||
orm_user = session.query(User).filter(User.email == email).first()
|
||||
if orm_user is None:
|
||||
print(f"signIn {email}: email not found")
|
||||
return {"error" : "email not found"}
|
||||
with local_session() as session:
|
||||
orm_user = session.query(User).filter(User.email == email).first()
|
||||
if orm_user is None:
|
||||
print(f"signIn {email}: email not found")
|
||||
return {"error": "email not found"}
|
||||
|
||||
if not password:
|
||||
print(f"signIn {email}: send auth email")
|
||||
await send_auth_email(orm_user)
|
||||
return {}
|
||||
if not password:
|
||||
print(f"signIn {email}: send auth email")
|
||||
await send_auth_email(orm_user)
|
||||
return {}
|
||||
|
||||
if not orm_user.emailConfirmed:
|
||||
return {"error" : "email not confirmed"}
|
||||
if not orm_user.emailConfirmed:
|
||||
return {"error": "email not confirmed"}
|
||||
|
||||
try:
|
||||
device = info.context["request"].headers['device']
|
||||
except KeyError:
|
||||
device = "pc"
|
||||
auto_delete = False if device == "mobile" else True # why autodelete with mobile?
|
||||
try:
|
||||
device = info.context["request"].headers["device"]
|
||||
except KeyError:
|
||||
device = "pc"
|
||||
auto_delete = False if device == "mobile" else True # why autodelete with mobile?
|
||||
|
||||
try:
|
||||
user = Identity.identity(orm_user, password)
|
||||
except InvalidPassword:
|
||||
print(f"signIn {email}: invalid password")
|
||||
return {"error" : "invalid password"}
|
||||
|
||||
token = await Authorize.authorize(user, device=device, auto_delete=auto_delete)
|
||||
print(f"signIn {email}: OK")
|
||||
try:
|
||||
user = Identity.identity(orm_user, password)
|
||||
except InvalidPassword:
|
||||
print(f"signIn {email}: invalid password")
|
||||
return {"error": "invalid password"}
|
||||
|
||||
return {
|
||||
"token" : token,
|
||||
"user": orm_user,
|
||||
"info": await get_user_info(orm_user.slug)
|
||||
}
|
||||
token = await Authorize.authorize(user, device=device, auto_delete=auto_delete)
|
||||
print(f"signIn {email}: OK")
|
||||
|
||||
return {
|
||||
"token": token,
|
||||
"user": orm_user,
|
||||
"info": await get_user_info(orm_user.slug),
|
||||
}
|
||||
|
||||
|
||||
@query.field("signOut")
|
||||
@login_required
|
||||
async def sign_out(_, info: GraphQLResolveInfo):
|
||||
token = info.context["request"].headers[JWT_AUTH_HEADER]
|
||||
status = await Authorize.revoke(token)
|
||||
return True
|
||||
token = info.context["request"].headers[JWT_AUTH_HEADER]
|
||||
status = await Authorize.revoke(token)
|
||||
return True
|
||||
|
||||
|
||||
@query.field("isEmailUsed")
|
||||
async def is_email_used(_, info, email):
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.email == email).first()
|
||||
return not user is None
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.email == email).first()
|
||||
return not user is None
|
||||
|
@@ -6,67 +6,69 @@ from orm.user import User
|
||||
from base.resolvers import query, mutation
|
||||
from auth.authenticate import login_required
|
||||
|
||||
|
||||
@query.field("getCollabs")
|
||||
@login_required
|
||||
async def get_collabs(_, info):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
collabs = []
|
||||
with local_session() as session:
|
||||
user = session.query(User).where(User.id == user_id).first()
|
||||
collabs = session.query(Collab).filter(user.slug in Collab.authors)
|
||||
return collabs
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
collabs = []
|
||||
with local_session() as session:
|
||||
user = session.query(User).where(User.id == user_id).first()
|
||||
collabs = session.query(Collab).filter(user.slug in Collab.authors)
|
||||
return collabs
|
||||
|
||||
|
||||
@mutation.field("inviteAuthor")
|
||||
@login_required
|
||||
async def invite_author(_, info, author, shout):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
|
||||
with local_session() as session:
|
||||
shout = session.query(Shout).filter(Shout.slug == shout).first()
|
||||
if not shout:
|
||||
return {"error": "invalid shout slug"}
|
||||
authors = [a.id for a in shout.authors]
|
||||
if user_id not in authors:
|
||||
return {"error": "access denied"}
|
||||
author = session.query(User).filter(User.slug == author).first()
|
||||
if author.id in authors:
|
||||
return {"error": "already added"}
|
||||
shout.authors.append(author)
|
||||
shout.updated_at = datetime.now()
|
||||
shout.save()
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
shout = session.query(Shout).filter(Shout.slug == shout).first()
|
||||
if not shout:
|
||||
return {"error": "invalid shout slug"}
|
||||
authors = [a.id for a in shout.authors]
|
||||
if user_id not in authors:
|
||||
return {"error": "access denied"}
|
||||
author = session.query(User).filter(User.slug == author).first()
|
||||
if author.id in authors:
|
||||
return {"error": "already added"}
|
||||
shout.authors.append(author)
|
||||
shout.updated_at = datetime.now()
|
||||
shout.save()
|
||||
session.commit()
|
||||
|
||||
# TODO: email notify
|
||||
# TODO: email notify
|
||||
|
||||
return {}
|
||||
|
||||
return {}
|
||||
|
||||
@mutation.field("removeAuthor")
|
||||
@login_required
|
||||
async def remove_author(_, info, author, shout):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
|
||||
with local_session() as session:
|
||||
shout = session.query(Shout).filter(Shout.slug == shout).first()
|
||||
if not shout:
|
||||
return {"error": "invalid shout slug"}
|
||||
authors = [author.id for author in shout.authors]
|
||||
if user_id not in authors:
|
||||
return {"error": "access denied"}
|
||||
author = session.query(User).filter(User.slug == author).first()
|
||||
if author.id not in authors:
|
||||
return {"error": "not in authors"}
|
||||
shout.authors.remove(author)
|
||||
shout.updated_at = datetime.now()
|
||||
shout.save()
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
shout = session.query(Shout).filter(Shout.slug == shout).first()
|
||||
if not shout:
|
||||
return {"error": "invalid shout slug"}
|
||||
authors = [author.id for author in shout.authors]
|
||||
if user_id not in authors:
|
||||
return {"error": "access denied"}
|
||||
author = session.query(User).filter(User.slug == author).first()
|
||||
if author.id not in authors:
|
||||
return {"error": "not in authors"}
|
||||
shout.authors.remove(author)
|
||||
shout.updated_at = datetime.now()
|
||||
shout.save()
|
||||
session.commit()
|
||||
|
||||
# result = Result("INVITED")
|
||||
# FIXME: await ShoutStorage.put(result)
|
||||
# result = Result("INVITED")
|
||||
# FIXME: await ShoutStorage.put(result)
|
||||
|
||||
# TODO: email notify
|
||||
# TODO: email notify
|
||||
|
||||
return {}
|
||||
return {}
|
||||
|
@@ -7,93 +7,121 @@ from datetime import datetime
|
||||
from typing import Collection
|
||||
from sqlalchemy import and_
|
||||
|
||||
|
||||
@mutation.field("createCollection")
|
||||
@login_required
|
||||
async def create_collection(_, info, input):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
collection = Collection.create(
|
||||
slug = input.get('slug', ''),
|
||||
title = input.get('title', ''),
|
||||
desc = input.get('desc', ''),
|
||||
pic = input.get('pic', '')
|
||||
)
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
collection = Collection.create(
|
||||
slug=input.get("slug", ""),
|
||||
title=input.get("title", ""),
|
||||
desc=input.get("desc", ""),
|
||||
pic=input.get("pic", ""),
|
||||
)
|
||||
|
||||
return {"collection": collection}
|
||||
|
||||
return {"collection": collection}
|
||||
|
||||
@mutation.field("updateCollection")
|
||||
@login_required
|
||||
async def update_collection(_, info, input):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
collection_slug = input.get('slug', '')
|
||||
with local_session() as session:
|
||||
owner = session.query(User).filter(User.id == user_id) # note list here
|
||||
collection = session.query(Collection).filter(Collection.slug == collection_slug).first()
|
||||
editors = [e.slug for e in collection.editors]
|
||||
if not collection:
|
||||
return {"error": "invalid collection id"}
|
||||
if collection.createdBy not in (owner + editors):
|
||||
return {"error": "access denied"}
|
||||
collection.title = input.get('title', '')
|
||||
collection.desc = input.get('desc', '')
|
||||
collection.pic = input.get('pic', '')
|
||||
collection.updatedAt = datetime.now()
|
||||
session.commit()
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
collection_slug = input.get("slug", "")
|
||||
with local_session() as session:
|
||||
owner = session.query(User).filter(User.id == user_id) # note list here
|
||||
collection = (
|
||||
session.query(Collection).filter(Collection.slug == collection_slug).first()
|
||||
)
|
||||
editors = [e.slug for e in collection.editors]
|
||||
if not collection:
|
||||
return {"error": "invalid collection id"}
|
||||
if collection.createdBy not in (owner + editors):
|
||||
return {"error": "access denied"}
|
||||
collection.title = input.get("title", "")
|
||||
collection.desc = input.get("desc", "")
|
||||
collection.pic = input.get("pic", "")
|
||||
collection.updatedAt = datetime.now()
|
||||
session.commit()
|
||||
|
||||
|
||||
@mutation.field("deleteCollection")
|
||||
@login_required
|
||||
async def delete_collection(_, info, slug):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
with local_session() as session:
|
||||
collection = session.query(Collection).filter(Collection.slug == slug).first()
|
||||
if not collection:
|
||||
return {"error": "invalid collection slug"}
|
||||
if collection.owner != user_id:
|
||||
return {"error": "access denied"}
|
||||
collection.deletedAt = datetime.now()
|
||||
session.commit()
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
with local_session() as session:
|
||||
collection = session.query(Collection).filter(Collection.slug == slug).first()
|
||||
if not collection:
|
||||
return {"error": "invalid collection slug"}
|
||||
if collection.owner != user_id:
|
||||
return {"error": "access denied"}
|
||||
collection.deletedAt = datetime.now()
|
||||
session.commit()
|
||||
|
||||
return {}
|
||||
|
||||
return {}
|
||||
|
||||
@query.field("getUserCollections")
|
||||
async def get_user_collections(_, info, userslug):
|
||||
collections = []
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.slug == userslug).first()
|
||||
if user:
|
||||
# TODO: check rights here
|
||||
collections = session.\
|
||||
query(Collection).\
|
||||
where(and_(Collection.createdBy == userslug, Collection.publishedAt != None)).\
|
||||
all()
|
||||
for c in collections:
|
||||
shouts = session.query(ShoutCollection).filter(ShoutCollection.collection == c.id).all()
|
||||
c.amount = len(shouts)
|
||||
return collections
|
||||
collections = []
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.slug == userslug).first()
|
||||
if user:
|
||||
# TODO: check rights here
|
||||
collections = (
|
||||
session.query(Collection)
|
||||
.where(
|
||||
and_(
|
||||
Collection.createdBy == userslug, Collection.publishedAt != None
|
||||
)
|
||||
)
|
||||
.all()
|
||||
)
|
||||
for c in collections:
|
||||
shouts = (
|
||||
session.query(ShoutCollection)
|
||||
.filter(ShoutCollection.collection == c.id)
|
||||
.all()
|
||||
)
|
||||
c.amount = len(shouts)
|
||||
return collections
|
||||
|
||||
|
||||
@query.field("getMyCollections")
|
||||
async def get_user_collections(_, info, userslug):
|
||||
collections = []
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.slug == userslug).first()
|
||||
if user:
|
||||
# TODO: check rights here
|
||||
collections = session.\
|
||||
query(Collection).\
|
||||
where(and_(Collection.createdBy == userslug, Collection.publishedAt != None)).\
|
||||
all()
|
||||
for c in collections:
|
||||
shouts = session.query(ShoutCollection).filter(ShoutCollection.collection == c.id).all()
|
||||
c.amount = len(shouts)
|
||||
return collections
|
||||
collections = []
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.slug == userslug).first()
|
||||
if user:
|
||||
# TODO: check rights here
|
||||
collections = (
|
||||
session.query(Collection)
|
||||
.where(
|
||||
and_(
|
||||
Collection.createdBy == userslug, Collection.publishedAt != None
|
||||
)
|
||||
)
|
||||
.all()
|
||||
)
|
||||
for c in collections:
|
||||
shouts = (
|
||||
session.query(ShoutCollection)
|
||||
.filter(ShoutCollection.collection == c.id)
|
||||
.all()
|
||||
)
|
||||
c.amount = len(shouts)
|
||||
return collections
|
||||
|
||||
|
||||
@query.field("getMyColelctions")
|
||||
@login_required
|
||||
async def get_my_collections(_, info):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
with local_session() as session:
|
||||
collections = session.query(Collection).when(Collection.createdBy == user_id).all()
|
||||
return collections
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
with local_session() as session:
|
||||
collections = (
|
||||
session.query(Collection).when(Collection.createdBy == user_id).all()
|
||||
)
|
||||
return collections
|
||||
|
@@ -7,96 +7,112 @@ from datetime import datetime
|
||||
from typing import List
|
||||
from sqlalchemy import and_
|
||||
|
||||
|
||||
@mutation.field("createCommunity")
|
||||
@login_required
|
||||
async def create_community(_, info, input):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
|
||||
community = Community.create(
|
||||
slug = input.get('slug', ''),
|
||||
title = input.get('title', ''),
|
||||
desc = input.get('desc', ''),
|
||||
pic = input.get('pic', '')
|
||||
)
|
||||
community = Community.create(
|
||||
slug=input.get("slug", ""),
|
||||
title=input.get("title", ""),
|
||||
desc=input.get("desc", ""),
|
||||
pic=input.get("pic", ""),
|
||||
)
|
||||
|
||||
return {"community": community}
|
||||
|
||||
return {"community": community}
|
||||
|
||||
@mutation.field("updateCommunity")
|
||||
@login_required
|
||||
async def update_community(_, info, input):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
community_slug = input.get('slug', '')
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
community_slug = input.get("slug", "")
|
||||
|
||||
with local_session() as session:
|
||||
owner = session.query(User).filter(User.id == user_id) # note list here
|
||||
community = (
|
||||
session.query(Community).filter(Community.slug == community_slug).first()
|
||||
)
|
||||
editors = [e.slug for e in community.editors]
|
||||
if not community:
|
||||
return {"error": "invalid community id"}
|
||||
if community.createdBy not in (owner + editors):
|
||||
return {"error": "access denied"}
|
||||
community.title = input.get("title", "")
|
||||
community.desc = input.get("desc", "")
|
||||
community.pic = input.get("pic", "")
|
||||
community.updatedAt = datetime.now()
|
||||
session.commit()
|
||||
|
||||
with local_session() as session:
|
||||
owner = session.query(User).filter(User.id == user_id) # note list here
|
||||
community = session.query(Community).filter(Community.slug == community_slug).first()
|
||||
editors = [e.slug for e in community.editors]
|
||||
if not community:
|
||||
return {"error": "invalid community id"}
|
||||
if community.createdBy not in (owner + editors):
|
||||
return {"error": "access denied"}
|
||||
community.title = input.get('title', '')
|
||||
community.desc = input.get('desc', '')
|
||||
community.pic = input.get('pic', '')
|
||||
community.updatedAt = datetime.now()
|
||||
session.commit()
|
||||
|
||||
@mutation.field("deleteCommunity")
|
||||
@login_required
|
||||
async def delete_community(_, info, slug):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
|
||||
with local_session() as session:
|
||||
community = session.query(Community).filter(Community.slug == slug).first()
|
||||
if not community:
|
||||
return {"error": "invalid community slug"}
|
||||
if community.owner != user_id:
|
||||
return {"error": "access denied"}
|
||||
community.deletedAt = datetime.now()
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
community = session.query(Community).filter(Community.slug == slug).first()
|
||||
if not community:
|
||||
return {"error": "invalid community slug"}
|
||||
if community.owner != user_id:
|
||||
return {"error": "access denied"}
|
||||
community.deletedAt = datetime.now()
|
||||
session.commit()
|
||||
|
||||
return {}
|
||||
|
||||
return {}
|
||||
|
||||
@query.field("getCommunity")
|
||||
async def get_community(_, info, slug):
|
||||
with local_session() as session:
|
||||
community = session.query(Community).filter(Community.slug == slug).first()
|
||||
if not community:
|
||||
return {"error": "invalid community id"}
|
||||
with local_session() as session:
|
||||
community = session.query(Community).filter(Community.slug == slug).first()
|
||||
if not community:
|
||||
return {"error": "invalid community id"}
|
||||
|
||||
return community
|
||||
|
||||
return community
|
||||
|
||||
@query.field("getCommunities")
|
||||
async def get_communities(_, info):
|
||||
with local_session() as session:
|
||||
communities = session.query(Community)
|
||||
return communities
|
||||
with local_session() as session:
|
||||
communities = session.query(Community)
|
||||
return communities
|
||||
|
||||
|
||||
def community_follow(user, slug):
|
||||
CommunityFollower.create(
|
||||
follower = user.slug,
|
||||
community = slug
|
||||
)
|
||||
CommunityFollower.create(follower=user.slug, community=slug)
|
||||
|
||||
|
||||
def community_unfollow(user, slug):
|
||||
with local_session() as session:
|
||||
following = session.query(CommunityFollower).\
|
||||
filter(and_(CommunityFollower.follower == user.slug, CommunityFollower.community == slug)).\
|
||||
first()
|
||||
if not following:
|
||||
raise Exception("[orm.community] following was not exist")
|
||||
session.delete(following)
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
following = (
|
||||
session.query(CommunityFollower)
|
||||
.filter(
|
||||
and_(
|
||||
CommunityFollower.follower == user.slug,
|
||||
CommunityFollower.community == slug,
|
||||
)
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not following:
|
||||
raise Exception("[orm.community] following was not exist")
|
||||
session.delete(following)
|
||||
session.commit()
|
||||
|
||||
|
||||
@query.field("userFollowedCommunities")
|
||||
def get_followed_communities(_, user_slug) -> List[Community]:
|
||||
ccc = []
|
||||
with local_session() as session:
|
||||
ccc = session.query(Community.slug).\
|
||||
join(CommunityFollower).\
|
||||
where(CommunityFollower.follower == user_slug).\
|
||||
all()
|
||||
return ccc
|
||||
ccc = []
|
||||
with local_session() as session:
|
||||
ccc = (
|
||||
session.query(Community.slug)
|
||||
.join(CommunityFollower)
|
||||
.where(CommunityFollower.follower == user_slug)
|
||||
.all()
|
||||
)
|
||||
return ccc
|
||||
|
@@ -13,106 +13,82 @@ from services.zine.gittask import GitTask
|
||||
@mutation.field("createShout")
|
||||
@login_required
|
||||
async def create_shout(_, info, input):
|
||||
user = info.context["request"].user
|
||||
user = info.context["request"].user
|
||||
|
||||
topic_slugs = input.get("topic_slugs", [])
|
||||
if topic_slugs:
|
||||
del input["topic_slugs"]
|
||||
topic_slugs = input.get("topic_slugs", [])
|
||||
if topic_slugs:
|
||||
del input["topic_slugs"]
|
||||
|
||||
new_shout = Shout.create(**input)
|
||||
ShoutAuthor.create(
|
||||
shout = new_shout.slug,
|
||||
user = user.slug
|
||||
)
|
||||
new_shout = Shout.create(**input)
|
||||
ShoutAuthor.create(shout=new_shout.slug, user=user.slug)
|
||||
|
||||
reactions_follow(user, new_shout.slug, True)
|
||||
reactions_follow(user, new_shout.slug, True)
|
||||
|
||||
if "mainTopic" in input:
|
||||
topic_slugs.append(input["mainTopic"])
|
||||
if "mainTopic" in input:
|
||||
topic_slugs.append(input["mainTopic"])
|
||||
|
||||
for slug in topic_slugs:
|
||||
topic = ShoutTopic.create(
|
||||
shout = new_shout.slug,
|
||||
topic = slug)
|
||||
new_shout.topic_slugs = topic_slugs
|
||||
for slug in topic_slugs:
|
||||
topic = ShoutTopic.create(shout=new_shout.slug, topic=slug)
|
||||
new_shout.topic_slugs = topic_slugs
|
||||
|
||||
task = GitTask(
|
||||
input,
|
||||
user.username,
|
||||
user.email,
|
||||
"new shout %s" % (new_shout.slug)
|
||||
)
|
||||
|
||||
# await ShoutCommentsStorage.send_shout(new_shout)
|
||||
task = GitTask(input, user.username, user.email, "new shout %s" % (new_shout.slug))
|
||||
|
||||
# await ShoutCommentsStorage.send_shout(new_shout)
|
||||
|
||||
return {"shout": new_shout}
|
||||
|
||||
return {
|
||||
"shout" : new_shout
|
||||
}
|
||||
|
||||
@mutation.field("updateShout")
|
||||
@login_required
|
||||
async def update_shout(_, info, input):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
|
||||
slug = input["slug"]
|
||||
slug = input["slug"]
|
||||
|
||||
session = local_session()
|
||||
user = session.query(User).filter(User.id == user_id).first()
|
||||
shout = session.query(Shout).filter(Shout.slug == slug).first()
|
||||
session = local_session()
|
||||
user = session.query(User).filter(User.id == user_id).first()
|
||||
shout = session.query(Shout).filter(Shout.slug == slug).first()
|
||||
|
||||
if not shout:
|
||||
return {
|
||||
"error" : "shout not found"
|
||||
}
|
||||
if not shout:
|
||||
return {"error": "shout not found"}
|
||||
|
||||
authors = [author.id for author in shout.authors]
|
||||
if not user_id in authors:
|
||||
scopes = auth.scopes
|
||||
print(scopes)
|
||||
if not Resource.shout_id in scopes:
|
||||
return {
|
||||
"error" : "access denied"
|
||||
}
|
||||
authors = [author.id for author in shout.authors]
|
||||
if not user_id in authors:
|
||||
scopes = auth.scopes
|
||||
print(scopes)
|
||||
if not Resource.shout_id in scopes:
|
||||
return {"error": "access denied"}
|
||||
|
||||
shout.update(input)
|
||||
shout.updatedAt = datetime.now()
|
||||
session.commit()
|
||||
session.close()
|
||||
shout.update(input)
|
||||
shout.updatedAt = datetime.now()
|
||||
session.commit()
|
||||
session.close()
|
||||
|
||||
for topic in input.get("topic_slugs", []):
|
||||
ShoutTopic.create(
|
||||
shout = slug,
|
||||
topic = topic)
|
||||
for topic in input.get("topic_slugs", []):
|
||||
ShoutTopic.create(shout=slug, topic=topic)
|
||||
|
||||
task = GitTask(
|
||||
input,
|
||||
user.username,
|
||||
user.email,
|
||||
"update shout %s" % (slug)
|
||||
)
|
||||
task = GitTask(input, user.username, user.email, "update shout %s" % (slug))
|
||||
|
||||
return {"shout": shout}
|
||||
|
||||
return {
|
||||
"shout" : shout
|
||||
}
|
||||
|
||||
@mutation.field("deleteShout")
|
||||
@login_required
|
||||
async def delete_shout(_, info, slug):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
|
||||
with local_session() as session:
|
||||
shout = session.query(Shout).filter(Shout.slug == slug).first()
|
||||
authors = [a.id for a in shout.authors]
|
||||
if not shout:
|
||||
return {"error": "invalid shout slug"}
|
||||
if user_id not in authors:
|
||||
return {"error": "access denied"}
|
||||
for a in authors:
|
||||
reactions_unfollow(a.slug, slug, True)
|
||||
shout.deletedAt = datetime.now()
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
shout = session.query(Shout).filter(Shout.slug == slug).first()
|
||||
authors = [a.id for a in shout.authors]
|
||||
if not shout:
|
||||
return {"error": "invalid shout slug"}
|
||||
if user_id not in authors:
|
||||
return {"error": "access denied"}
|
||||
for a in authors:
|
||||
reactions_unfollow(a.slug, slug, True)
|
||||
shout.deletedAt = datetime.now()
|
||||
session.commit()
|
||||
|
||||
|
||||
return {}
|
||||
return {}
|
||||
|
@@ -7,36 +7,44 @@ from orm.topic import TopicFollower
|
||||
from orm.user import AuthorFollower
|
||||
from typing import List
|
||||
|
||||
|
||||
@query.field("shoutsForFeed")
|
||||
@login_required
|
||||
def get_user_feed(_, info, page, size) -> List[Shout]:
|
||||
user = info.context["request"].user
|
||||
shouts = []
|
||||
with local_session() as session:
|
||||
shouts = session.query(Shout).\
|
||||
join(ShoutAuthor).\
|
||||
join(AuthorFollower).\
|
||||
where(AuthorFollower.follower == user.slug).\
|
||||
order_by(desc(Shout.createdAt))
|
||||
topicrows = session.query(Shout).\
|
||||
join(ShoutTopic).\
|
||||
join(TopicFollower).\
|
||||
where(TopicFollower.follower == user.slug).\
|
||||
order_by(desc(Shout.createdAt))
|
||||
shouts = shouts.union(topicrows).limit(size).offset(page * size).all()
|
||||
return shouts
|
||||
user = info.context["request"].user
|
||||
shouts = []
|
||||
with local_session() as session:
|
||||
shouts = (
|
||||
session.query(Shout)
|
||||
.join(ShoutAuthor)
|
||||
.join(AuthorFollower)
|
||||
.where(AuthorFollower.follower == user.slug)
|
||||
.order_by(desc(Shout.createdAt))
|
||||
)
|
||||
topicrows = (
|
||||
session.query(Shout)
|
||||
.join(ShoutTopic)
|
||||
.join(TopicFollower)
|
||||
.where(TopicFollower.follower == user.slug)
|
||||
.order_by(desc(Shout.createdAt))
|
||||
)
|
||||
shouts = shouts.union(topicrows).limit(size).offset(page * size).all()
|
||||
return shouts
|
||||
|
||||
|
||||
@query.field("myCandidates")
|
||||
@login_required
|
||||
async def user_unpublished_shouts(_, info, page = 1, size = 10) -> List[Shout]:
|
||||
user = info.context["request"].user
|
||||
shouts = []
|
||||
with local_session() as session:
|
||||
shouts = session.query(Shout).\
|
||||
join(ShoutAuthor).\
|
||||
where(and_(Shout.publishedAt == None, ShoutAuthor.user == user.slug)).\
|
||||
order_by(desc(Shout.createdAt)).\
|
||||
limit(size).\
|
||||
offset( page * size).\
|
||||
all()
|
||||
return shouts
|
||||
async def user_unpublished_shouts(_, info, page=1, size=10) -> List[Shout]:
|
||||
user = info.context["request"].user
|
||||
shouts = []
|
||||
with local_session() as session:
|
||||
shouts = (
|
||||
session.query(Shout)
|
||||
.join(ShoutAuthor)
|
||||
.where(and_(Shout.publishedAt == None, ShoutAuthor.user == user.slug))
|
||||
.order_by(desc(Shout.createdAt))
|
||||
.limit(size)
|
||||
.offset(page * size)
|
||||
.all()
|
||||
)
|
||||
return shouts
|
||||
|
@@ -4,263 +4,283 @@ import asyncio, uuid, json
|
||||
from datetime import datetime
|
||||
from base.redis import redis
|
||||
|
||||
class ChatFollowing:
|
||||
queue = asyncio.Queue()
|
||||
|
||||
def __init__(self, chat_id):
|
||||
self.chat_id = chat_id
|
||||
class ChatFollowing:
|
||||
queue = asyncio.Queue()
|
||||
|
||||
def __init__(self, chat_id):
|
||||
self.chat_id = chat_id
|
||||
|
||||
|
||||
class MessagesStorage:
|
||||
lock = asyncio.Lock()
|
||||
chats = []
|
||||
lock = asyncio.Lock()
|
||||
chats = []
|
||||
|
||||
@staticmethod
|
||||
async def register_chat(chat):
|
||||
async with MessagesStorage.lock:
|
||||
MessagesStorage.chats.append(chat)
|
||||
|
||||
@staticmethod
|
||||
async def remove_chat(chat):
|
||||
async with MessagesStorage.lock:
|
||||
MessagesStorage.chats.remove(chat)
|
||||
|
||||
@staticmethod
|
||||
async def put(message_result):
|
||||
async with MessagesStorage.lock:
|
||||
for chat in MessagesStorage.chats:
|
||||
if message_result.message["chatId"] == chat.chat_id:
|
||||
chat.queue.put_nowait(message_result)
|
||||
|
||||
@staticmethod
|
||||
async def register_chat(chat):
|
||||
async with MessagesStorage.lock:
|
||||
MessagesStorage.chats.append(chat)
|
||||
|
||||
@staticmethod
|
||||
async def remove_chat(chat):
|
||||
async with MessagesStorage.lock:
|
||||
MessagesStorage.chats.remove(chat)
|
||||
|
||||
@staticmethod
|
||||
async def put(message_result):
|
||||
async with MessagesStorage.lock:
|
||||
for chat in MessagesStorage.chats:
|
||||
if message_result.message["chatId"] == chat.chat_id:
|
||||
chat.queue.put_nowait(message_result)
|
||||
|
||||
class MessageResult:
|
||||
def __init__(self, status, message):
|
||||
self.status = status
|
||||
self.message = message
|
||||
def __init__(self, status, message):
|
||||
self.status = status
|
||||
self.message = message
|
||||
|
||||
|
||||
async def get_unread_counter(user_slug):
|
||||
chats = await redis.execute("GET", f"chats_by_user/{user_slug}")
|
||||
if not chats:
|
||||
return 0
|
||||
chats = await redis.execute("GET", f"chats_by_user/{user_slug}")
|
||||
if not chats:
|
||||
return 0
|
||||
|
||||
chats = json.loads(chats)
|
||||
unread = 0
|
||||
for chat_id in chats:
|
||||
n = await redis.execute("LLEN", f"chats/{chat_id}/unread/{user_slug}")
|
||||
unread += n
|
||||
chats = json.loads(chats)
|
||||
unread = 0
|
||||
for chat_id in chats:
|
||||
n = await redis.execute("LLEN", f"chats/{chat_id}/unread/{user_slug}")
|
||||
unread += n
|
||||
|
||||
return unread
|
||||
return unread
|
||||
|
||||
async def add_user_to_chat(user_slug, chat_id, chat = None):
|
||||
chats = await redis.execute("GET", f"chats_by_user/{user_slug}")
|
||||
if not chats:
|
||||
chats = set()
|
||||
else:
|
||||
chats = set(json.loads(chats))
|
||||
chats.add(str(chat_id))
|
||||
chats = list(chats)
|
||||
await redis.execute("SET", f"chats_by_user/{user_slug}", json.dumps(chats))
|
||||
|
||||
if chat:
|
||||
users = set(chat["users"])
|
||||
users.add(user_slug)
|
||||
chat["users"] = list(users)
|
||||
await redis.execute("SET", f"chats/{chat_id}", json.dumps(chat))
|
||||
async def add_user_to_chat(user_slug, chat_id, chat=None):
|
||||
chats = await redis.execute("GET", f"chats_by_user/{user_slug}")
|
||||
if not chats:
|
||||
chats = set()
|
||||
else:
|
||||
chats = set(json.loads(chats))
|
||||
chats.add(str(chat_id))
|
||||
chats = list(chats)
|
||||
await redis.execute("SET", f"chats_by_user/{user_slug}", json.dumps(chats))
|
||||
|
||||
if chat:
|
||||
users = set(chat["users"])
|
||||
users.add(user_slug)
|
||||
chat["users"] = list(users)
|
||||
await redis.execute("SET", f"chats/{chat_id}", json.dumps(chat))
|
||||
|
||||
|
||||
@mutation.field("createChat")
|
||||
@login_required
|
||||
async def create_chat(_, info, description):
|
||||
user = info.context["request"].user
|
||||
user = info.context["request"].user
|
||||
|
||||
chat_id = uuid.uuid4()
|
||||
chat = {
|
||||
"description" : description,
|
||||
"createdAt" : str(datetime.now),
|
||||
"createdBy" : user.slug,
|
||||
"id" : str(chat_id),
|
||||
"users" : [user.slug]
|
||||
}
|
||||
chat_id = uuid.uuid4()
|
||||
chat = {
|
||||
"description": description,
|
||||
"createdAt": str(datetime.now),
|
||||
"createdBy": user.slug,
|
||||
"id": str(chat_id),
|
||||
"users": [user.slug],
|
||||
}
|
||||
|
||||
await redis.execute("SET", f"chats/{chat_id}", json.dumps(chat))
|
||||
await redis.execute("SET", f"chats/{chat_id}/next_message_id", 0)
|
||||
await redis.execute("SET", f"chats/{chat_id}", json.dumps(chat))
|
||||
await redis.execute("SET", f"chats/{chat_id}/next_message_id", 0)
|
||||
|
||||
await add_user_to_chat(user.slug, chat_id)
|
||||
await add_user_to_chat(user.slug, chat_id)
|
||||
|
||||
return {"chatId": chat_id}
|
||||
|
||||
return { "chatId" : chat_id }
|
||||
|
||||
async def load_messages(chatId, size, page):
|
||||
message_ids = await redis.lrange(f"chats/{chatId}/message_ids",
|
||||
size * (page -1), size * page - 1)
|
||||
messages = []
|
||||
if message_ids:
|
||||
message_keys = [f"chats/{chatId}/messages/{id.decode('UTF-8')}" for id in message_ids]
|
||||
messages = await redis.mget(*message_keys)
|
||||
messages = [json.loads(msg) for msg in messages]
|
||||
return messages
|
||||
message_ids = await redis.lrange(
|
||||
f"chats/{chatId}/message_ids", size * (page - 1), size * page - 1
|
||||
)
|
||||
messages = []
|
||||
if message_ids:
|
||||
message_keys = [
|
||||
f"chats/{chatId}/messages/{id.decode('UTF-8')}" for id in message_ids
|
||||
]
|
||||
messages = await redis.mget(*message_keys)
|
||||
messages = [json.loads(msg) for msg in messages]
|
||||
return messages
|
||||
|
||||
|
||||
@query.field("userChats")
|
||||
@login_required
|
||||
async def user_chats(_, info):
|
||||
user = info.context["request"].user
|
||||
user = info.context["request"].user
|
||||
|
||||
chats = await redis.execute("GET", f"chats_by_user/{user.slug}")
|
||||
if not chats:
|
||||
chats = list()
|
||||
else:
|
||||
chats = list(json.loads(chats))
|
||||
chats = await redis.execute("GET", f"chats_by_user/{user.slug}")
|
||||
if not chats:
|
||||
chats = list()
|
||||
else:
|
||||
chats = list(json.loads(chats))
|
||||
|
||||
return {"chats": chats}
|
||||
|
||||
return {"chats" : chats}
|
||||
|
||||
@query.field("enterChat")
|
||||
@login_required
|
||||
async def enter_chat(_, info, chatId, size):
|
||||
user = info.context["request"].user
|
||||
user = info.context["request"].user
|
||||
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return { "error" : "chat not exist" }
|
||||
chat = json.loads(chat)
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return {"error": "chat not exist"}
|
||||
chat = json.loads(chat)
|
||||
|
||||
messages = await load_messages(chatId, size, 1)
|
||||
messages = await load_messages(chatId, size, 1)
|
||||
|
||||
await add_user_to_chat(user.slug, chatId, chat)
|
||||
await add_user_to_chat(user.slug, chatId, chat)
|
||||
|
||||
return {"chat": chat, "messages": messages}
|
||||
|
||||
return {
|
||||
"chat" : chat,
|
||||
"messages" : messages
|
||||
}
|
||||
|
||||
@mutation.field("createMessage")
|
||||
@login_required
|
||||
async def create_message(_, info, chatId, body, replyTo = None):
|
||||
user = info.context["request"].user
|
||||
async def create_message(_, info, chatId, body, replyTo=None):
|
||||
user = info.context["request"].user
|
||||
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return { "error" : "chat not exist" }
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return {"error": "chat not exist"}
|
||||
|
||||
message_id = await redis.execute("GET", f"chats/{chatId}/next_message_id")
|
||||
message_id = int(message_id)
|
||||
message_id = await redis.execute("GET", f"chats/{chatId}/next_message_id")
|
||||
message_id = int(message_id)
|
||||
|
||||
new_message = {
|
||||
"chatId" : chatId,
|
||||
"id" : message_id,
|
||||
"author" : user.slug,
|
||||
"body" : body,
|
||||
"replyTo" : replyTo,
|
||||
"createdAt" : datetime.now().isoformat()
|
||||
}
|
||||
new_message = {
|
||||
"chatId": chatId,
|
||||
"id": message_id,
|
||||
"author": user.slug,
|
||||
"body": body,
|
||||
"replyTo": replyTo,
|
||||
"createdAt": datetime.now().isoformat(),
|
||||
}
|
||||
|
||||
await redis.execute("SET", f"chats/{chatId}/messages/{message_id}", json.dumps(new_message))
|
||||
await redis.execute("LPUSH", f"chats/{chatId}/message_ids", str(message_id))
|
||||
await redis.execute("SET", f"chats/{chatId}/next_message_id", str(message_id + 1))
|
||||
await redis.execute(
|
||||
"SET", f"chats/{chatId}/messages/{message_id}", json.dumps(new_message)
|
||||
)
|
||||
await redis.execute("LPUSH", f"chats/{chatId}/message_ids", str(message_id))
|
||||
await redis.execute("SET", f"chats/{chatId}/next_message_id", str(message_id + 1))
|
||||
|
||||
chat = json.loads(chat)
|
||||
users = chat["users"]
|
||||
for user_slug in users:
|
||||
await redis.execute("LPUSH", f"chats/{chatId}/unread/{user_slug}", str(message_id))
|
||||
chat = json.loads(chat)
|
||||
users = chat["users"]
|
||||
for user_slug in users:
|
||||
await redis.execute(
|
||||
"LPUSH", f"chats/{chatId}/unread/{user_slug}", str(message_id)
|
||||
)
|
||||
|
||||
result = MessageResult("NEW", new_message)
|
||||
await MessagesStorage.put(result)
|
||||
result = MessageResult("NEW", new_message)
|
||||
await MessagesStorage.put(result)
|
||||
|
||||
return {"message": new_message}
|
||||
|
||||
return {"message" : new_message}
|
||||
|
||||
@query.field("getMessages")
|
||||
@login_required
|
||||
async def get_messages(_, info, chatId, size, page):
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return { "error" : "chat not exist" }
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return {"error": "chat not exist"}
|
||||
|
||||
messages = await load_messages(chatId, size, page)
|
||||
messages = await load_messages(chatId, size, page)
|
||||
|
||||
return messages
|
||||
|
||||
return messages
|
||||
|
||||
@mutation.field("updateMessage")
|
||||
@login_required
|
||||
async def update_message(_, info, chatId, id, body):
|
||||
user = info.context["request"].user
|
||||
user = info.context["request"].user
|
||||
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return { "error" : "chat not exist" }
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return {"error": "chat not exist"}
|
||||
|
||||
message = await redis.execute("GET", f"chats/{chatId}/messages/{id}")
|
||||
if not message:
|
||||
return { "error" : "message not exist" }
|
||||
message = await redis.execute("GET", f"chats/{chatId}/messages/{id}")
|
||||
if not message:
|
||||
return {"error": "message not exist"}
|
||||
|
||||
message = json.loads(message)
|
||||
if message["author"] != user.slug:
|
||||
return { "error" : "access denied" }
|
||||
message = json.loads(message)
|
||||
if message["author"] != user.slug:
|
||||
return {"error": "access denied"}
|
||||
|
||||
message["body"] = body
|
||||
message["updatedAt"] = datetime.now().isoformat()
|
||||
message["body"] = body
|
||||
message["updatedAt"] = datetime.now().isoformat()
|
||||
|
||||
await redis.execute("SET", f"chats/{chatId}/messages/{id}", json.dumps(message))
|
||||
await redis.execute("SET", f"chats/{chatId}/messages/{id}", json.dumps(message))
|
||||
|
||||
result = MessageResult("UPDATED", message)
|
||||
await MessagesStorage.put(result)
|
||||
result = MessageResult("UPDATED", message)
|
||||
await MessagesStorage.put(result)
|
||||
|
||||
return {"message": message}
|
||||
|
||||
return {"message" : message}
|
||||
|
||||
@mutation.field("deleteMessage")
|
||||
@login_required
|
||||
async def delete_message(_, info, chatId, id):
|
||||
user = info.context["request"].user
|
||||
user = info.context["request"].user
|
||||
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return { "error" : "chat not exist" }
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return {"error": "chat not exist"}
|
||||
|
||||
message = await redis.execute("GET", f"chats/{chatId}/messages/{id}")
|
||||
if not message:
|
||||
return { "error" : "message not exist" }
|
||||
message = json.loads(message)
|
||||
if message["author"] != user.slug:
|
||||
return { "error" : "access denied" }
|
||||
message = await redis.execute("GET", f"chats/{chatId}/messages/{id}")
|
||||
if not message:
|
||||
return {"error": "message not exist"}
|
||||
message = json.loads(message)
|
||||
if message["author"] != user.slug:
|
||||
return {"error": "access denied"}
|
||||
|
||||
await redis.execute("LREM", f"chats/{chatId}/message_ids", 0, str(id))
|
||||
await redis.execute("DEL", f"chats/{chatId}/messages/{id}")
|
||||
await redis.execute("LREM", f"chats/{chatId}/message_ids", 0, str(id))
|
||||
await redis.execute("DEL", f"chats/{chatId}/messages/{id}")
|
||||
|
||||
chat = json.loads(chat)
|
||||
users = chat["users"]
|
||||
for user_slug in users:
|
||||
await redis.execute("LREM", f"chats/{chatId}/unread/{user_slug}", 0, str(id))
|
||||
chat = json.loads(chat)
|
||||
users = chat["users"]
|
||||
for user_slug in users:
|
||||
await redis.execute("LREM", f"chats/{chatId}/unread/{user_slug}", 0, str(id))
|
||||
|
||||
result = MessageResult("DELETED", message)
|
||||
await MessagesStorage.put(result)
|
||||
result = MessageResult("DELETED", message)
|
||||
await MessagesStorage.put(result)
|
||||
|
||||
return {}
|
||||
|
||||
return {}
|
||||
|
||||
@mutation.field("markAsRead")
|
||||
@login_required
|
||||
async def mark_as_read(_, info, chatId, ids):
|
||||
user = info.context["request"].user
|
||||
user = info.context["request"].user
|
||||
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return { "error" : "chat not exist" }
|
||||
chat = await redis.execute("GET", f"chats/{chatId}")
|
||||
if not chat:
|
||||
return {"error": "chat not exist"}
|
||||
|
||||
chat = json.loads(chat)
|
||||
users = set(chat["users"])
|
||||
if not user.slug in users:
|
||||
return { "error" : "access denied" }
|
||||
chat = json.loads(chat)
|
||||
users = set(chat["users"])
|
||||
if not user.slug in users:
|
||||
return {"error": "access denied"}
|
||||
|
||||
for id in ids:
|
||||
await redis.execute("LREM", f"chats/{chatId}/unread/{user.slug}", 0, str(id))
|
||||
for id in ids:
|
||||
await redis.execute("LREM", f"chats/{chatId}/unread/{user.slug}", 0, str(id))
|
||||
|
||||
return {}
|
||||
|
||||
return {}
|
||||
|
||||
@subscription.source("chatUpdated")
|
||||
@login_required
|
||||
async def message_generator(obj, info, chatId):
|
||||
try:
|
||||
following_chat = ChatFollowing(chatId)
|
||||
await MessagesStorage.register_chat(following_chat)
|
||||
while True:
|
||||
msg = await following_chat.queue.get()
|
||||
yield msg
|
||||
finally:
|
||||
await MessagesStorage.remove_chat(following_chat)
|
||||
try:
|
||||
following_chat = ChatFollowing(chatId)
|
||||
await MessagesStorage.register_chat(following_chat)
|
||||
while True:
|
||||
msg = await following_chat.queue.get()
|
||||
yield msg
|
||||
finally:
|
||||
await MessagesStorage.remove_chat(following_chat)
|
||||
|
||||
|
||||
@subscription.field("chatUpdated")
|
||||
def message_resolver(message, info, chatId):
|
||||
return message
|
||||
return message
|
||||
|
@@ -14,154 +14,176 @@ from sqlalchemy import and_, desc
|
||||
from sqlalchemy.orm import selectinload
|
||||
from typing import List
|
||||
|
||||
|
||||
@query.field("userReactedShouts")
|
||||
async def get_user_reacted_shouts(_, info, slug, page, size) -> List[Shout]:
|
||||
user = await UserStorage.get_user_by_slug(slug)
|
||||
if not user: return {}
|
||||
with local_session() as session:
|
||||
shouts = session.query(Shout).\
|
||||
join(Reaction).\
|
||||
where(Reaction.createdBy == user.slug).\
|
||||
order_by(desc(Reaction.createdAt)).\
|
||||
limit(size).\
|
||||
offset(page * size).all()
|
||||
return shouts
|
||||
user = await UserStorage.get_user_by_slug(slug)
|
||||
if not user:
|
||||
return []
|
||||
with local_session() as session:
|
||||
shouts = (
|
||||
session.query(Shout)
|
||||
.join(Reaction)
|
||||
.where(Reaction.createdBy == user.slug)
|
||||
.order_by(desc(Reaction.createdAt))
|
||||
.limit(size)
|
||||
.offset(page * size)
|
||||
.all()
|
||||
)
|
||||
return shouts
|
||||
|
||||
|
||||
@query.field("userFollowedTopics")
|
||||
@login_required
|
||||
def get_followed_topics(_, slug) -> List[Topic]:
|
||||
rows = []
|
||||
with local_session() as session:
|
||||
rows = session.query(Topic).\
|
||||
join(TopicFollower).\
|
||||
where(TopicFollower.follower == slug).\
|
||||
all()
|
||||
return rows
|
||||
rows = []
|
||||
with local_session() as session:
|
||||
rows = (
|
||||
session.query(Topic)
|
||||
.join(TopicFollower)
|
||||
.where(TopicFollower.follower == slug)
|
||||
.all()
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
@query.field("userFollowedAuthors")
|
||||
def get_followed_authors(_, slug) -> List[User]:
|
||||
authors = []
|
||||
with local_session() as session:
|
||||
authors = session.query(User).\
|
||||
join(AuthorFollower, User.slug == AuthorFollower.author).\
|
||||
where(AuthorFollower.follower == slug).\
|
||||
all()
|
||||
return authors
|
||||
authors = []
|
||||
with local_session() as session:
|
||||
authors = (
|
||||
session.query(User)
|
||||
.join(AuthorFollower, User.slug == AuthorFollower.author)
|
||||
.where(AuthorFollower.follower == slug)
|
||||
.all()
|
||||
)
|
||||
return authors
|
||||
|
||||
|
||||
@query.field("userFollowers")
|
||||
async def user_followers(_, slug) -> List[User]:
|
||||
with local_session() as session:
|
||||
users = session.query(User).\
|
||||
join(AuthorFollower, User.slug == AuthorFollower.follower).\
|
||||
where(AuthorFollower.author == slug).\
|
||||
all()
|
||||
return users
|
||||
with local_session() as session:
|
||||
users = (
|
||||
session.query(User)
|
||||
.join(AuthorFollower, User.slug == AuthorFollower.follower)
|
||||
.where(AuthorFollower.author == slug)
|
||||
.all()
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
# for mutation.field("refreshSession")
|
||||
async def get_user_info(slug):
|
||||
return {
|
||||
"unread": await get_unread_counter(slug),
|
||||
"topics": [t.slug for t in get_followed_topics(0, slug)],
|
||||
"authors": [a.slug for a in get_followed_authors(0, slug)],
|
||||
"reactions": [r.shout for r in get_shout_reactions(0, slug)],
|
||||
"communities": [c.slug for c in get_followed_communities(0, slug)]
|
||||
}
|
||||
return {
|
||||
"unread": await get_unread_counter(slug),
|
||||
"topics": [t.slug for t in get_followed_topics(0, slug)],
|
||||
"authors": [a.slug for a in get_followed_authors(0, slug)],
|
||||
"reactions": [r.shout for r in get_shout_reactions(0, slug)],
|
||||
"communities": [c.slug for c in get_followed_communities(0, slug)],
|
||||
}
|
||||
|
||||
|
||||
@mutation.field("refreshSession")
|
||||
@login_required
|
||||
async def get_current_user(_, info):
|
||||
user = info.context["request"].user
|
||||
with local_session() as session:
|
||||
user.lastSeen = datetime.now()
|
||||
user.save()
|
||||
session.commit()
|
||||
return {
|
||||
"token": "", # same token?
|
||||
"user": user,
|
||||
"info": await get_user_info(user.slug)
|
||||
}
|
||||
user = info.context["request"].user
|
||||
with local_session() as session:
|
||||
user.lastSeen = datetime.now()
|
||||
user.save()
|
||||
session.commit()
|
||||
return {
|
||||
"token": "", # same token?
|
||||
"user": user,
|
||||
"info": await get_user_info(user.slug),
|
||||
}
|
||||
|
||||
|
||||
@query.field("getUsersBySlugs")
|
||||
async def get_users_by_slugs(_, info, slugs):
|
||||
with local_session() as session:
|
||||
users = session.query(User).\
|
||||
options(selectinload(User.ratings)).\
|
||||
filter(User.slug.in_(slugs)).all()
|
||||
return users
|
||||
with local_session() as session:
|
||||
users = (
|
||||
session.query(User)
|
||||
.options(selectinload(User.ratings))
|
||||
.filter(User.slug in slugs)
|
||||
.all()
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
@query.field("getUserRoles")
|
||||
async def get_user_roles(_, info, slug):
|
||||
with local_session() as session:
|
||||
user = session.query(User).where(User.slug == slug).first()
|
||||
roles = session.query(Role).\
|
||||
options(selectinload(Role.permissions)).\
|
||||
join(UserRole).\
|
||||
where(UserRole.user_id == user.id).all()
|
||||
return roles
|
||||
with local_session() as session:
|
||||
user = session.query(User).where(User.slug == slug).first()
|
||||
roles = (
|
||||
session.query(Role)
|
||||
.options(selectinload(Role.permissions))
|
||||
.join(UserRole)
|
||||
.where(UserRole.user_id == user.id)
|
||||
.all()
|
||||
)
|
||||
return roles
|
||||
|
||||
|
||||
@mutation.field("updateProfile")
|
||||
@login_required
|
||||
async def update_profile(_, info, profile):
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.id == user_id).first()
|
||||
user.update(profile)
|
||||
session.commit()
|
||||
return {}
|
||||
auth = info.context["request"].auth
|
||||
user_id = auth.user_id
|
||||
with local_session() as session:
|
||||
user = session.query(User).filter(User.id == user_id).first()
|
||||
if user:
|
||||
User.update(user, **profile)
|
||||
session.commit()
|
||||
return {}
|
||||
|
||||
|
||||
@mutation.field("rateUser")
|
||||
@login_required
|
||||
async def rate_user(_, info, slug, value):
|
||||
user = info.context["request"].user
|
||||
with local_session() as session:
|
||||
rating = session.query(UserRating).\
|
||||
filter(and_(UserRating.rater == user.slug, UserRating.user == slug)).\
|
||||
first()
|
||||
if rating:
|
||||
rating.value = value
|
||||
session.commit()
|
||||
return {}
|
||||
try:
|
||||
UserRating.create(
|
||||
rater=user.slug,
|
||||
user=slug,
|
||||
value=value
|
||||
)
|
||||
except Exception as err:
|
||||
return {"error": err}
|
||||
return {}
|
||||
user = info.context["request"].user
|
||||
with local_session() as session:
|
||||
rating = (
|
||||
session.query(UserRating)
|
||||
.filter(and_(UserRating.rater == user.slug, UserRating.user == slug))
|
||||
.first()
|
||||
)
|
||||
if rating:
|
||||
rating.value = value
|
||||
session.commit()
|
||||
return {}
|
||||
try:
|
||||
UserRating.create(rater=user.slug, user=slug, value=value)
|
||||
except Exception as err:
|
||||
return {"error": err}
|
||||
return {}
|
||||
|
||||
|
||||
# for mutation.field("follow")
|
||||
def author_follow(user, slug):
|
||||
AuthorFollower.create(
|
||||
follower=user.slug,
|
||||
author=slug
|
||||
)
|
||||
AuthorFollower.create(follower=user.slug, author=slug)
|
||||
|
||||
|
||||
# for mutation.field("unfollow")
|
||||
def author_unfollow(user, slug):
|
||||
with local_session() as session:
|
||||
flw = session.query(AuthorFollower).\
|
||||
filter(and_(AuthorFollower.follower == user.slug, AuthorFollower.author == slug)).\
|
||||
first()
|
||||
if not flw:
|
||||
raise Exception("[resolvers.profile] follower not exist, cant unfollow")
|
||||
else:
|
||||
session.delete(flw)
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
flw = (
|
||||
session.query(AuthorFollower)
|
||||
.filter(
|
||||
and_(
|
||||
AuthorFollower.follower == user.slug, AuthorFollower.author == slug
|
||||
)
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not flw:
|
||||
raise Exception("[resolvers.profile] follower not exist, cant unfollow")
|
||||
else:
|
||||
session.delete(flw)
|
||||
session.commit()
|
||||
|
||||
|
||||
@query.field("authorsAll")
|
||||
def get_authors_all(_, info, page, size):
|
||||
end = page * size
|
||||
start = end - size
|
||||
return UserStorage.get_all_users()[start:end]
|
||||
|
||||
end = page * size
|
||||
start = end - size
|
||||
return list(UserStorage.get_all_users())[start:end] # type: ignore
|
||||
|
@@ -10,11 +10,17 @@ from datetime import datetime
|
||||
from services.auth.users import UserStorage
|
||||
from services.stat.reacted import ReactedStorage
|
||||
|
||||
|
||||
def reactions_follow(user, slug, auto=False):
|
||||
with local_session() as session:
|
||||
fw = session.query(ShoutReactionsFollower).\
|
||||
filter(ShoutReactionsFollower.follower == user.slug, ShoutReactionsFollower.shout == slug).\
|
||||
first()
|
||||
fw = (
|
||||
session.query(ShoutReactionsFollower)
|
||||
.filter(
|
||||
ShoutReactionsFollower.follower == user.slug,
|
||||
ShoutReactionsFollower.shout == slug,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if auto and fw:
|
||||
return
|
||||
elif not auto and fw:
|
||||
@@ -25,17 +31,19 @@ def reactions_follow(user, slug, auto=False):
|
||||
return
|
||||
# print("[resolvers.reactions] was followed before")
|
||||
|
||||
ShoutReactionsFollower.create(
|
||||
follower=user.slug,
|
||||
shout=slug,
|
||||
auto=auto)
|
||||
ShoutReactionsFollower.create(follower=user.slug, shout=slug, auto=auto)
|
||||
|
||||
|
||||
def reactions_unfollow(user, slug):
|
||||
with local_session() as session:
|
||||
following = session.query(ShoutReactionsFollower).\
|
||||
filter(ShoutReactionsFollower.follower == user.slug, ShoutReactionsFollower.shout == slug).\
|
||||
first()
|
||||
following = (
|
||||
session.query(ShoutReactionsFollower)
|
||||
.filter(
|
||||
ShoutReactionsFollower.follower == user.slug,
|
||||
ShoutReactionsFollower.shout == slug,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not following:
|
||||
# print("[resolvers.reactions] was not followed", slug)
|
||||
return
|
||||
@@ -56,7 +64,7 @@ async def create_reaction(_, info, inp):
|
||||
reaction = Reaction.create(**inp)
|
||||
ReactedStorage.increment(reaction.shout, reaction.replyTo)
|
||||
try:
|
||||
reactions_follow(user, inp['shout'], True)
|
||||
reactions_follow(user, inp["shout"], True)
|
||||
except Exception as e:
|
||||
print(f"[resolvers.reactions] error on reactions autofollowing: {e}")
|
||||
|
||||
@@ -76,13 +84,13 @@ async def update_reaction(_, info, inp):
|
||||
return {"error": "invalid reaction id"}
|
||||
if reaction.createdBy != user.slug:
|
||||
return {"error": "access denied"}
|
||||
reaction.body = inp['body']
|
||||
reaction.body = inp["body"]
|
||||
reaction.updatedAt = datetime.now()
|
||||
if reaction.kind != inp['kind']:
|
||||
if reaction.kind != inp["kind"]:
|
||||
# NOTE: change mind detection can be here
|
||||
pass
|
||||
if inp.get('range'):
|
||||
reaction.range = inp.get('range')
|
||||
if inp.get("range"):
|
||||
reaction.range = inp.get("range")
|
||||
session.commit()
|
||||
|
||||
return {"reaction": reaction}
|
||||
@@ -104,29 +112,39 @@ async def delete_reaction(_, info, id):
|
||||
session.commit()
|
||||
return {}
|
||||
|
||||
|
||||
@query.field("reactionsByShout")
|
||||
async def get_shout_reactions(_, info, slug, page, size):
|
||||
offset = page * size
|
||||
reactions = []
|
||||
with local_session() as session:
|
||||
reactions = session.query(Reaction).\
|
||||
filter(Reaction.shout == slug).\
|
||||
limit(size).offset(offset).all()
|
||||
reactions = (
|
||||
session.query(Reaction)
|
||||
.filter(Reaction.shout == slug)
|
||||
.limit(size)
|
||||
.offset(offset)
|
||||
.all()
|
||||
)
|
||||
for r in reactions:
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or 'discours')
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or "discours")
|
||||
return reactions
|
||||
|
||||
|
||||
@query.field("reactionsForSlugs")
|
||||
async def get_shout_reactions(_, info, slugs, page, size):
|
||||
offset = page * size
|
||||
reactions = []
|
||||
with local_session() as session:
|
||||
for slug in slugs:
|
||||
reactions += session.query(Reaction).\
|
||||
filter(Reaction.shout == slug).\
|
||||
limit(size).offset(offset).all()
|
||||
for slug in slugs:
|
||||
reactions += (
|
||||
session.query(Reaction)
|
||||
.filter(Reaction.shout == slug)
|
||||
.limit(size)
|
||||
.offset(offset)
|
||||
.all()
|
||||
)
|
||||
for r in reactions:
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or 'discours')
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or "discours")
|
||||
return reactions
|
||||
|
||||
|
||||
@@ -135,22 +153,31 @@ async def get_all_reactions(_, info, page=1, size=10):
|
||||
offset = page * size
|
||||
reactions = []
|
||||
with local_session() as session:
|
||||
reactions = session.query(Reaction).\
|
||||
filter(Reaction.deletedAt == None).\
|
||||
order_by(desc("createdAt")).\
|
||||
offset(offset).limit(size)
|
||||
reactions = (
|
||||
session.query(Reaction)
|
||||
.filter(Reaction.deletedAt == None)
|
||||
.order_by(desc("createdAt"))
|
||||
.offset(offset)
|
||||
.limit(size)
|
||||
)
|
||||
for r in reactions:
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or 'discours')
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or "discours")
|
||||
reactions = list(reactions)
|
||||
reactions.sort(key=lambda x: x.createdAt, reverse=True)
|
||||
return reactions
|
||||
|
||||
|
||||
@query.field("reactionsByAuthor")
|
||||
async def get_reactions_by_author(_, info, slug, page=1, size=50):
|
||||
offset = page * size
|
||||
reactions = []
|
||||
with local_session() as session:
|
||||
reactions = session.query(Reaction).filter(Reaction.createdBy == slug).limit(size).offset(offset)
|
||||
reactions = (
|
||||
session.query(Reaction)
|
||||
.filter(Reaction.createdBy == slug)
|
||||
.limit(size)
|
||||
.offset(offset)
|
||||
)
|
||||
for r in reactions:
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or 'discours')
|
||||
r.createdBy = await UserStorage.get_user(r.createdBy or "discours")
|
||||
return reactions
|
||||
|
@@ -8,68 +8,76 @@ from base.resolvers import mutation, query
|
||||
from auth.authenticate import login_required
|
||||
from sqlalchemy import and_
|
||||
|
||||
|
||||
@query.field("topicsAll")
|
||||
async def topics_all(_, info, page = 1, size = 50):
|
||||
topics = await TopicStorage.get_topics_all(page, size)
|
||||
for topic in topics:
|
||||
topic.stat = await TopicStat.get_stat(topic.slug)
|
||||
return topics
|
||||
async def topics_all(_, info, page=1, size=50):
|
||||
topics = await TopicStorage.get_topics_all(page, size)
|
||||
for topic in topics:
|
||||
topic.stat = await TopicStat.get_stat(topic.slug)
|
||||
return topics
|
||||
|
||||
|
||||
@query.field("topicsByCommunity")
|
||||
async def topics_by_community(_, info, community):
|
||||
topics = await TopicStorage.get_topics_by_community(community)
|
||||
for topic in topics:
|
||||
topic.stat = await TopicStat.get_stat(topic.slug)
|
||||
return topics
|
||||
|
||||
topics = await TopicStorage.get_topics_by_community(community)
|
||||
for topic in topics:
|
||||
topic.stat = await TopicStat.get_stat(topic.slug)
|
||||
return topics
|
||||
|
||||
|
||||
@query.field("topicsByAuthor")
|
||||
async def topics_by_author(_, info, author):
|
||||
slugs = set()
|
||||
with local_session() as session:
|
||||
shouts = session.query(Shout).\
|
||||
filter(Shout.authors.any(User.slug == author))
|
||||
for shout in shouts:
|
||||
slugs.update([topic.slug for topic in shout.topics])
|
||||
return await TopicStorage.get_topics(slugs)
|
||||
slugs = set()
|
||||
with local_session() as session:
|
||||
shouts = session.query(Shout).filter(Shout.authors.any(User.slug == author))
|
||||
for shout in shouts:
|
||||
slugs.update([topic.slug for topic in shout.topics])
|
||||
return await TopicStorage.get_topics(slugs)
|
||||
|
||||
|
||||
@mutation.field("createTopic")
|
||||
@login_required
|
||||
async def create_topic(_, info, input):
|
||||
new_topic = Topic.create(**input)
|
||||
await TopicStorage.add_topic(new_topic)
|
||||
new_topic = Topic.create(**input)
|
||||
await TopicStorage.add_topic(new_topic)
|
||||
|
||||
return {"topic": new_topic}
|
||||
|
||||
return { "topic" : new_topic }
|
||||
|
||||
@mutation.field("updateTopic")
|
||||
@login_required
|
||||
async def update_topic(_, info, input):
|
||||
slug = input["slug"]
|
||||
slug = input["slug"]
|
||||
|
||||
session = local_session()
|
||||
topic = session.query(Topic).filter(Topic.slug == slug).first()
|
||||
session = local_session()
|
||||
topic = session.query(Topic).filter(Topic.slug == slug).first()
|
||||
|
||||
if not topic:
|
||||
return { "error" : "topic not found" }
|
||||
if not topic:
|
||||
return {"error": "topic not found"}
|
||||
|
||||
topic.update(input)
|
||||
session.commit()
|
||||
session.close()
|
||||
topic.update(input)
|
||||
session.commit()
|
||||
session.close()
|
||||
|
||||
await TopicStorage.add_topic(topic)
|
||||
await TopicStorage.add_topic(topic)
|
||||
|
||||
return {"topic": topic}
|
||||
|
||||
return { "topic" : topic }
|
||||
|
||||
def topic_follow(user, slug):
|
||||
TopicFollower.create(
|
||||
follower = user.slug,
|
||||
topic = slug)
|
||||
TopicFollower.create(follower=user.slug, topic=slug)
|
||||
|
||||
|
||||
def topic_unfollow(user, slug):
|
||||
with local_session() as session:
|
||||
sub = session.query(TopicFollower).\
|
||||
filter(and_(TopicFollower.follower == user.slug, TopicFollower.topic == slug)).\
|
||||
first()
|
||||
if not sub:
|
||||
raise Exception("[resolvers.topics] follower not exist")
|
||||
session.delete(sub)
|
||||
session.commit()
|
||||
with local_session() as session:
|
||||
sub = (
|
||||
session.query(TopicFollower)
|
||||
.filter(
|
||||
and_(TopicFollower.follower == user.slug, TopicFollower.topic == slug)
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not sub:
|
||||
raise Exception("[resolvers.topics] follower not exist")
|
||||
session.delete(sub)
|
||||
session.commit()
|
||||
|
@@ -13,138 +13,171 @@ from resolvers.reactions import reactions_follow, reactions_unfollow
|
||||
from auth.authenticate import login_required
|
||||
from sqlalchemy import select, desc, and_, text
|
||||
from sqlalchemy.orm import selectinload
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
|
||||
@query.field("topViewed")
|
||||
async def top_viewed(_, info, page, size):
|
||||
async with ShoutsCache.lock:
|
||||
return ShoutsCache.top_viewed[(page - 1) * size : page * size]
|
||||
|
||||
|
||||
@query.field("topMonth")
|
||||
async def top_month(_, info, page, size):
|
||||
async with ShoutsCache.lock:
|
||||
return ShoutsCache.top_month[(page - 1) * size : page * size]
|
||||
|
||||
|
||||
@query.field("topOverall")
|
||||
async def top_overall(_, info, page, size):
|
||||
async with ShoutsCache.lock:
|
||||
return ShoutsCache.top_overall[(page - 1) * size : page * size]
|
||||
|
||||
|
||||
@query.field("recentPublished")
|
||||
async def recent_published(_, info, page, size):
|
||||
async with ShoutsCache.lock:
|
||||
return ShoutsCache.recent_published[(page - 1) * size : page * size]
|
||||
|
||||
|
||||
@query.field("recentAll")
|
||||
async def recent_all(_, info, page, size):
|
||||
async with ShoutsCache.lock:
|
||||
return ShoutsCache.recent_all[(page - 1) * size : page * size]
|
||||
|
||||
|
||||
@query.field("recentReacted")
|
||||
async def recent_reacted(_, info, page, size):
|
||||
async with ShoutsCache.lock:
|
||||
return ShoutsCache.recent_reacted[(page - 1) * size : page * size]
|
||||
|
||||
|
||||
@mutation.field("viewShout")
|
||||
async def view_shout(_, info, slug):
|
||||
await ViewedStorage.inc_shout(slug)
|
||||
return {"error" : ""}
|
||||
return {"error": ""}
|
||||
|
||||
|
||||
@query.field("getShoutBySlug")
|
||||
async def get_shout_by_slug(_, info, slug):
|
||||
all_fields = [node.name.value for node in info.field_nodes[0].selection_set.selections]
|
||||
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]
|
||||
shout = {}
|
||||
with local_session() as session:
|
||||
try: s = text(open('src/queries/shout-by-slug.sql', 'r').read() % slug)
|
||||
except: pass
|
||||
shout = session.query(Shout).\
|
||||
options(select_options).\
|
||||
filter(Shout.slug == slug).first()
|
||||
try:
|
||||
s = text(open("src/queries/shout-by-slug.sql", "r").read() % slug)
|
||||
except:
|
||||
pass
|
||||
shout = (
|
||||
session.query(Shout)
|
||||
.options(select_options)
|
||||
.filter(Shout.slug == slug)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not shout:
|
||||
print(f"shout with slug {slug} not exist")
|
||||
return {"error" : "shout not found"}
|
||||
return {"error": "shout not found"}
|
||||
else:
|
||||
for a in shout.authors:
|
||||
a.caption = await ShoutAuthorStorage.get_author_caption(slug, a.slug)
|
||||
return shout
|
||||
|
||||
|
||||
@query.field("shoutsByTopics")
|
||||
async def shouts_by_topics(_, info, slugs, page, size):
|
||||
page = page - 1
|
||||
with local_session() as session:
|
||||
shouts = session.query(Shout).\
|
||||
join(ShoutTopic).\
|
||||
where(and_(ShoutTopic.topic.in_(slugs), Shout.publishedAt != None)).\
|
||||
order_by(desc(Shout.publishedAt)).\
|
||||
limit(size).\
|
||||
offset(page * size)
|
||||
|
||||
shouts = (
|
||||
session.query(Shout)
|
||||
.join(ShoutTopic)
|
||||
.where(and_(ShoutTopic.topic.in_(slugs), Shout.publishedAt != None))
|
||||
.order_by(desc(Shout.publishedAt))
|
||||
.limit(size)
|
||||
.offset(page * size)
|
||||
)
|
||||
|
||||
for s in shouts:
|
||||
for a in s.authors:
|
||||
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
|
||||
return shouts
|
||||
|
||||
|
||||
@query.field("shoutsByCollection")
|
||||
async def shouts_by_topics(_, info, collection, page, size):
|
||||
page = page - 1
|
||||
shouts = []
|
||||
with local_session() as session:
|
||||
shouts = session.query(Shout).\
|
||||
join(ShoutCollection, ShoutCollection.collection == collection).\
|
||||
where(and_(ShoutCollection.shout == Shout.slug, Shout.publishedAt != None)).\
|
||||
order_by(desc(Shout.publishedAt)).\
|
||||
limit(size).\
|
||||
offset(page * size)
|
||||
shouts = (
|
||||
session.query(Shout)
|
||||
.join(ShoutCollection, ShoutCollection.collection == collection)
|
||||
.where(and_(ShoutCollection.shout == Shout.slug, Shout.publishedAt != None))
|
||||
.order_by(desc(Shout.publishedAt))
|
||||
.limit(size)
|
||||
.offset(page * size)
|
||||
)
|
||||
for s in shouts:
|
||||
for a in s.authors:
|
||||
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
|
||||
return shouts
|
||||
|
||||
|
||||
@query.field("shoutsByAuthors")
|
||||
async def shouts_by_authors(_, info, slugs, page, size):
|
||||
page = page - 1
|
||||
with local_session() as session:
|
||||
|
||||
shouts = session.query(Shout).\
|
||||
join(ShoutAuthor).\
|
||||
where(and_(ShoutAuthor.user.in_(slugs), Shout.publishedAt != None)).\
|
||||
order_by(desc(Shout.publishedAt)).\
|
||||
limit(size).\
|
||||
offset(page * size)
|
||||
|
||||
shouts = (
|
||||
session.query(Shout)
|
||||
.join(ShoutAuthor)
|
||||
.where(and_(ShoutAuthor.user.in_(slugs), Shout.publishedAt != None))
|
||||
.order_by(desc(Shout.publishedAt))
|
||||
.limit(size)
|
||||
.offset(page * size)
|
||||
)
|
||||
|
||||
for s in shouts:
|
||||
for a in s.authors:
|
||||
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
|
||||
return shouts
|
||||
|
||||
|
||||
SINGLE_COMMUNITY = True
|
||||
|
||||
|
||||
@query.field("shoutsByCommunities")
|
||||
async def shouts_by_communities(_, info, slugs, page, size):
|
||||
if SINGLE_COMMUNITY:
|
||||
if SINGLE_COMMUNITY:
|
||||
return recent_published(_, info, page, size)
|
||||
else:
|
||||
page = page - 1
|
||||
with local_session() as session:
|
||||
#TODO fix postgres high load
|
||||
shouts = session.query(Shout).distinct().\
|
||||
join(ShoutTopic).\
|
||||
where(and_(Shout.publishedAt != None,\
|
||||
ShoutTopic.topic.in_(\
|
||||
select(Topic.slug).where(Topic.community.in_(slugs))\
|
||||
))).\
|
||||
order_by(desc(Shout.publishedAt)).\
|
||||
limit(size).\
|
||||
offset(page * size)
|
||||
|
||||
# TODO fix postgres high load
|
||||
shouts = (
|
||||
session.query(Shout)
|
||||
.distinct()
|
||||
.join(ShoutTopic)
|
||||
.where(
|
||||
and_(
|
||||
Shout.publishedAt != None,
|
||||
ShoutTopic.topic.in_(
|
||||
select(Topic.slug).where(Topic.community.in_(slugs))
|
||||
),
|
||||
)
|
||||
)
|
||||
.order_by(desc(Shout.publishedAt))
|
||||
.limit(size)
|
||||
.offset(page * size)
|
||||
)
|
||||
|
||||
for s in shouts:
|
||||
for a in s.authors:
|
||||
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
|
||||
return shouts
|
||||
|
||||
|
||||
@mutation.field("follow")
|
||||
@login_required
|
||||
async def follow(_, info, what, slug):
|
||||
@@ -159,10 +192,11 @@ async def follow(_, info, what, slug):
|
||||
elif what == "REACTIONS":
|
||||
reactions_follow(user, slug)
|
||||
except Exception as e:
|
||||
return {"error" : str(e)}
|
||||
return {"error": str(e)}
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
@mutation.field("unfollow")
|
||||
@login_required
|
||||
async def unfollow(_, info, what, slug):
|
||||
@@ -178,6 +212,6 @@ async def unfollow(_, info, what, slug):
|
||||
elif what == "REACTIONS":
|
||||
reactions_unfollow(user, slug)
|
||||
except Exception as e:
|
||||
return {"error" : str(e)}
|
||||
return {"error": str(e)}
|
||||
|
||||
return {}
|
||||
|
Reference in New Issue
Block a user