flag low effort commenters

This commit is contained in:
rimu 2024-05-21 22:20:08 +12:00
parent fa953ba976
commit 709980c6f3
13 changed files with 90 additions and 6 deletions

View file

@ -1426,6 +1426,8 @@ def create_post_reply(activity_log: ActivityPubLog, community: Community, in_rep
post_reply.ranking = confidence(post_reply.up_votes, post_reply.down_votes)
db.session.commit()
user.recalculate_avg_comment_length()
# send notification to the post/comment being replied to
if parent_comment_id:
notify_about_post_reply(parent_comment, post_reply)

View file

@ -3,9 +3,10 @@ from time import time
from typing import List, Union
import requests
from bs4 import BeautifulSoup
from flask import current_app, escape, url_for, render_template_string
from flask_login import UserMixin, current_user
from sqlalchemy import or_, text
from sqlalchemy import or_, text, desc
from werkzeug.security import generate_password_hash, check_password_hash
from flask_babel import _, lazy_gettext as _l
from sqlalchemy.orm import backref
@ -615,6 +616,8 @@ class User(UserMixin, db.Model):
markdown_editor = db.Column(db.Boolean, default=False)
interface_language = db.Column(db.String(10)) # a locale that the translation system understands e.g. 'en' or 'en-us'. If empty, use browser default
language_id = db.Column(db.Integer, db.ForeignKey('language.id')) # the default choice in the language dropdown when composing posts & comments
average_comment_length = db.Column(db.Integer)
comment_length_warning = db.Column(db.Integer, default=15)
avatar = db.relationship('File', lazy='joined', foreign_keys=[avatar_id], single_parent=True, cascade="all, delete-orphan")
cover = db.relationship('File', lazy='joined', foreign_keys=[cover_id], single_parent=True, cascade="all, delete-orphan")
@ -808,6 +811,19 @@ class User(UserMixin, db.Model):
else:
self.attitude = (total_upvotes - total_downvotes) / (total_upvotes + total_downvotes)
def recalculate_avg_comment_length(self):
replies = db.session.execute(text('SELECT body, body_html FROM "post_reply" WHERE user_id = :user_id ORDER BY created_at DESC LIMIT 30'),
{'user_id': self.id}).all()
lengths = []
for reply in replies:
if reply.body.strip() != '':
lengths.append(len(reply.body.strip()))
else:
soup = BeautifulSoup(reply.body_html, 'html.parser')
lengths.append(len(soup.get_text()))
if len(lengths) > 5:
self.average_comment_length = math.ceil(sum(lengths) / len(lengths))
def subscribed(self, community_id: int) -> int:
if community_id is None:
return False

View file

@ -111,6 +111,8 @@ def show_post(post_id: int):
db.session.add(reply)
db.session.commit()
current_user.recalculate_avg_comment_length()
notify_about_post_reply(None, reply)
# Subscribe to own comment
@ -671,6 +673,8 @@ def add_reply(post_id: int, comment_id: int):
db.session.add(reply)
db.session.commit()
current_user.recalculate_avg_comment_length()
# Notify subscribers
notify_about_post_reply(in_reply_to, reply)

View file

@ -14,4 +14,8 @@ $super-dark-grey: #424549;
.orangered {
color: orangered;
}
}
.purple {
color: purple;
}

View file

@ -8,6 +8,10 @@ nav, etc which are used site-wide */
color: orangered;
}
.purple {
color: purple;
}
.pl-0 {
padding-left: 0 !important;
}

View file

@ -7,6 +7,10 @@
color: orangered;
}
.purple {
color: purple;
}
.pl-0 {
padding-left: 0 !important;
}

View file

@ -138,7 +138,9 @@
</div>
{% if post.type == POST_TYPE_POLL %}
<div class="post_poll">
{% if poll_results %}
{% if poll_results and poll_total_votes == 0 %}
<p>{{ _('The poll has finished, yet no votes were cast.') }}</p>
{% elif poll_results and poll_total_votes %}
<ul>
{% for choice in poll_choices %}
<li>

View file

@ -100,6 +100,9 @@
{% elif comment['comment'].author.reputation < 0 %}
<span class="fe fe-warning orangered" title="Low reputation."> </span>
{% endif %}
{% if current_user.is_authenticated and current_user.comment_length_warning and comment['comment'].author.average_comment_length and comment['comment'].author.average_comment_length <= current_user.comment_length_warning %}
<span class="fe fe-warning purple" title="{{ _('Usually makes short and low effort comments.') }}"> </span>
{% endif %}
{% endif %}
{% if comment['comment'].author.id == post.author.id %}<span title="Submitter of original post" aria-label="{{ _('Post creator') }}" class="small">[OP]</span>{% endif %}
<span class="text-muted small" aria_label="{{ _('When: ') }}">{{ moment(comment['comment'].posted_at).fromNow(refresh=True) }}{% if comment['comment'].edited_at %}, edited {{ moment(comment['comment'].edited_at).fromNow(refresh=True) }} {% endif %}</span>

View file

@ -35,6 +35,8 @@
{{ render_field(form.markdown_editor) }}
{{ render_field(form.default_sort) }}
{{ render_field(form.theme) }}
{{ render_field(form.comment_length_warning) }}
<small class="field_hint">{{ _('Accounts which usually post comments shorter than this will have a warning. Set to 0 to disable warning.') }}</small>
<h5>Import</h5>
{{ render_field(form.import_file) }}
{{ render_field(form.submit) }}

View file

@ -2,7 +2,7 @@ from flask import session
from flask_login import current_user
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, PasswordField, BooleanField, EmailField, TextAreaField, FileField, \
RadioField, DateField, SelectField
RadioField, DateField, SelectField, IntegerField
from wtforms.fields.choices import SelectMultipleField
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo, Length, Optional
from flask_babel import _, lazy_gettext as _l
@ -50,6 +50,7 @@ class SettingsForm(FlaskForm):
]
default_sort = SelectField(_l('By default, sort posts by'), choices=sorts, validators=[DataRequired()], coerce=str, render_kw={'class': 'form-select'})
theme = SelectField(_l('Theme'), coerce=str, render_kw={'class': 'form-select'})
comment_length_warning = IntegerField(_('Useless comment cutoff length'))
submit = SubmitField(_l('Save settings'))

View file

@ -188,6 +188,7 @@ def change_settings():
current_user.email_unread = form.email_unread.data
current_user.markdown_editor = form.markdown_editor.data
current_user.interface_language = form.interface_language.data
current_user.comment_length_warning = form.comment_length_warning.data
session['ui_language'] = form.interface_language.data
import_file = request.files['import_file']
if propagate_indexable:
@ -227,6 +228,7 @@ def change_settings():
form.theme.data = current_user.theme
form.markdown_editor.data = current_user.markdown_editor
form.interface_language.data = current_user.interface_language
form.comment_length_warning.data = current_user.comment_length_warning
return render_template('user/edit_settings.html', title=_('Edit profile'), form=form, user=current_user,
moderating_communities=moderating_communities(current_user.get_id()),

View file

@ -258,6 +258,13 @@ def markdown_to_text(markdown_text) -> str:
return markdown_text.replace("# ", '')
def html_to_text(html) -> str:
if html is None or html == '':
return ''
soup = BeautifulSoup(html, 'html.parser')
return soup.get_text()
def microblog_content_to_title(html: str) -> str:
title = ''
if '<p>' in html:
@ -267,8 +274,7 @@ def microblog_content_to_title(html: str) -> str:
if title and title.strip() != '' and len(title.strip()) >= 5:
break
else:
soup = BeautifulSoup(html, 'html.parser')
title = soup.get_text()
title = html_to_text(html)
period_index = title.find('.')
question_index = title.find('?')

View file

@ -0,0 +1,34 @@
"""comment length
Revision ID: e76f2067e689
Revises: 05e3a7023a1e
Create Date: 2024-05-21 21:58:22.133194
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'e76f2067e689'
down_revision = '05e3a7023a1e'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('average_comment_length', sa.Integer(), nullable=True))
batch_op.add_column(sa.Column('comment_length_warning', sa.Integer(), 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('comment_length_warning')
batch_op.drop_column('average_comment_length')
# ### end Alembic commands ###