mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 11:26:56 -08:00
federate votes
This commit is contained in:
parent
bfc4b243bf
commit
08a771daf0
4 changed files with 139 additions and 4 deletions
|
@ -7,10 +7,11 @@ from flask import request, Response, render_template, current_app, abort, jsonif
|
||||||
|
|
||||||
from app.activitypub.signature import HttpSignature
|
from app.activitypub.signature import HttpSignature
|
||||||
from app.community.routes import show_community
|
from app.community.routes import show_community
|
||||||
from app.models import User, Community, CommunityJoinRequest, CommunityMember, CommunityBan, ActivityPubLog
|
from app.models import User, Community, CommunityJoinRequest, CommunityMember, CommunityBan, ActivityPubLog, Post, \
|
||||||
|
PostReply, Instance, PostVote, PostReplyVote
|
||||||
from app.activitypub.util import public_key, users_total, active_half_year, active_month, local_posts, local_comments, \
|
from app.activitypub.util import public_key, users_total, active_half_year, active_month, local_posts, local_comments, \
|
||||||
post_to_activity, find_actor_or_create
|
post_to_activity, find_actor_or_create
|
||||||
from app.utils import gibberish
|
from app.utils import gibberish, get_setting
|
||||||
|
|
||||||
INBOX = []
|
INBOX = []
|
||||||
|
|
||||||
|
@ -222,7 +223,48 @@ def shared_inbox():
|
||||||
if 'type' in request_json:
|
if 'type' in request_json:
|
||||||
activity_log.activity_type = request_json['type']
|
activity_log.activity_type = request_json['type']
|
||||||
if request_json['type'] == 'Announce':
|
if request_json['type'] == 'Announce':
|
||||||
...
|
if request_json['object']['type'] == 'Like' or request_json['object']['type'] == 'Dislike':
|
||||||
|
activity_log.activity_type = request_json['object']['type']
|
||||||
|
vote_effect = 1.0 if request_json['object']['type'] == 'Like' else -1.0
|
||||||
|
if vote_effect < 0 and get_setting('allow_dislike', True) is False:
|
||||||
|
activity_log.exception_message = 'Dislike ignored because of allow_dislike setting'
|
||||||
|
else:
|
||||||
|
user_ap_id = request_json['object']['actor']
|
||||||
|
liked_ap_id = request_json['object']['object']
|
||||||
|
user = find_actor_or_create(user_ap_id)
|
||||||
|
vote_weight = 1.0
|
||||||
|
if user.ap_domain:
|
||||||
|
instance = Instance.query.filter_by(domain=user.ap_domain).fetch()
|
||||||
|
if instance:
|
||||||
|
vote_weight = instance.vote_weight
|
||||||
|
liked = find_liked_object(liked_ap_id)
|
||||||
|
# insert into voted table
|
||||||
|
if isinstance(liked, Post):
|
||||||
|
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=liked.id).first()
|
||||||
|
if existing_vote:
|
||||||
|
existing_vote.effect = vote_effect * vote_weight
|
||||||
|
else:
|
||||||
|
vote = PostVote(user_id=user.id, author_id=liked.user_id, post_id=liked.id,
|
||||||
|
effect=vote_effect * vote_weight)
|
||||||
|
db.session.add(vote)
|
||||||
|
db.session.commit()
|
||||||
|
activity_log.result = 'success'
|
||||||
|
elif isinstance(liked, PostReply):
|
||||||
|
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=liked.id).first()
|
||||||
|
if existing_vote:
|
||||||
|
existing_vote.effect = vote_effect * vote_weight
|
||||||
|
else:
|
||||||
|
vote = PostReplyVote(user_id=user.id, author_id=liked.user_id, post_reply_id=liked.id,
|
||||||
|
effect=vote_effect * vote_weight)
|
||||||
|
db.session.add(vote)
|
||||||
|
db.session.commit()
|
||||||
|
activity_log.result = 'success'
|
||||||
|
else:
|
||||||
|
activity_log.result='failure'
|
||||||
|
activity_log.exception_message = 'Could not detect type of like'
|
||||||
|
if activity_log.result == 'success':
|
||||||
|
... # todo: recalculate 'hotness' of liked post/reply
|
||||||
|
|
||||||
# remote user wants to follow one of our communities
|
# remote user wants to follow one of our communities
|
||||||
elif request_json['type'] == 'Follow':
|
elif request_json['type'] == 'Follow':
|
||||||
user_ap_id = request_json['actor']
|
user_ap_id = request_json['actor']
|
||||||
|
|
|
@ -49,6 +49,7 @@ def register(app):
|
||||||
db.configure_mappers()
|
db.configure_mappers()
|
||||||
db.create_all()
|
db.create_all()
|
||||||
db.session.append(Settings(name='allow_nsfw', value=json.dumps(False)))
|
db.session.append(Settings(name='allow_nsfw', value=json.dumps(False)))
|
||||||
|
db.session.append(Settings(name='allow_dislike', value=json.dumps(True)))
|
||||||
db.session.append(BannedInstances(domain='lemmygrad.ml'))
|
db.session.append(BannedInstances(domain='lemmygrad.ml'))
|
||||||
db.session.append(BannedInstances(domain='gab.com'))
|
db.session.append(BannedInstances(domain='gab.com'))
|
||||||
db.session.append(BannedInstances(domain='exploding-heads.com'))
|
db.session.append(BannedInstances(domain='exploding-heads.com'))
|
||||||
|
|
|
@ -117,6 +117,7 @@ class User(UserMixin, db.Model):
|
||||||
newsletter = db.Column(db.Boolean, default=True)
|
newsletter = db.Column(db.Boolean, default=True)
|
||||||
bounces = db.Column(db.SmallInteger, default=0)
|
bounces = db.Column(db.SmallInteger, default=0)
|
||||||
timezone = db.Column(db.String(20))
|
timezone = db.Column(db.String(20))
|
||||||
|
reputation = db.Column(db.Float, default=0.0)
|
||||||
stripe_customer_id = db.Column(db.String(50))
|
stripe_customer_id = db.Column(db.String(50))
|
||||||
stripe_subscription_id = db.Column(db.String(50))
|
stripe_subscription_id = db.Column(db.String(50))
|
||||||
searchable = db.Column(db.Boolean, default=True)
|
searchable = db.Column(db.Boolean, default=True)
|
||||||
|
@ -349,6 +350,7 @@ class Instance(db.Model):
|
||||||
inbox = db.Column(db.String(256))
|
inbox = db.Column(db.String(256))
|
||||||
shared_inbox = db.Column(db.String(256))
|
shared_inbox = db.Column(db.String(256))
|
||||||
outbox = db.Column(db.String(256))
|
outbox = db.Column(db.String(256))
|
||||||
|
vote_weight = db.Column(db.Float, default=1.0)
|
||||||
|
|
||||||
|
|
||||||
class Settings(db.Model):
|
class Settings(db.Model):
|
||||||
|
@ -374,11 +376,29 @@ class UserFollowRequest(db.Model):
|
||||||
follow_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
follow_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
|
|
||||||
|
|
||||||
|
class PostVote(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
|
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
|
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
|
||||||
|
effect = db.Column(db.Float)
|
||||||
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
|
||||||
|
|
||||||
|
class PostReplyVote(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
|
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
|
post_reply_id = db.Column(db.Integer, db.ForeignKey('post_reply.id'))
|
||||||
|
effect = db.Column(db.Float)
|
||||||
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
|
||||||
|
|
||||||
# save every activity to a log, to aid debugging
|
# save every activity to a log, to aid debugging
|
||||||
class ActivityPubLog(db.Model):
|
class ActivityPubLog(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
direction = db.Column(db.String(3)) # 'in' or 'out'
|
direction = db.Column(db.String(3)) # 'in' or 'out'
|
||||||
activity_id = db.Column(db.String(100), indexed=True)
|
activity_id = db.Column(db.String(100), index=True)
|
||||||
activity_type = db.Column(db.String(50)) # e.g. 'Follow', 'Accept', 'Like', etc
|
activity_type = db.Column(db.String(50)) # e.g. 'Follow', 'Accept', 'Like', etc
|
||||||
activity_json = db.Column(db.Text) # the full json of the activity
|
activity_json = db.Column(db.Text) # the full json of the activity
|
||||||
result = db.Column(db.String(10)) # 'success' or 'failure'
|
result = db.Column(db.String(10)) # 'success' or 'failure'
|
||||||
|
|
72
migrations/versions/6b84580a94cd_voting.py
Normal file
72
migrations/versions/6b84580a94cd_voting.py
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
"""voting
|
||||||
|
|
||||||
|
Revision ID: 6b84580a94cd
|
||||||
|
Revises: f032dbdfbd1d
|
||||||
|
Create Date: 2023-09-10 19:59:15.735823
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '6b84580a94cd'
|
||||||
|
down_revision = 'f032dbdfbd1d'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('post_vote',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('author_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('post_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('effect', sa.Float(), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['author_id'], ['user.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['post_id'], ['post.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('post_reply_vote',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('author_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('post_reply_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('effect', sa.Float(), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['author_id'], ['user.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['post_reply_id'], ['post_reply.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
with op.batch_alter_table('activity_pub_log', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('activity_id', sa.String(length=100), nullable=True))
|
||||||
|
batch_op.create_index(batch_op.f('ix_activity_pub_log_activity_id'), ['activity_id'], unique=False)
|
||||||
|
|
||||||
|
with op.batch_alter_table('instance', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('vote_weight', sa.Float(), nullable=True))
|
||||||
|
|
||||||
|
with op.batch_alter_table('user', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('reputation', sa.Float(), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('user', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('reputation')
|
||||||
|
|
||||||
|
with op.batch_alter_table('instance', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('vote_weight')
|
||||||
|
|
||||||
|
with op.batch_alter_table('activity_pub_log', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_activity_pub_log_activity_id'))
|
||||||
|
batch_op.drop_column('activity_id')
|
||||||
|
|
||||||
|
op.drop_table('post_reply_vote')
|
||||||
|
op.drop_table('post_vote')
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in a new issue