- {% if other_party %}
-
{{ _('Messages with %(name)s', name=other_party.display_name()) }}
+ {% if messages %}
+
{{ _('Messages with %(name)s', name=conversation.member_names(current_user.id)) }}
{{ _('Messages with: ') }}
-
-
diff --git a/app/templates/chat/denied.html b/app/templates/chat/denied.html
new file mode 100644
index 00000000..1e492577
--- /dev/null
+++ b/app/templates/chat/denied.html
@@ -0,0 +1,21 @@
+{% if theme() and file_exists('app/templates/themes/' + theme() + '/base.html') %}
+ {% extends 'themes/' + theme() + '/base.html' %}
+{% else %}
+ {% extends "base.html" %}
+{% endif %} %}
+{% from 'bootstrap/form.html' import render_form %}
+
+{% block app_content %}
+
+
+
+
+
{{ _('Sorry') }}
+
+
{{ _('You have not been using PieFed long enough to be allowed to send messages to people.') }}
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/app/templates/chat/new_message.html b/app/templates/chat/new_message.html
new file mode 100644
index 00000000..3373f53f
--- /dev/null
+++ b/app/templates/chat/new_message.html
@@ -0,0 +1,21 @@
+{% if theme() and file_exists('app/templates/themes/' + theme() + '/base.html') %}
+ {% extends 'themes/' + theme() + '/base.html' %}
+{% else %}
+ {% extends "base.html" %}
+{% endif %} %}
+{% from 'bootstrap/form.html' import render_form %}
+
+{% block app_content %}
+
+
+
+
+
{{ _('New message to "%(recipient_name)s"', recipient_name=recipient.link()) }}
+
+ {{ render_form(form) }}
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/app/templates/chat/report.html b/app/templates/chat/report.html
new file mode 100644
index 00000000..b8a73ab2
--- /dev/null
+++ b/app/templates/chat/report.html
@@ -0,0 +1,21 @@
+{% if theme() and file_exists('app/templates/themes/' + theme() + '/base.html') %}
+ {% extends 'themes/' + theme() + '/base.html' %}
+{% else %}
+ {% extends "base.html" %}
+{% endif %} %}
+{% from 'bootstrap/form.html' import render_form %}
+
+{% block app_content %}
+
+
+
+
+
{{ _('Report conversation with "%(member_names)s"', member_names=conversation.member_names(current_user.id)) }}
+
+ {{ render_form(form) }}
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/app/templates/user/show_profile.html b/app/templates/user/show_profile.html
index 3e20d9b3..66310e56 100644
--- a/app/templates/user/show_profile.html
+++ b/app/templates/user/show_profile.html
@@ -41,11 +41,9 @@
{% endif %}
{% if current_user.is_authenticated %}
- {% if not current_user.created_recently() and current_user.reputation > 10 %}
-
{{ _('Send message') }}
- {% if user.matrix_user_id %}
-
{{ _('Send message using Matrix') }}
- {% endif %}
+
{{ _('Send message') }}
+ {% if user.matrix_user_id %}
+
{{ _('Send message using Matrix') }}
{% endif %}
{% if current_user.id != user.id %}
{% if current_user.has_blocked_user(user.id) %}
diff --git a/app/utils.py b/app/utils.py
index cc8353e4..273687b8 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -389,7 +389,7 @@ def user_cookie_banned() -> bool:
return cookie is not None
-@cache.memoize(timeout=300)
+@cache.memoize(timeout=30)
def banned_ip_addresses() -> List[str]:
ips = IpBan.query.all()
return [ip.ip_address for ip in ips]
diff --git a/migrations/versions/8ca0f0789040_chat_reporting.py b/migrations/versions/8ca0f0789040_chat_reporting.py
new file mode 100644
index 00000000..cff6dba5
--- /dev/null
+++ b/migrations/versions/8ca0f0789040_chat_reporting.py
@@ -0,0 +1,34 @@
+"""chat reporting
+
+Revision ID: 8ca0f0789040
+Revises: b4f7322082f4
+Create Date: 2024-02-19 14:58:13.481708
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '8ca0f0789040'
+down_revision = 'b4f7322082f4'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table('report', schema=None) as batch_op:
+ batch_op.add_column(sa.Column('suspect_conversation_id', sa.Integer(), nullable=True))
+ batch_op.create_foreign_key(None, 'conversation', ['suspect_conversation_id'], ['id'])
+
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table('report', schema=None) as batch_op:
+ batch_op.drop_constraint(None, type_='foreignkey')
+ batch_op.drop_column('suspect_conversation_id')
+
+ # ### end Alembic commands ###
diff --git a/migrations/versions/b4f7322082f4_chat_conversations.py b/migrations/versions/b4f7322082f4_chat_conversations.py
new file mode 100644
index 00000000..934e896b
--- /dev/null
+++ b/migrations/versions/b4f7322082f4_chat_conversations.py
@@ -0,0 +1,61 @@
+"""chat conversations
+
+Revision ID: b4f7322082f4
+Revises: fe1e3fbf5b9d
+Create Date: 2024-02-18 14:54:20.090872
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = 'b4f7322082f4'
+down_revision = 'fe1e3fbf5b9d'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.create_table('conversation',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('user_id', sa.Integer(), nullable=True),
+ sa.Column('reported', sa.Boolean(), nullable=True),
+ sa.Column('read', sa.Boolean(), nullable=True),
+ sa.Column('created_at', sa.DateTime(), nullable=True),
+ sa.Column('updated_at', sa.DateTime(), nullable=True),
+ sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
+ sa.PrimaryKeyConstraint('id')
+ )
+ with op.batch_alter_table('conversation', schema=None) as batch_op:
+ batch_op.create_index(batch_op.f('ix_conversation_user_id'), ['user_id'], unique=False)
+
+ op.create_table('conversation_member',
+ sa.Column('user_id', sa.Integer(), nullable=False),
+ sa.Column('conversation_id', sa.Integer(), nullable=False),
+ sa.ForeignKeyConstraint(['conversation_id'], ['conversation.id'], ),
+ sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
+ sa.PrimaryKeyConstraint('user_id', 'conversation_id')
+ )
+ with op.batch_alter_table('chat_message', schema=None) as batch_op:
+ batch_op.add_column(sa.Column('conversation_id', sa.Integer(), nullable=True))
+ batch_op.create_index(batch_op.f('ix_chat_message_conversation_id'), ['conversation_id'], unique=False)
+ batch_op.create_foreign_key(None, 'conversation', ['conversation_id'], ['id'])
+
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table('chat_message', schema=None) as batch_op:
+ batch_op.drop_constraint(None, type_='foreignkey')
+ batch_op.drop_index(batch_op.f('ix_chat_message_conversation_id'))
+ batch_op.drop_column('conversation_id')
+
+ op.drop_table('conversation_member')
+ with op.batch_alter_table('conversation', schema=None) as batch_op:
+ batch_op.drop_index(batch_op.f('ix_conversation_user_id'))
+
+ op.drop_table('conversation')
+ # ### end Alembic commands ###