forked from forks/microblog.pub
Fix caching and tweak design
This commit is contained in:
parent
8aba17f742
commit
98a2f8dbf8
9 changed files with 82 additions and 51 deletions
|
@ -569,6 +569,7 @@ class MicroblogPubBackend(Backend):
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
print(f"processing {create!r} and incrementing {in_reply_to}")
|
||||||
creply = DB.activities.find_one_and_update(
|
creply = DB.activities.find_one_and_update(
|
||||||
{"activity.object.id": in_reply_to},
|
{"activity.object.id": in_reply_to},
|
||||||
{"$inc": {"meta.count_reply": 1, "meta.count_direct_reply": 1}},
|
{"$inc": {"meta.count_reply": 1, "meta.count_direct_reply": 1}},
|
||||||
|
|
27
app.py
27
app.py
|
@ -2639,6 +2639,7 @@ def post_to_inbox(activity: ap.BaseActivity) -> None:
|
||||||
if back.inbox_check_duplicate(MY_PERSON, activity.id):
|
if back.inbox_check_duplicate(MY_PERSON, activity.id):
|
||||||
# The activity is already in the inbox
|
# The activity is already in the inbox
|
||||||
app.logger.info(f"received duplicate activity {activity!r}, dropping it")
|
app.logger.info(f"received duplicate activity {activity!r}, dropping it")
|
||||||
|
return
|
||||||
|
|
||||||
back.save(Box.INBOX, activity)
|
back.save(Box.INBOX, activity)
|
||||||
Tasks.process_new_activity(activity.id)
|
Tasks.process_new_activity(activity.id)
|
||||||
|
@ -2691,14 +2692,21 @@ def task_cache_attachments():
|
||||||
if actor.icon:
|
if actor.icon:
|
||||||
MEDIA_CACHE.cache(actor.icon["url"], Kind.ACTOR_ICON)
|
MEDIA_CACHE.cache(actor.icon["url"], Kind.ACTOR_ICON)
|
||||||
|
|
||||||
|
obj = None
|
||||||
if activity.has_type(ap.ActivityType.CREATE):
|
if activity.has_type(ap.ActivityType.CREATE):
|
||||||
for attachment in activity.get_object()._data.get("attachment", []):
|
# This means a `Create` triggered the task
|
||||||
if (
|
obj = activity.get_object()
|
||||||
attachment.get("mediaType", "").startswith("image/")
|
elif activity.has_type(ap.CREATE_TYPES):
|
||||||
or attachment.get("type") == ap.ActivityType.IMAGE.value
|
# This means a `Announce` triggered the task
|
||||||
):
|
obj = activity
|
||||||
|
else:
|
||||||
|
app.logger.warning(f"Don't know what to do with {activity!r}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Iter the attachments
|
||||||
|
for attachment in obj._data.get("attachment", []):
|
||||||
try:
|
try:
|
||||||
MEDIA_CACHE.cache_attachment2(attachment["url"], iri)
|
MEDIA_CACHE.cache_attachment2(attachment, iri)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
app.logger.exception(f"failed to cache {attachment}")
|
app.logger.exception(f"failed to cache {attachment}")
|
||||||
|
|
||||||
|
@ -2725,6 +2733,7 @@ def task_cache_actor() -> str:
|
||||||
activity = ap.fetch_remote_activity(iri)
|
activity = ap.fetch_remote_activity(iri)
|
||||||
app.logger.info(f"activity={activity!r}")
|
app.logger.info(f"activity={activity!r}")
|
||||||
|
|
||||||
|
# FIXME(tsileo): OG meta for Announce?
|
||||||
if activity.has_type(ap.ActivityType.CREATE):
|
if activity.has_type(ap.ActivityType.CREATE):
|
||||||
Tasks.fetch_og_meta(iri)
|
Tasks.fetch_og_meta(iri)
|
||||||
|
|
||||||
|
@ -2766,6 +2775,10 @@ def task_cache_actor() -> str:
|
||||||
app.logger.info(f"actor cached for {iri}")
|
app.logger.info(f"actor cached for {iri}")
|
||||||
if also_cache_attachments and activity.has_type(ap.ActivityType.CREATE):
|
if also_cache_attachments and activity.has_type(ap.ActivityType.CREATE):
|
||||||
Tasks.cache_attachments(iri)
|
Tasks.cache_attachments(iri)
|
||||||
|
elif also_cache_attachments and activity.has_type(ap.ActivityType.ANNOUNCE):
|
||||||
|
obj = activity.get_object()
|
||||||
|
Tasks.cache_attachments(obj.id)
|
||||||
|
Tasks.cache_actor(obj.id)
|
||||||
|
|
||||||
except (ActivityGoneError, ActivityNotFoundError):
|
except (ActivityGoneError, ActivityNotFoundError):
|
||||||
DB.activities.update_one({"remote_id": iri}, {"$set": {"meta.deleted": True}})
|
DB.activities.update_one({"remote_id": iri}, {"$set": {"meta.deleted": True}})
|
||||||
|
@ -3201,6 +3214,8 @@ def task_cleanup_part_2():
|
||||||
MEDIA_CACHE.fs.delete(grid_item._id)
|
MEDIA_CACHE.fs.delete(grid_item._id)
|
||||||
DB.activities.delete_one({"_id": data["_id"]})
|
DB.activities.delete_one({"_id": data["_id"]})
|
||||||
|
|
||||||
|
# FIXME(tsileo): cleanup cache from announces object
|
||||||
|
|
||||||
p.push({}, "/task/cleanup_part_3")
|
p.push({}, "/task/cleanup_part_3")
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,7 @@ a:hover {
|
||||||
color: $color-light;
|
color: $color-light;
|
||||||
margin-right:5px;
|
margin-right:5px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
.bar-item-no-hover:hover {
|
.bar-item-no-hover:hover {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<div id="following">
|
<div id="following">
|
||||||
{% for (follow_id, follow) in following_data %}
|
{% for (follow_id, follow) in following_data %}
|
||||||
{% if session.logged_in %}
|
{% if session.logged_in %}
|
||||||
<div style="margin-left:90px;padding-bottom:5px;margin-bottom:15px;">
|
<div style="margin-left:90px;padding-bottom:5px;margin-bottom:15px;display:inline-block;">
|
||||||
<form action="/api/undo" class="action-form" method="POST">
|
<form action="/api/undo" class="action-form" method="POST">
|
||||||
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||||
<input type="hidden" name="id" value="{{ follow_id }}"/>
|
<input type="hidden" name="id" value="{{ follow_id }}"/>
|
||||||
|
|
|
@ -37,17 +37,17 @@
|
||||||
{% if "actor" in item.meta %}
|
{% if "actor" in item.meta %}
|
||||||
{% set boost_actor = item.meta.actor %}
|
{% set boost_actor = item.meta.actor %}
|
||||||
{% if session.logged_in %}
|
{% if session.logged_in %}
|
||||||
<div style="margin-left:65px;padding-bottom:5px;margin-bottom:15px;">
|
<div style="margin-left:65px;padding-bottom:5px;margin-bottom:15px;display:inline-block">
|
||||||
<span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name }}</a> boosted</span>
|
|
||||||
<form action="/api/undo" class="action-form" method="POST">
|
<form action="/api/undo" class="action-form" method="POST">
|
||||||
<input type="hidden" name="redirect" value="/"/>
|
<input type="hidden" name="redirect" value="/"/>
|
||||||
<input type="hidden" name="id" value="{{ item.remote_id }}"/>
|
<input type="hidden" name="id" value="{{ item.remote_id }}"/>
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
<button type="submit" class="bar-item">unboost</button>
|
<button type="submit" class="bar-item">unboost</button>
|
||||||
</form>
|
</form>
|
||||||
|
<span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name }}</a> boosted</span>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p style="margin-left:65px;padding-bottom:5px;">
|
<p style="margin-left:65px;padding-bottom:5px;display:inline-block;">
|
||||||
<span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name }}</a> boosted</span>
|
<span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name }}</a> boosted</span>
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<div id="notes">
|
<div id="notes">
|
||||||
{% for item in liked %}
|
{% for item in liked %}
|
||||||
{% if session.logged_in %}
|
{% if session.logged_in %}
|
||||||
<div style="margin-left:65px;padding-bottom:5px;margin-bottom:15px;">
|
<div style="margin-left:65px;padding-bottom:5px;margin-bottom:15px;display:inline-block;">
|
||||||
<form action="/api/undo" class="action-form" method="POST">
|
<form action="/api/undo" class="action-form" method="POST">
|
||||||
<input type="hidden" name="redirect" value="/liked"/>
|
<input type="hidden" name="redirect" value="/liked"/>
|
||||||
<input type="hidden" name="id" value="{{ item.remote_id }}"/>
|
<input type="hidden" name="id" value="{{ item.remote_id }}"/>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
{% set data = data.to_dict() %}
|
{% set data = data.to_dict() %}
|
||||||
<div id="lookup-result" style="margin-top:30px;">
|
<div id="lookup-result" style="margin-top:30px;">
|
||||||
{% if data | has_actor_type %}
|
{% if data | has_actor_type %}
|
||||||
<div style="margin-left:95px;padding-bottom:5px;margin-bottom:15px;">
|
<div style="margin-left:95px;padding-bottom:5px;margin-bottom:15px;display:inline-block;">
|
||||||
<form action="/api/follow" class="action-form" method="POST">
|
<form action="/api/follow" class="action-form" method="POST">
|
||||||
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||||
<input type="hidden" name="actor" value="{{ data.id }}"/>
|
<input type="hidden" name="actor" value="{{ data.id }}"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
{% if item | has_type('Announce') %}
|
{% if item | has_type('Announce') %}
|
||||||
{% set boost_actor = item.meta.actor %}
|
{% set boost_actor = item.meta.actor %}
|
||||||
{% if boost_actor %}
|
{% if boost_actor %}
|
||||||
<p style="margin-left:70px;padding-bottom:5px;"><span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name or boost_actor.preferredUsername }}</a> boosted</span></p>
|
<p style="margin-left:70px;padding-bottom:5px;display:inline-block;"><span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name or boost_actor.preferredUsername }}</a> boosted</span></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if item.meta.object %}
|
{% if item.meta.object %}
|
||||||
{{ utils.display_note(item.meta.object, ui=True) }}
|
{{ utils.display_note(item.meta.object, ui=True) }}
|
||||||
|
@ -24,26 +24,26 @@
|
||||||
|
|
||||||
{% if item | has_type('Like') %}
|
{% if item | has_type('Like') %}
|
||||||
{% set boost_actor = item.meta.actor %}
|
{% set boost_actor = item.meta.actor %}
|
||||||
<p style="margin-left:70px;padding-bottom:5px;"><span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name or boost_actor.preferredUsername }}</a> liked</span></p>
|
<p style="margin-left:70px;padding-bottom:5px;display:inline-block;"><span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name or boost_actor.preferredUsername }}</a> liked</span></p>
|
||||||
{% if item.meta.object %}
|
{% if item.meta.object %}
|
||||||
{{ utils.display_note(item.meta.object, ui=False, meta={'actor': item.meta.object_actor}) }}
|
{{ utils.display_note(item.meta.object, ui=False, meta={'actor': item.meta.object_actor}) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if item | has_type('Follow') %}
|
{% if item | has_type('Follow') %}
|
||||||
<p style="margin-left:70px;padding-bottom:5px;"><span class="bar-item-no-hover">new follower</span> <!-- <a href="" class="bar-item">follow back</a></p> -->
|
<p style="margin-left:70px;padding-bottom:5px;display:inline-block;"><span class="bar-item-no-hover">new follower</span> <!-- <a href="" class="bar-item">follow back</a></p> -->
|
||||||
<div style="height: 100px;">
|
<div style="height: 100px;">
|
||||||
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
|
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% elif item | has_type('Accept') %}
|
{% elif item | has_type('Accept') %}
|
||||||
<p style="margin-left:70px;padding-bottom:5px;"><span class="bar-item-no-hover">you started following</span></p>
|
<p style="margin-left:70px;padding-bottom:5px;display:inline-block;"><span class="bar-item-no-hover">you started following</span></p>
|
||||||
<div style="height: 100px;">
|
<div style="height: 100px;">
|
||||||
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
|
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% elif item | has_type('Undo') %}
|
{% elif item | has_type('Undo') %}
|
||||||
<p style="margin-left:70px;padding-bottom:5px;"><span class="bar-item-no-hover">unfollowed you</span></p>
|
<p style="margin-left:70px;padding-bottom:5px;display:inline-block;"><span class="bar-item-no-hover">unfollowed you</span></p>
|
||||||
<div style="height: 100px;">
|
<div style="height: 100px;">
|
||||||
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
|
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
{% if item | has_type('question_ended') %}
|
{% if item | has_type('question_ended') %}
|
||||||
<p style="margin-left:70px;padding-bottom:5px;"><span class="bar-item-no-hover">poll ended</span></p>
|
<p style="margin-left:70px;padding-bottom:5px;display:inline-block;"><span class="bar-item-no-hover">poll ended</span></p>
|
||||||
{{ utils.display_note(item.activity.object) }}
|
{{ utils.display_note(item.activity.object) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ from enum import Enum
|
||||||
from gzip import GzipFile
|
from gzip import GzipFile
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from little_boxes import activitypub as ap
|
||||||
|
|
||||||
import gridfs
|
import gridfs
|
||||||
import piexif
|
import piexif
|
||||||
|
@ -115,15 +118,23 @@ class MediaCache(object):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
def cache_attachment2(self, url: str, remote_id: str) -> None:
|
def cache_attachment2(self, attachment: Dict[str, Any], remote_id: str) -> None:
|
||||||
|
url = attachment["url"]
|
||||||
|
|
||||||
|
# Ensure it's not already there
|
||||||
if self.fs.find_one({"url": url, "kind": Kind.ATTACHMENT.value}):
|
if self.fs.find_one({"url": url, "kind": Kind.ATTACHMENT.value}):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# If it's an image, make some thumbnails
|
||||||
if (
|
if (
|
||||||
url.endswith(".png")
|
url.endswith(".png")
|
||||||
or url.endswith(".jpg")
|
or url.endswith(".jpg")
|
||||||
or url.endswith(".jpeg")
|
or url.endswith(".jpeg")
|
||||||
or url.endswith(".gif")
|
or url.endswith(".gif")
|
||||||
|
or attachment.get("mediaType", "").startswith("image/")
|
||||||
|
or ap._has_type(attachment.get("type"), ap.ActivityType.IMAGE)
|
||||||
):
|
):
|
||||||
|
try:
|
||||||
i = load(url, self.user_agent)
|
i = load(url, self.user_agent)
|
||||||
# Save the original attachment (gzipped)
|
# Save the original attachment (gzipped)
|
||||||
with BytesIO() as buf:
|
with BytesIO() as buf:
|
||||||
|
@ -154,6 +165,9 @@ class MediaCache(object):
|
||||||
remote_id=remote_id,
|
remote_id=remote_id,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
except Exception:
|
||||||
|
# FIXME(tsileo): logging
|
||||||
|
pass
|
||||||
|
|
||||||
# The attachment is not an image, download and save it anyway
|
# The attachment is not an image, download and save it anyway
|
||||||
with requests.get(
|
with requests.get(
|
||||||
|
|
Loading…
Reference in a new issue