followers-migrated

This commit is contained in:
tonyrewin 2022-09-18 17:29:21 +03:00
parent 60c7a1571b
commit 1122fe580b
12 changed files with 144 additions and 76 deletions

View File

@ -4,10 +4,11 @@ from dateutil.parser import parse as date_parse
from base.orm import local_session from base.orm import local_session
from migration.html2text import html2text from migration.html2text import html2text
from orm import Reaction, User from orm.user import User
from orm.reaction import ReactionKind from orm.topic import TopicFollower
from orm.reaction import Reaction, ReactionKind
from services.stat.reacted import ReactedStorage from services.stat.reacted import ReactedStorage
from orm.shout import ShoutReactionsFollower
ts = datetime.now() ts = datetime.now()
@ -74,8 +75,42 @@ async def migrate(entry, storage):
# creating reaction from old comment # creating reaction from old comment
reaction = Reaction.create(**reaction_dict) reaction = Reaction.create(**reaction_dict)
session.add(reaction)
await ReactedStorage.react(reaction) await ReactedStorage.react(reaction)
# creating shout's reactions following for reaction author
following1 = session.query(
ShoutReactionsFollower
).where(
ShoutReactionsFollower.follower == reaction_dict["createdBy"]
).filter(
ShoutReactionsFollower.shout == reaction.shout
).first()
if not following1:
following1 = ShoutReactionsFollower.create(
follower=reaction_dict["createdBy"],
shout=reaction.shout,
auto=True
)
session.add(following1)
# creating topics followings for reaction author
for t in shout_dict["topics"]:
tf = session.query(
TopicFollower
).where(
TopicFollower.follower == reaction_dict["createdBy"]
).filter(
TopicFollower.topic == t
).first()
if not tf:
topic_following = TopicFollower.create(
follower=reaction_dict["createdBy"],
topic=t,
auto=True
)
session.add(topic_following)
reaction_dict["id"] = reaction.id reaction_dict["id"] = reaction.id
for comment_rating_old in entry.get("ratings", []): for comment_rating_old in entry.get("ratings", []):
rater = ( rater = (
@ -83,18 +118,13 @@ async def migrate(entry, storage):
.filter(User.oid == comment_rating_old["createdBy"]) .filter(User.oid == comment_rating_old["createdBy"])
.first() .first()
) )
reactedBy = (
rater
if rater
else session.query(User).filter(User.slug == "noname").first()
)
re_reaction_dict = { re_reaction_dict = {
"shout": reaction_dict["shout"], "shout": reaction_dict["shout"],
"replyTo": reaction.id, "replyTo": reaction.id,
"kind": ReactionKind.LIKE "kind": ReactionKind.LIKE
if comment_rating_old["value"] > 0 if comment_rating_old["value"] > 0
else ReactionKind.DISLIKE, else ReactionKind.DISLIKE,
"createdBy": reactedBy.slug if reactedBy else "discours", "createdBy": rater.slug if rater else "discours",
} }
cts = comment_rating_old.get("createdAt") cts = comment_rating_old.get("createdAt")
if cts: if cts:
@ -102,11 +132,27 @@ async def migrate(entry, storage):
try: try:
# creating reaction from old rating # creating reaction from old rating
rr = Reaction.create(**re_reaction_dict) rr = Reaction.create(**re_reaction_dict)
following2 = session.query(
ShoutReactionsFollower
).where(
ShoutReactionsFollower.follower == re_reaction_dict['createdBy']
).filter(
ShoutReactionsFollower.shout == rr.shout
).first()
if not following2:
following2 = ShoutReactionsFollower.create(
follower=re_reaction_dict['createdBy'],
shout=rr.shout,
auto=True
)
session.add(following2)
session.add(rr)
await ReactedStorage.react(rr) await ReactedStorage.react(rr)
except Exception as e: except Exception as e:
print("[migration] comment rating error: %r" % re_reaction_dict) print("[migration] comment rating error: %r" % re_reaction_dict)
raise e raise e
session.commit()
else: else:
print( print(
"[migration] error: cannot find shout for comment %r" "[migration] error: cannot find shout for comment %r"
@ -126,6 +172,15 @@ def migrate_2stage(rr, old_new_id):
comment = session.query(Reaction).filter(Reaction.id == new_id).first() comment = session.query(Reaction).filter(Reaction.id == new_id).first()
comment.replyTo = old_new_id.get(reply_oid) comment.replyTo = old_new_id.get(reply_oid)
session.add(comment) session.add(comment)
srf = session.query(ShoutReactionsFollower).where(
ShoutReactionsFollower.shout == comment.shout
).filter(
ShoutReactionsFollower.follower == comment.createdBy
).first()
if not srf:
srf = ShoutReactionsFollower.create(shout=comment.shout, follower=comment.createdBy, auto=True)
session.add(srf)
session.commit() session.commit()
if not rr["body"]: if not rr["body"]:
raise Exception(rr) raise Exception(rr)

View File

@ -8,7 +8,7 @@ from base.orm import local_session
from migration.extract import prepare_html_body from migration.extract import prepare_html_body
from orm.community import Community from orm.community import Community
from orm.reaction import Reaction, ReactionKind from orm.reaction import Reaction, ReactionKind
from orm.shout import Shout, ShoutTopic, User from orm.shout import Shout, ShoutTopic, User, ShoutReactionsFollower
from orm.topic import TopicFollower from orm.topic import TopicFollower
from services.stat.reacted import ReactedStorage from services.stat.reacted import ReactedStorage
from services.stat.viewed import ViewedByDay from services.stat.viewed import ViewedByDay
@ -115,12 +115,8 @@ async def migrate(entry, storage):
category = entry["category"] category = entry["category"]
mainTopic = topics_by_oid.get(category) mainTopic = topics_by_oid.get(category)
if mainTopic: if mainTopic:
r["mainTopic"] = storage["replacements"].get( r["mainTopic"] = storage["replacements"].get(mainTopic["slug"], mainTopic["slug"])
mainTopic["slug"], mainTopic["slug"] topic_oids = [category, ]
)
topic_oids = [
category,
]
topic_oids.extend(entry.get("tags", [])) topic_oids.extend(entry.get("tags", []))
for oid in topic_oids: for oid in topic_oids:
if oid in storage["topics"]["by_oid"]: if oid in storage["topics"]["by_oid"]:
@ -137,7 +133,6 @@ async def migrate(entry, storage):
r["body"] = prepare_html_body(entry) r["body"] = prepare_html_body(entry)
# save shout to db # save shout to db
s = object() s = object()
shout_dict = r.copy() shout_dict = r.copy()
user = None user = None
@ -167,18 +162,29 @@ async def migrate(entry, storage):
storage["users"]["by_oid"][entry["_id"]] = userdata storage["users"]["by_oid"][entry["_id"]] = userdata
if not user: if not user:
raise Exception("could not get a user") raise Exception("could not get a user")
shout_dict["authors"] = [ shout_dict["authors"] = [user, ]
user,
]
# TODO: subscribe shout user on shout topics
try: try:
s = Shout.create(**shout_dict) s = Shout.create(**shout_dict)
with local_session() as session: with local_session() as session:
topics = session.query(ShoutTopic).where(ShoutTopic.shout == s.slug).all() topics = session.query(ShoutTopic).where(ShoutTopic.shout == s.slug).all()
for tpc in topics: for tpc in topics:
TopicFollower.create(topic=tpc.slug, follower=userslug) tf = session.query(TopicFollower).where(TopicFollower.follower ==
userslug).filter(TopicFollower.topic ==
tpc.slug).first()
if not tf:
tf = TopicFollower.create(topic=tpc.slug, follower=userslug, auto=True)
session.add(tf)
await TopicStorage.update_topic(tpc.slug) await TopicStorage.update_topic(tpc.slug)
srf = session.query(ShoutReactionsFollower).where(
ShoutReactionsFollower.shout == s.slug
).filter(
ShoutReactionsFollower.follower == userslug
).first()
if not srf:
srf = ShoutReactionsFollower.create(shout=s.slug, follower=userslug, auto=True)
session.add(srf)
session.commit()
except IntegrityError as e: except IntegrityError as e:
with local_session() as session: with local_session() as session:
s = session.query(Shout).filter(Shout.slug == shout_dict["slug"]).first() s = session.query(Shout).filter(Shout.slug == shout_dict["slug"]).first()

View File

@ -3,7 +3,7 @@ from sqlalchemy.exc import IntegrityError
from base.orm import local_session from base.orm import local_session
from migration.html2text import html2text from migration.html2text import html2text
from orm import User, UserRating from orm.user import User, UserRating, AuthorFollower
def migrate(entry): def migrate(entry):
@ -118,6 +118,13 @@ def migrate_2stage(entry, id_map):
with local_session() as session: with local_session() as session:
try: try:
user_rating = UserRating.create(**user_rating_dict) user_rating = UserRating.create(**user_rating_dict)
if user_rating_dict['value'] > 0:
af = AuthorFollower.create(
author=user_rating_dict['user'],
follower=user_rating_dict['rater'],
auto=True
)
session.add(af)
session.add(user_rating) session.add(user_rating)
session.commit() session.commit()
except IntegrityError: except IntegrityError:

View File

@ -1,6 +1,6 @@
from datetime import datetime from datetime import datetime
from sqlalchemy import Column, String, ForeignKey, DateTime from sqlalchemy import Column, String, ForeignKey, DateTime, Boolean
from base.orm import Base, local_session from base.orm import Base, local_session
@ -14,6 +14,7 @@ class CommunityFollower(Base):
createdAt = Column( createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at" DateTime, nullable=False, default=datetime.now, comment="Created at"
) )
auto = Column(Boolean, nullable=False, default=False)
class Community(Base): class Community(Base):

View File

@ -46,29 +46,25 @@ class Shout(Base):
id = None # type: ignore id = None # type: ignore
slug = Column(String, primary_key=True) slug = Column(String, primary_key=True)
community = Column( community = Column(Integer, ForeignKey("community.id"), nullable=False, comment="Community")
Integer, ForeignKey("community.id"), nullable=False, comment="Community"
)
body = Column(String, nullable=False, comment="Body") body = Column(String, nullable=False, comment="Body")
createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at"
)
updatedAt = Column(DateTime, nullable=True, comment="Updated at")
replyTo = Column(ForeignKey("shout.slug"), nullable=True)
versionOf = Column(ForeignKey("shout.slug"), nullable=True)
tags = Column(String, nullable=True)
publishedBy = Column(ForeignKey("user.id"), nullable=True)
publishedAt = Column(DateTime, nullable=True)
cover = Column(String, nullable=True)
title = Column(String, nullable=True) title = Column(String, nullable=True)
subtitle = Column(String, nullable=True) subtitle = Column(String, nullable=True)
layout = Column(String, nullable=True) layout = Column(String, nullable=True)
reactions = relationship(lambda: Reaction) mainTopic = Column(ForeignKey("topic.slug"), nullable=True)
cover = Column(String, nullable=True)
authors = relationship(lambda: User, secondary=ShoutAuthor.__tablename__) authors = relationship(lambda: User, secondary=ShoutAuthor.__tablename__)
topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__)
mainTopic = Column(ForeignKey("topic.slug"), nullable=True) reactions = relationship(lambda: Reaction)
visibleFor = relationship(lambda: User, secondary=ShoutAllowed.__tablename__) visibleFor = relationship(lambda: User, secondary=ShoutAllowed.__tablename__)
draft = Column(Boolean, default=True)
createdAt = Column(DateTime, nullable=False, default=datetime.now, comment="Created at")
updatedAt = Column(DateTime, nullable=True, comment="Updated at")
publishedAt = Column(DateTime, nullable=True)
versionOf = Column(ForeignKey("shout.slug"), nullable=True)
draft = Column(Boolean, default=False)
lang = Column(String, default='ru')
oid = Column(String, nullable=True) oid = Column(String, nullable=True)
@property @property

View File

@ -1,6 +1,6 @@
from datetime import datetime from datetime import datetime
from sqlalchemy import Column, String, ForeignKey, DateTime, JSON as JSONType from sqlalchemy import Column, Boolean, String, ForeignKey, DateTime, JSON as JSONType
from base.orm import Base from base.orm import Base
@ -22,6 +22,7 @@ class TopicFollower(Base):
createdAt = Column( createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at" DateTime, nullable=False, default=datetime.now, comment="Created at"
) )
auto = Column(Boolean, nullable=False, default=False)
class Topic(Base): class Topic(Base):

View File

@ -50,6 +50,7 @@ class AuthorFollower(Base):
createdAt = Column( createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at" DateTime, nullable=False, default=datetime.now, comment="Created at"
) )
auto = Column(Boolean, nullable=False, default=False)
class User(Base): class User(Base):

View File

@ -93,7 +93,10 @@ async def get_communities(_, info):
def community_follow(user, slug): def community_follow(user, slug):
CommunityFollower.create(follower=user.slug, community=slug) with local_session() as session:
cf = CommunityFollower.create(follower=user.slug, community=slug)
session.add(cf)
session.commit()
def community_unfollow(user, slug): def community_unfollow(user, slug):

View File

@ -165,7 +165,10 @@ async def rate_user(_, info, slug, value):
# for mutation.field("follow") # for mutation.field("follow")
def author_follow(user, slug): def author_follow(user, slug):
AuthorFollower.create(follower=user.slug, author=slug) with local_session() as session:
af = AuthorFollower.create(follower=user.slug, author=slug)
session.add(af)
session.commit()
# for mutation.field("unfollow") # for mutation.field("unfollow")

View File

@ -14,25 +14,22 @@ from services.stat.reacted import ReactedStorage
def reactions_follow(user, slug, auto=False): def reactions_follow(user, slug, auto=False):
with local_session() as session: with local_session() as session:
fw = ( following = (
session.query(ShoutReactionsFollower) session.query(ShoutReactionsFollower)
.filter( .filter(
ShoutReactionsFollower.follower == user.slug, ShoutReactionsFollower.follower == user.slug,
ShoutReactionsFollower.shout == slug, ShoutReactionsFollower.shout == slug
) )
.first() .first()
) )
if auto and fw: if not following:
return following = ShoutReactionsFollower.create(
elif not auto and fw: follower=user.slug,
if bool(fw.deletedAt): shout=slug,
fw.deletedAt = None auto=auto
fw.auto = False )
session.commit() session.add(following)
return session.commit()
# print("[resolvers.reactions] was followed before")
ShoutReactionsFollower.create(follower=user.slug, shout=slug, auto=auto)
def reactions_unfollow(user, slug): def reactions_unfollow(user, slug):
@ -45,14 +42,9 @@ def reactions_unfollow(user, slug):
) )
.first() .first()
) )
if not following: if following:
# print("[resolvers.reactions] was not followed", slug)
return
if following.auto:
following.deletedAt = datetime.now()
else:
session.delete(following) session.delete(following)
session.commit() session.commit()
@mutation.field("createReaction") @mutation.field("createReaction")

View File

@ -50,20 +50,23 @@ async def create_topic(_, _info, inp):
@login_required @login_required
async def update_topic(_, _info, inp): async def update_topic(_, _info, inp):
slug = inp["slug"] slug = inp["slug"]
session = local_session() with local_session() as session:
topic = session.query(Topic).filter(Topic.slug == slug).first() topic = session.query(Topic).filter(Topic.slug == slug).first()
if not topic: if not topic:
return {"error": "topic not found"} return {"error": "topic not found"}
topic.update(**inp) else:
session.commit() topic.update(**inp)
session.close() session.commit()
await TopicStorage.update_topic(topic.slug) await TopicStorage.update_topic(topic.slug)
return {"topic": topic} return {"topic": topic}
async def topic_follow(user, slug): async def topic_follow(user, slug):
TopicFollower.create(topic=slug, follower=user.slug) with local_session() as session:
await TopicStorage.update_topic(slug) following = TopicFollower.create(topic=slug, follower=user.slug)
session.add(following)
session.commit()
await TopicStorage.update_topic(slug)
async def topic_unfollow(user, slug): async def topic_unfollow(user, slug):

View File

@ -112,7 +112,7 @@ async def get_search_results(_, _info, query, offset, limit):
for s in shouts: for s in shouts:
for a in s.authors: for a in s.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug) a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
s.stat.relevance = 1 # FIXME s.stat.relevance = 1 # FIXME: expecting search engine rated relevance
return shouts return shouts