mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
API: inbox private messages
This commit is contained in:
parent
7e45e4e939
commit
0f79b8075f
5 changed files with 120 additions and 16 deletions
|
@ -6,7 +6,8 @@ from app.api.alpha.utils import get_site, post_site_block, \
|
|||
get_reply_list, post_reply_like, put_reply_save, put_reply_subscribe, post_reply, put_reply, post_reply_mark_as_read, \
|
||||
post_reply_delete, post_reply_report, post_reply_remove, \
|
||||
get_community_list, get_community, post_community_follow, post_community_block, \
|
||||
get_user, post_user_block, get_user_unread_count, get_user_replies
|
||||
get_user, post_user_block, get_user_unread_count, get_user_replies, post_user_mark_all_as_read, \
|
||||
get_private_message_list
|
||||
from app.shared.auth import log_user_in
|
||||
|
||||
from flask import current_app, jsonify, request
|
||||
|
@ -366,6 +367,19 @@ def post_alpha_comment_mark_as_read():
|
|||
return jsonify({"error": str(ex)}), 400
|
||||
|
||||
|
||||
# Private Message
|
||||
@bp.route('/api/alpha/private_message/list', methods=['GET'])
|
||||
def get_alpha_private_message_list():
|
||||
if not enable_api():
|
||||
return jsonify({'error': 'alpha api is not enabled'})
|
||||
try:
|
||||
auth = request.headers.get('Authorization')
|
||||
data = request.args.to_dict() or None
|
||||
return jsonify(get_private_message_list(auth, data))
|
||||
except Exception as ex:
|
||||
return jsonify({"error": str(ex)}), 400
|
||||
|
||||
|
||||
# User
|
||||
@bp.route('/api/alpha/user', methods=['GET'])
|
||||
def get_alpha_user():
|
||||
|
@ -426,6 +440,17 @@ def post_alpha_user_block():
|
|||
return jsonify({"error": str(ex)}), 400
|
||||
|
||||
|
||||
@bp.route('/api/alpha/user/mark_all_as_read', methods=['POST'])
|
||||
def post_alpha_user_mark_all_as_read():
|
||||
if not enable_api():
|
||||
return jsonify({'error': 'alpha api is not enabled'})
|
||||
try:
|
||||
auth = request.headers.get('Authorization')
|
||||
return jsonify(post_user_mark_all_as_read(auth))
|
||||
except Exception as ex:
|
||||
return jsonify({"error": str(ex)}), 400
|
||||
|
||||
|
||||
# Not yet implemented. Copied from lemmy's V3 api, so some aren't needed, and some need changing
|
||||
|
||||
# Site - not yet implemented
|
||||
|
@ -436,7 +461,7 @@ def alpha_site():
|
|||
|
||||
# Miscellaneous - not yet implemented
|
||||
@bp.route('/api/alpha/modlog', methods=['GET']) # Get Modlog. Not usually public
|
||||
@bp.route('/api/alpha/resolve_object', methods=['GET']) # Stage 1: Needed for search
|
||||
@bp.route('/api/alpha/resolve_object', methods=['GET']) # Stage 2
|
||||
@bp.route('/api/alpha/federated_instances', methods=['GET']) # No plans to implement - only V3 version needed
|
||||
def alpha_miscellaneous():
|
||||
return jsonify({"error": "not_yet_implemented"}), 400
|
||||
|
@ -469,12 +494,11 @@ def alpha_reply():
|
|||
return jsonify({"error": "not_yet_implemented"}), 400
|
||||
|
||||
# Chat - not yet implemented
|
||||
@bp.route('/api/alpha/private_message/list', methods=['GET']) # Stage 1
|
||||
@bp.route('/api/alpha/private_message', methods=['PUT']) # Stage 1
|
||||
@bp.route('/api/alpha/private_message', methods=['POST']) # Stage 1
|
||||
@bp.route('/api/alpha/private_message/delete', methods=['POST']) # Stage 1
|
||||
@bp.route('/api/alpha/private_message/mark_as_read', methods=['POST']) # Stage 1
|
||||
@bp.route('/api/alpha/private_message/report', methods=['POST']) # Stage 1
|
||||
@bp.route('/api/alpha/private_message', methods=['PUT']) # Not available in app
|
||||
@bp.route('/api/alpha/private_message', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/private_message/delete', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/private_message/mark_as_read', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/private_message/report', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/private_message/report/resolve', methods=['PUT']) # Stage 2
|
||||
@bp.route('/api/alpha/private_message/report/list', methods=['GET']) # Stage 2
|
||||
def alpha_chat():
|
||||
|
@ -484,15 +508,14 @@ def alpha_chat():
|
|||
@bp.route('/api/alpha/user/register', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/user/get_captcha', methods=['GET']) # Not available in app
|
||||
@bp.route('/api/alpha/user/mention', methods=['GET']) # No DB support
|
||||
@bp.route('/api/alpha/user/mention/mark_as_read', methods=['POST']) # No DB support
|
||||
@bp.route('/api/alpha/user/mention/mark_as_read', methods=['POST']) # No DB support / Not available in app (using mark_all instead)
|
||||
@bp.route('/api/alpha/user/ban', methods=['POST']) # Admin function. No plans to implement
|
||||
@bp.route('/api/alpha/user/banned', methods=['GET']) # Admin function. No plans to implement
|
||||
@bp.route('/api/alpha/user/delete_account', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/user/password_reset', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/user/password_change', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/user/mark_all_as_read', methods=['POST']) # Stage 1
|
||||
@bp.route('/api/alpha/user/save_user_settings', methods=['PUT']) # Not available in app
|
||||
@bp.route('/api/alpha/user/change_password', methods=['PUT']) # Not available in app
|
||||
@bp.route('/api/alpha/user/save_user_settings', methods=['PUT']) # Stage 2
|
||||
@bp.route('/api/alpha/user/change_password', methods=['PUT']) # Stage 2
|
||||
@bp.route('/api/alpha/user/report_count', methods=['GET']) # Stage 2
|
||||
@bp.route('/api/alpha/user/verify_email', methods=['POST']) # Admin function. No plans to implement
|
||||
@bp.route('/api/alpha/user/leave_admin', methods=['POST']) # Admin function. No plans to implement
|
||||
|
@ -502,7 +525,7 @@ def alpha_chat():
|
|||
@bp.route('/api/alpha/user/import_settings', methods=['POST']) # Not available in app
|
||||
@bp.route('/api/alpha/user/list_logins', methods=['GET']) # Not available in app
|
||||
@bp.route('/api/alpha/user/validate_auth', methods=['GET']) # Not available in app
|
||||
@bp.route('/api/alpha/user/logout', methods=['POST']) # Stage 1
|
||||
@bp.route('/api/alpha/user/logout', methods=['POST']) # Stage 2
|
||||
def alpha_user():
|
||||
return jsonify({"error": "not_yet_implemented"}), 400
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ from app.api.alpha.utils.misc import get_search
|
|||
from app.api.alpha.utils.post import get_post_list, get_post, post_post_like, put_post_save, put_post_subscribe, post_post, put_post, post_post_delete, post_post_report, post_post_lock, post_post_feature, post_post_remove
|
||||
from app.api.alpha.utils.reply import get_reply_list, post_reply_like, put_reply_save, put_reply_subscribe, post_reply, put_reply, post_reply_delete, post_reply_report, post_reply_remove, post_reply_mark_as_read
|
||||
from app.api.alpha.utils.community import get_community, get_community_list, post_community_follow, post_community_block
|
||||
from app.api.alpha.utils.user import get_user, post_user_block, get_user_unread_count, get_user_replies
|
||||
from app.api.alpha.utils.user import get_user, post_user_block, get_user_unread_count, get_user_replies, post_user_mark_all_as_read
|
||||
from app.api.alpha.utils.private_message import get_private_message_list
|
||||
|
||||
|
||||
|
|
38
app/api/alpha/utils/private_message.py
Normal file
38
app/api/alpha/utils/private_message.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
from app import db
|
||||
from app.api.alpha.views import private_message_view
|
||||
from app.models import ChatMessage, Conversation
|
||||
from app.utils import authorise_api_user
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from sqlalchemy import text
|
||||
|
||||
import re
|
||||
|
||||
def get_private_message_list(auth, data):
|
||||
page = int(data['page']) if data and 'page' in data else 1
|
||||
limit = int(data['limit']) if data and 'limit' in data else 10
|
||||
unread_only = data['unread_only'] if data and 'unread_only' in data else True
|
||||
|
||||
user_id = authorise_api_user(auth)
|
||||
|
||||
read = not unread_only
|
||||
|
||||
unread_urls = db.session.execute(text("select url from notification where user_id = :user_id and read = false and url ilike '%#message_<ChatMessage%'"), {'user_id': user_id}).scalars()
|
||||
unread_ids = []
|
||||
pattern = r"/chat/.+?#message_<ChatMessage (.+?)>"
|
||||
for url in unread_urls:
|
||||
match = re.search(pattern, url)
|
||||
if match:
|
||||
unread_ids.append(match.group(1))
|
||||
|
||||
private_messages = ChatMessage.query.filter(ChatMessage.recipient_id == user_id, ChatMessage.id.in_(unread_ids)).join(Conversation, Conversation.id == ChatMessage.conversation_id).filter_by(read=read)
|
||||
pm_list = []
|
||||
for private_message in private_messages:
|
||||
ap_id = 'https://' + current_app.config['SERVER_NAME'] + '/chat/' + str(private_message.conversation_id) + '#message_<ChatMessage ' + str(private_message.id) + '>'
|
||||
pm_list.append(private_message_view(private_message, user_id, ap_id))
|
||||
|
||||
pm_json = {
|
||||
"private_messages": pm_list
|
||||
}
|
||||
return pm_json
|
|
@ -4,7 +4,7 @@ from app.utils import authorise_api_user
|
|||
from app.api.alpha.utils.post import get_post_list
|
||||
from app.api.alpha.utils.reply import get_reply_list
|
||||
from app.api.alpha.utils.validators import required, integer_expected, boolean_expected
|
||||
from app.models import PostReply, User
|
||||
from app.models import Conversation, ChatMessage, Notification, PostReply, User
|
||||
from app.shared.user import block_another_user, unblock_another_user
|
||||
|
||||
from sqlalchemy import text, desc
|
||||
|
@ -96,6 +96,8 @@ def get_user_unread_count(auth):
|
|||
unread_messages = db.session.execute(text("SELECT * from chat_message AS cm INNER JOIN conversation c ON cm.conversation_id =c.id WHERE c.read = false AND cm.recipient_id = :user_id"), {'user_id': user_id}).scalar()
|
||||
if not unread_messages:
|
||||
unread_messages = 0
|
||||
if unread_notifications == 0:
|
||||
unread_messages = 0
|
||||
|
||||
unread_count = {
|
||||
"replies": unread_notifications - unread_messages,
|
||||
|
@ -132,3 +134,19 @@ def get_user_replies(auth, data):
|
|||
return list_json
|
||||
|
||||
|
||||
def post_user_mark_all_as_read(auth):
|
||||
user_id = authorise_api_user(auth)
|
||||
|
||||
notifications = Notification.query.filter_by(user_id=user_id, read=False)
|
||||
for notification in notifications:
|
||||
notification.read = True
|
||||
|
||||
conversations = Conversation.query.filter_by(read=False).join(ChatMessage, ChatMessage.conversation_id == Conversation.id).filter_by(recipient_id=user_id)
|
||||
for conversation in conversations:
|
||||
conversation.read = True
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return {'replies': []}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||
|
||||
from app import cache, db
|
||||
from app.constants import *
|
||||
from app.models import Community, CommunityMember, Instance, Post, PostReply, PostVote, User
|
||||
from app.models import ChatMessage, Community, CommunityMember, Instance, Post, PostReply, PostVote, User
|
||||
from app.utils import blocked_communities
|
||||
|
||||
from sqlalchemy import text
|
||||
|
@ -471,6 +471,30 @@ def instance_view(instance: Instance | int, variant):
|
|||
return v1
|
||||
|
||||
|
||||
def private_message_view(cm: ChatMessage, user_id, ap_id):
|
||||
creator = user_view(cm.sender_id, variant=1)
|
||||
recipient = user_view(cm.recipient_id, variant=1)
|
||||
is_local = creator['instance_id'] == 1
|
||||
|
||||
v1 = {
|
||||
'private_message': {
|
||||
'id': cm.id,
|
||||
'creator_id': cm.sender_id,
|
||||
'recipient_id': user_id,
|
||||
'content': cm.body,
|
||||
'deleted': False,
|
||||
'read': cm.read,
|
||||
'published': cm.created_at.isoformat() + 'Z',
|
||||
'ap_id': ap_id,
|
||||
'local': is_local
|
||||
},
|
||||
'creator': creator,
|
||||
'recipient': recipient
|
||||
}
|
||||
|
||||
return v1
|
||||
|
||||
|
||||
@cache.memoize(timeout=86400)
|
||||
def cached_modlist_for_community(community_id):
|
||||
moderator_ids = db.session.execute(text('SELECT user_id FROM "community_member" WHERE community_id = :community_id and is_moderator = True'), {'community_id': community_id}).scalars()
|
||||
|
|
Loading…
Add table
Reference in a new issue