save incoming hashtags during federation #184

This commit is contained in:
rimu 2024-05-11 13:45:04 +12:00
parent c498146917
commit c869c47e9f
3 changed files with 74 additions and 2 deletions

View file

@ -13,7 +13,7 @@ from sqlalchemy import text, func
from app import db, cache, constants, celery from app import db, cache, constants, celery
from app.models import User, Post, Community, BannedInstances, File, PostReply, AllowedInstances, Instance, utcnow, \ from app.models import User, Post, Community, BannedInstances, File, PostReply, AllowedInstances, Instance, utcnow, \
PostVote, PostReplyVote, ActivityPubLog, Notification, Site, CommunityMember, InstanceRole, Report, Conversation, \ PostVote, PostReplyVote, ActivityPubLog, Notification, Site, CommunityMember, InstanceRole, Report, Conversation, \
Language Language, Tag
from app.activitypub.signature import signed_get_request from app.activitypub.signature import signed_get_request
import time import time
import base64 import base64
@ -374,6 +374,23 @@ def find_language_or_create(code: str, name: str) -> Language:
return new_language return new_language
def find_hashtag_or_create(hashtag: str) -> Tag:
if hashtag is None or hashtag == '':
return None
hashtag = hashtag.strip()
if hashtag[0] == '#':
hashtag = hashtag[1:]
existing_tag = Tag.query.filter(Tag.name == hashtag.lower()).first()
if existing_tag:
return existing_tag
else:
new_tag = Tag(name=hashtag.lower(), display_as=hashtag)
db.session.add(new_tag)
return new_tag
def extract_domain_and_actor(url_string: str): def extract_domain_and_actor(url_string: str):
# Parse the URL # Parse the URL
parsed_url = urlparse(url_string) parsed_url = urlparse(url_string)
@ -765,6 +782,13 @@ def post_json_to_model(activity_log, post_json, user, community) -> Post:
if language: if language:
post.language_id = language.id post.language_id = language.id
if 'tag' in post_json:
for json_tag in post_json['tag']:
if json_tag['type'] == 'Hashtag':
hashtag = find_hashtag_or_create(json_tag['name'])
if hashtag:
post.tags.append(hashtag)
if post is not None: if post is not None:
if 'image' in post_json and post.image is None: if 'image' in post_json and post.image is None:
image = File(source_url=post_json['image']['url']) image = File(source_url=post_json['image']['url'])
@ -1496,6 +1520,12 @@ def create_post(activity_log: ActivityPubLog, community: Community, request_json
language = find_language_or_create(request_json['object']['language']['identifier'], language = find_language_or_create(request_json['object']['language']['identifier'],
request_json['object']['language']['name']) request_json['object']['language']['name'])
post.language_id = language.id post.language_id = language.id
if 'tag' in request_json['object'] and isinstance(request_json['object']['tag'], list):
for json_tag in request_json['object']['tag']:
if json_tag['type'] == 'Hashtag':
hashtag = find_hashtag_or_create(json_tag['name'])
if hashtag:
post.tags.append(hashtag)
if 'image' in request_json['object'] and post.image is None: if 'image' in request_json['object'] and post.image is None:
image = File(source_url=request_json['object']['image']['url']) image = File(source_url=request_json['object']['image']['url'])
db.session.add(image) db.session.add(image)
@ -1721,6 +1751,13 @@ def update_post_from_activity(post: Post, request_json: dict):
post.nsfl = True post.nsfl = True
elif 'nsfl' in request_json['object']: elif 'nsfl' in request_json['object']:
post.nsfl = request_json['object']['nsfl'] post.nsfl = request_json['object']['nsfl']
if 'tag' in request_json['object'] and isinstance(request_json['object']['tag'], list):
db.session.execute(text('DELETE FROM "post_tag" WHERE post_id = :post_id'), {'post_id': post.id})
for json_tag in request_json['object']['tag']:
if json_tag['type'] == 'Hashtag':
hashtag = find_hashtag_or_create(json_tag['name'])
if hashtag:
post.tags.append(hashtag)
post.comments_enabled = request_json['object']['commentsEnabled'] if 'commentsEnabled' in request_json['object'] else True post.comments_enabled = request_json['object']['commentsEnabled'] if 'commentsEnabled' in request_json['object'] else True
post.edited_at = utcnow() post.edited_at = utcnow()
db.session.commit() db.session.commit()

View file

@ -172,7 +172,8 @@ class ChatMessage(db.Model):
class Tag(db.Model): class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256)) name = db.Column(db.String(256), index=True) # lowercase version of tag, e.g. solarstorm
display_as = db.Column(db.String(256)) # Version of tag with uppercase letters, e.g. SolarStorm
class Language(db.Model): class Language(db.Model):

View file

@ -0,0 +1,34 @@
"""tag formatting
Revision ID: 20ee24728510
Revises: 9ad372b72d7c
Create Date: 2024-05-11 13:42:31.772863
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '20ee24728510'
down_revision = '9ad372b72d7c'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('tag', schema=None) as batch_op:
batch_op.add_column(sa.Column('display_as', sa.String(length=256), nullable=True))
batch_op.create_index(batch_op.f('ix_tag_name'), ['name'], unique=False)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('tag', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_tag_name'))
batch_op.drop_column('display_as')
# ### end Alembic commands ###