More bugfixes and re-handle replies

This commit is contained in:
Thomas Sileo 2018-06-18 22:01:21 +02:00
parent 986edbd35e
commit 1338d99994
3 changed files with 80 additions and 22 deletions

View file

@ -91,13 +91,13 @@ class MicroblogPubBackend(Backend):
# Check if the activity is owned by this server # Check if the activity is owned by this server
if iri.startswith(BASE_URL): if iri.startswith(BASE_URL):
is_a_note = False is_a_note = False
if iri.endswith('/activity'): if iri.endswith("/activity"):
iri = iri.replace('/activity', '') iri = iri.replace("/activity", "")
is_a_note = True is_a_note = True
data = DB.outbox.find_one({"remote_id": iri}) data = DB.outbox.find_one({"remote_id": iri})
if data: if data:
if is_a_note: if is_a_note:
return data['activity']['object'] return data["activity"]["object"]
return data["activity"] return data["activity"]
else: else:
# Check if the activity is stored in the inbox # Check if the activity is stored in the inbox
@ -239,6 +239,11 @@ class MicroblogPubBackend(Backend):
{"activity.object.id": delete.get_object().id}, {"activity.object.id": delete.get_object().id},
{"$set": {"meta.deleted": True}}, {"$set": {"meta.deleted": True}},
) )
obj = delete.get_object()
if obj.ACTIVITY_TYPE != ActivityType.NOTE:
obj = self.fetch_iri(delete.get_object().id)
self._handle_replies_delete(as_actor, obj)
# FIXME(tsileo): handle threads # FIXME(tsileo): handle threads
# obj = delete._get_actual_object() # obj = delete._get_actual_object()
# if obj.type_enum == ActivityType.NOTE: # if obj.type_enum == ActivityType.NOTE:
@ -291,12 +296,44 @@ class MicroblogPubBackend(Backend):
# FIXME(tsileo): should send an Update (but not a partial one, to all the note's recipients # FIXME(tsileo): should send an Update (but not a partial one, to all the note's recipients
# (create a new Update with the result of the update, and send it without saving it?) # (create a new Update with the result of the update, and send it without saving it?)
@ensure_it_is_me
def outbox_create(self, as_actor: ap.Person, create: ap.Create) -> None: def outbox_create(self, as_actor: ap.Person, create: ap.Create) -> None:
self._handle_replies(as_actor, create)
@ensure_it_is_me
def inbox_create(self, as_actor: ap.Person, create: ap.Create) -> None:
self._handle_replies(as_actor, create)
@ensure_it_is_me
def _handle_replies_delete(self, as_actor: ap.Person, note: ap.Create) -> None:
in_reply_to = note.inReplyTo
if not in_reply_to:
pass pass
def inbox_create(self, as_actor: ap.Person, create: ap.Create) -> None: if not DB.inbox.find_one_and_update(
{"activity.object.id": in_reply_to},
{"$inc": {"meta.count_reply": -1, "meta.count_direct_reply": -1}},
):
DB.outbox.update_one(
{"activity.object.id": in_reply_to},
{"$inc": {"meta.count_reply": -1, "meta.count_direct_reply": -1}},
)
@ensure_it_is_me
def _handle_replies(self, as_actor: ap.Person, create: ap.Create) -> None:
in_reply_to = create.get_object().inReplyTo
if not in_reply_to:
pass pass
if not DB.inbox.find_one_and_update(
{"activity.object.id": in_reply_to},
{"$inc": {"meta.count_reply": 1, "meta.count_direct_reply": 1}},
):
DB.outbox.update_one(
{"activity.object.id": in_reply_to},
{"$inc": {"meta.count_reply": 1, "meta.count_direct_reply": 1}},
)
def gen_feed(): def gen_feed():
fg = FeedGenerator() fg = FeedGenerator()

51
app.py
View file

@ -553,7 +553,7 @@ def _build_thread(data, include_children=True):
@app.route("/note/<note_id>") @app.route("/note/<note_id>")
def note_by_id(note_id): def note_by_id(note_id):
data = DB.outbox.find_one({"id": note_id}) data = DB.outbox.find_one({"remote_id": back.activity_url(note_id)})
if not data: if not data:
abort(404) abort(404)
if data["meta"].get("deleted", False): if data["meta"].get("deleted", False):
@ -671,17 +671,15 @@ def add_extra_collection(raw_doc: Dict[str, Any]) -> Dict[str, Any]:
raw_doc["activity"]["object"]["replies"] = embed_collection( raw_doc["activity"]["object"]["replies"] = embed_collection(
raw_doc.get("meta", {}).get("count_direct_reply", 0), raw_doc.get("meta", {}).get("count_direct_reply", 0),
f'{ID}/outbox/{raw_doc["id"]}/replies', f'{raw_doc["remote_id"]}/replies',
) )
raw_doc["activity"]["object"]["likes"] = embed_collection( raw_doc["activity"]["object"]["likes"] = embed_collection(
raw_doc.get("meta", {}).get("count_like", 0), raw_doc.get("meta", {}).get("count_like", 0), f'{raw_doc["remote_id"]}/likes'
f'{ID}/outbox/{raw_doc["id"]}/likes',
) )
raw_doc["activity"]["object"]["shares"] = embed_collection( raw_doc["activity"]["object"]["shares"] = embed_collection(
raw_doc.get("meta", {}).get("count_boost", 0), raw_doc.get("meta", {}).get("count_boost", 0), f'{raw_doc["remote_id"]}/shares'
f'{ID}/outbox/{raw_doc["id"]}/shares',
) )
return raw_doc return raw_doc
@ -740,7 +738,7 @@ def outbox():
@app.route("/outbox/<item_id>") @app.route("/outbox/<item_id>")
def outbox_detail(item_id): def outbox_detail(item_id):
doc = DB.outbox.find_one({"id": item_id}) doc = DB.outbox.find_one({"remote_id": back.activity_url(item_id)})
if doc["meta"].get("deleted", False): if doc["meta"].get("deleted", False):
obj = ap.parse_activity(doc["activity"]) obj = ap.parse_activity(doc["activity"])
resp = jsonify(**obj.get_object().get_tombstone()) resp = jsonify(**obj.get_object().get_tombstone())
@ -752,7 +750,9 @@ def outbox_detail(item_id):
@app.route("/outbox/<item_id>/activity") @app.route("/outbox/<item_id>/activity")
def outbox_activity(item_id): def outbox_activity(item_id):
# TODO(tsileo): handle Tombstone # TODO(tsileo): handle Tombstone
data = DB.outbox.find_one({"id": item_id, "meta.deleted": False}) data = DB.outbox.find_one(
{"remote_id": back.activity_url(item_id), "meta.deleted": False}
)
if not data: if not data:
abort(404) abort(404)
obj = activity_from_doc(data) obj = activity_from_doc(data)
@ -766,7 +766,9 @@ def outbox_activity_replies(item_id):
# TODO(tsileo): handle Tombstone # TODO(tsileo): handle Tombstone
if not is_api_request(): if not is_api_request():
abort(404) abort(404)
data = DB.outbox.find_one({"id": item_id, "meta.deleted": False}) data = DB.outbox.find_one(
{"remote_id": back.activity_url(item_id), "meta.deleted": False}
)
if not data: if not data:
abort(404) abort(404)
obj = ap.parse_activity(data["activity"]) obj = ap.parse_activity(data["activity"])
@ -796,7 +798,9 @@ def outbox_activity_likes(item_id):
# TODO(tsileo): handle Tombstone # TODO(tsileo): handle Tombstone
if not is_api_request(): if not is_api_request():
abort(404) abort(404)
data = DB.outbox.find_one({"id": item_id, "meta.deleted": False}) data = DB.outbox.find_one(
{"remote_id": back.activity_url(item_id), "meta.deleted": False}
)
if not data: if not data:
abort(404) abort(404)
obj = ap.parse_activity(data["activity"]) obj = ap.parse_activity(data["activity"])
@ -829,7 +833,9 @@ def outbox_activity_shares(item_id):
# TODO(tsileo): handle Tombstone # TODO(tsileo): handle Tombstone
if not is_api_request(): if not is_api_request():
abort(404) abort(404)
data = DB.outbox.find_one({"id": item_id, "meta.deleted": False}) data = DB.outbox.find_one(
{"remote_id": back.activity_url(item_id), "meta.deleted": False}
)
if not data: if not data:
abort(404) abort(404)
obj = ap.parse_activity(data["activity"]) obj = ap.parse_activity(data["activity"])
@ -1007,7 +1013,7 @@ def api_delete():
def api_boost(): def api_boost():
note = _user_api_get_note() note = _user_api_get_note()
announce = note.build_announce() announce = note.build_announce(MY_PERSON)
OUTBOX.post(announce) OUTBOX.post(announce)
return _user_api_response(activity=announce.id) return _user_api_response(activity=announce.id)
@ -1018,7 +1024,7 @@ def api_boost():
def api_like(): def api_like():
note = _user_api_get_note() note = _user_api_get_note()
like = note.build_like() like = note.build_like(MY_PERSON)
OUTBOX.post(like) OUTBOX.post(like)
return _user_api_response(activity=like.id) return _user_api_response(activity=like.id)
@ -1028,7 +1034,9 @@ def api_like():
@api_required @api_required
def api_undo(): def api_undo():
oid = _user_api_arg("id") oid = _user_api_arg("id")
doc = DB.outbox.find_one({"$or": [{"id": oid}, {"remote_id": oid}]}) doc = DB.outbox.find_one(
{"$or": [{"remote_id": back.activity_url(oid)}, {"remote_id": oid}]}
)
if not doc: if not doc:
raise ActivityNotFoundError(f"cannot found {oid}") raise ActivityNotFoundError(f"cannot found {oid}")
@ -1141,6 +1149,15 @@ def inbox():
return Response(status=201) return Response(status=201)
def without_id(l):
out = []
for d in l:
if "_id" in d:
del d["_id"]
out.append(d)
return out
@app.route("/api/debug", methods=["GET", "DELETE"]) @app.route("/api/debug", methods=["GET", "DELETE"])
@api_required @api_required
def api_debug(): def api_debug():
@ -1152,7 +1169,11 @@ def api_debug():
_drop_db() _drop_db()
return flask_jsonify(message="DB dropped") return flask_jsonify(message="DB dropped")
return flask_jsonify(inbox=DB.inbox.count(), outbox=DB.outbox.count()) return flask_jsonify(
inbox=DB.inbox.count(),
outbox=DB.outbox.count(),
outbox_data=without_id(DB.outbox.find()),
)
@app.route("/api/upload", methods=["POST"]) @app.route("/api/upload", methods=["POST"])

View file

@ -30,10 +30,10 @@ class Instance(object):
api_key = f.read() api_key = f.read()
self._auth_headers = {"Authorization": f"Bearer {api_key}"} self._auth_headers = {"Authorization": f"Bearer {api_key}"}
def _do_req(self, url, headers): def _do_req(self, url):
"""Used to parse collection.""" """Used to parse collection."""
url = url.replace(self.docker_url, self.host_url) url = url.replace(self.docker_url, self.host_url)
resp = requests.get(url, headers={'Accept': 'application/actiivty+json'}) resp = requests.get(url, headers={'Accept': 'application/activity+json'})
resp.raise_for_status() resp.raise_for_status()
return resp.json() return resp.json()