Fix caching and tweak design

This commit is contained in:
Thomas Sileo 2019-07-05 22:05:28 +02:00
parent 8aba17f742
commit 98a2f8dbf8
9 changed files with 82 additions and 51 deletions

View file

@ -569,6 +569,7 @@ class MicroblogPubBackend(Backend):
)
return None
print(f"processing {create!r} and incrementing {in_reply_to}")
creply = DB.activities.find_one_and_update(
{"activity.object.id": in_reply_to},
{"$inc": {"meta.count_reply": 1, "meta.count_direct_reply": 1}},

33
app.py
View file

@ -2639,6 +2639,7 @@ def post_to_inbox(activity: ap.BaseActivity) -> None:
if back.inbox_check_duplicate(MY_PERSON, activity.id):
# The activity is already in the inbox
app.logger.info(f"received duplicate activity {activity!r}, dropping it")
return
back.save(Box.INBOX, activity)
Tasks.process_new_activity(activity.id)
@ -2691,16 +2692,23 @@ def task_cache_attachments():
if actor.icon:
MEDIA_CACHE.cache(actor.icon["url"], Kind.ACTOR_ICON)
obj = None
if activity.has_type(ap.ActivityType.CREATE):
for attachment in activity.get_object()._data.get("attachment", []):
if (
attachment.get("mediaType", "").startswith("image/")
or attachment.get("type") == ap.ActivityType.IMAGE.value
):
try:
MEDIA_CACHE.cache_attachment2(attachment["url"], iri)
except ValueError:
app.logger.exception(f"failed to cache {attachment}")
# This means a `Create` triggered the task
obj = activity.get_object()
elif activity.has_type(ap.CREATE_TYPES):
# 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:
MEDIA_CACHE.cache_attachment2(attachment, iri)
except ValueError:
app.logger.exception(f"failed to cache {attachment}")
app.logger.info(f"attachments cached for {iri}")
@ -2725,6 +2733,7 @@ def task_cache_actor() -> str:
activity = ap.fetch_remote_activity(iri)
app.logger.info(f"activity={activity!r}")
# FIXME(tsileo): OG meta for Announce?
if activity.has_type(ap.ActivityType.CREATE):
Tasks.fetch_og_meta(iri)
@ -2766,6 +2775,10 @@ def task_cache_actor() -> str:
app.logger.info(f"actor cached for {iri}")
if also_cache_attachments and activity.has_type(ap.ActivityType.CREATE):
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):
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)
DB.activities.delete_one({"_id": data["_id"]})
# FIXME(tsileo): cleanup cache from announces object
p.push({}, "/task/cleanup_part_3")
return "OK"

View file

@ -246,6 +246,7 @@ a:hover {
color: $color-light;
margin-right:5px;
border-radius:2px;
float: left;
}
.bar-item-no-hover:hover {
cursor: default;

View file

@ -10,7 +10,7 @@
<div id="following">
{% for (follow_id, follow) in following_data %}
{% 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">
<input type="hidden" name="redirect" value="{{ request.path }}"/>
<input type="hidden" name="id" value="{{ follow_id }}"/>

View file

@ -37,17 +37,17 @@
{% if "actor" in item.meta %}
{% set boost_actor = item.meta.actor %}
{% if session.logged_in %}
<div style="margin-left:65px;padding-bottom:5px;margin-bottom:15px;">
<span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name }}</a> boosted</span>
<div style="margin-left:65px;padding-bottom:5px;margin-bottom:15px;display:inline-block">
<form action="/api/undo" class="action-form" method="POST">
<input type="hidden" name="redirect" value="/"/>
<input type="hidden" name="id" value="{{ item.remote_id }}"/>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<button type="submit" class="bar-item">unboost</button>
</form>
<span class="bar-item-no-hover"><a style="color:#808080;" href="{{ boost_actor.url | get_url }}">{{ boost_actor.name }}</a> boosted</span>
</div>
{% 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>
</p>
{% endif %}

View file

@ -9,7 +9,7 @@
<div id="notes">
{% for item in liked %}
{% 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">
<input type="hidden" name="redirect" value="/liked"/>
<input type="hidden" name="id" value="{{ item.remote_id }}"/>

View file

@ -16,7 +16,7 @@
{% set data = data.to_dict() %}
<div id="lookup-result" style="margin-top:30px;">
{% 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">
<input type="hidden" name="redirect" value="{{ request.path }}"/>
<input type="hidden" name="actor" value="{{ data.id }}"/>

View file

@ -15,7 +15,7 @@
{% if item | has_type('Announce') %}
{% set boost_actor = item.meta.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 %}
{% if item.meta.object %}
{{ utils.display_note(item.meta.object, ui=True) }}
@ -24,26 +24,26 @@
{% if item | has_type('Like') %}
{% 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 %}
{{ utils.display_note(item.meta.object, ui=False, meta={'actor': item.meta.object_actor}) }}
{% endif %}
{% endif %}
{% 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;">
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
</div>
{% 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;">
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
</div>
{% 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;">
{{ utils.display_actor_inline(item.meta.actor, size=50) }}
</div>
@ -57,7 +57,7 @@
{% else %}
{% 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) }}
{% endif %}

View file

@ -4,6 +4,9 @@ from enum import Enum
from gzip import GzipFile
from io import BytesIO
from typing import Any
from typing import Dict
from little_boxes import activitypub as ap
import gridfs
import piexif
@ -115,45 +118,56 @@ class MediaCache(object):
)
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}):
return
# If it's an image, make some thumbnails
if (
url.endswith(".png")
or url.endswith(".jpg")
or url.endswith(".jpeg")
or url.endswith(".gif")
or attachment.get("mediaType", "").startswith("image/")
or ap._has_type(attachment.get("type"), ap.ActivityType.IMAGE)
):
i = load(url, self.user_agent)
# Save the original attachment (gzipped)
with BytesIO() as buf:
f1 = GzipFile(mode="wb", fileobj=buf)
i.save(f1, format=i.format)
f1.close()
buf.seek(0)
self.fs.put(
buf,
url=url,
size=None,
content_type=i.get_format_mimetype(),
kind=Kind.ATTACHMENT.value,
remote_id=remote_id,
)
# Save a thumbnail (gzipped)
i.thumbnail((720, 720))
with BytesIO() as buf:
with GzipFile(mode="wb", fileobj=buf) as f1:
try:
i = load(url, self.user_agent)
# Save the original attachment (gzipped)
with BytesIO() as buf:
f1 = GzipFile(mode="wb", fileobj=buf)
i.save(f1, format=i.format)
buf.seek(0)
self.fs.put(
buf,
url=url,
size=720,
content_type=i.get_format_mimetype(),
kind=Kind.ATTACHMENT.value,
remote_id=remote_id,
)
return
f1.close()
buf.seek(0)
self.fs.put(
buf,
url=url,
size=None,
content_type=i.get_format_mimetype(),
kind=Kind.ATTACHMENT.value,
remote_id=remote_id,
)
# Save a thumbnail (gzipped)
i.thumbnail((720, 720))
with BytesIO() as buf:
with GzipFile(mode="wb", fileobj=buf) as f1:
i.save(f1, format=i.format)
buf.seek(0)
self.fs.put(
buf,
url=url,
size=720,
content_type=i.get_format_mimetype(),
kind=Kind.ATTACHMENT.value,
remote_id=remote_id,
)
return
except Exception:
# FIXME(tsileo): logging
pass
# The attachment is not an image, download and save it anyway
with requests.get(