note: basic support of image attachments

This commit is contained in:
Your Name 2024-06-13 22:03:35 -04:00 committed by Henri Dickson
parent 0f6c19cf19
commit 9a8389cd49
6 changed files with 70 additions and 11 deletions

View file

@ -92,6 +92,16 @@
</span>
<h6>{{ note.title|default:'' }}</h6>
<p>{{ note.content|linebreaks }}</p>
<div>
{% for attachment in note.attachments %}
{% if attachment.type == 'image' %}
<img src="{{ attachment.url }}"
alt="image attachment"
style="max-height:6em;
max-width:50%">
{% endif %}
{% endfor %}
</div>
{% endfor %}
</section>
<section>

View file

@ -41,7 +41,7 @@ class Migration(migrations.Migration):
("title", models.TextField(blank=True, default=None, null=True)),
("content", models.TextField()),
("sensitive", models.BooleanField(default=False)),
("attachements", models.JSONField(default=list)),
("attachments", models.JSONField(default=list)),
(
"item",
models.ForeignKey(

View file

@ -228,7 +228,7 @@ class Piece(PolymorphicModel, UserOwnedObjectMixin):
return pp.post_id if pp else None
@cached_property
def latest_post(self):
def latest_post(self) -> "Post | None":
pk = self.latest_post_id
return Takahe.get_post(pk) if pk else None

View file

@ -16,7 +16,7 @@ class Note(Content):
title = models.TextField(blank=True, null=True, default=None)
content = models.TextField(blank=False, null=False)
sensitive = models.BooleanField(default=False, null=False)
attachements = models.JSONField(default=list)
attachments = models.JSONField(default=list)
@property
def html(self):
@ -41,12 +41,23 @@ class Note(Content):
@override
@classmethod
def params_from_ap_object(cls, post, obj, piece):
return {
params = {
"title": obj.get("title", post.summary),
"content": obj.get("content", "").strip(),
"sensitive": obj.get("sensitive", post.sensitive),
# "attachements": obj.get("attachements", []),
"attachments": [],
}
if post:
for atta in post.attachments.all():
params["attachments"].append(
{
"type": (atta.mimetype or "unknown").split("/")[0],
"mimetype": atta.mimetype,
"url": atta.full_url().absolute,
"preview_url": atta.thumbnail_url().absolute,
}
)
return params
@override
@classmethod
@ -66,15 +77,21 @@ class Note(Content):
return ShelfMember.objects.filter(item=self.item, owner=self.owner).first()
def to_mastodon_params(self):
return {
params = {
"spoiler_text": self.title,
"content": self.content,
"sensitive": self.sensitive,
# "attachements": self.attachements,
"reply_to_toot_url": (
self.shelfmember.get_mastodon_repost_url() if self.shelfmember else None
),
}
if self.latest_post:
attachments = []
for atta in self.latest_post.attachments.all():
attachments.append((atta.file_display_name, atta.file, atta.mimetype))
if attachments:
params["attachments"] = attachments
return params
def to_post_params(self):
return {
@ -84,4 +101,5 @@ class Note(Content):
"reply_to_pk": (
self.shelfmember.latest_post_id if self.shelfmember else None
),
# not passing "attachments" so it won't change
}

View file

@ -1,9 +1,13 @@
import re
from typing import cast
from typing import TYPE_CHECKING, cast
import mistune
from django.utils.html import escape
if TYPE_CHECKING:
from catalog.models import Item
from users.models import User
_mistune_plugins = [
"url",
"strikethrough",
@ -50,3 +54,11 @@ def _spolier(s: str) -> str:
def render_text(s: str) -> str:
return _spolier(s).strip().replace("\n", "<br>")
def render_post_with_macro(txt: str, item: "Item") -> str:
return (
txt.replace("[category]", item.category.name)
.replace("[title]", item.display_title)
.replace("[url]", item.absolute_url)
)

View file

@ -262,14 +262,16 @@ def post_toot2(
reply_to_toot_url: str | None = None,
sensitive: bool = False,
spoiler_text: str | None = None,
attachments: list = [],
):
headers = {
"User-Agent": USER_AGENT,
"Authorization": f"Bearer {user.mastodon_token}",
"Idempotency-Key": random_string_generator(16),
}
base_url = "https://" + get_api_domain(user.mastodon_site)
response = None
url = "https://" + get_api_domain(user.mastodon_site) + API_PUBLISH_TOOT
url = base_url + API_PUBLISH_TOOT
payload = {
"status": content,
"visibility": get_toot_visibility(visibility, user),
@ -278,12 +280,29 @@ def post_toot2(
reply_to_id = get_status_id_by_url(reply_to_toot_url)
if reply_to_id:
payload["in_reply_to_id"] = reply_to_id
# if media_id:
# payload["media_ids[]"] = [media_id]
if spoiler_text:
payload["spoiler_text"] = spoiler_text
if sensitive:
payload["sensitive"] = True
media_ids = []
for atta in attachments:
try:
media_id = (
requests.post(
base_url + "/api/v1/media",
headers=headers,
data={},
files={"file": atta},
)
.json()
.get("id")
)
media_ids.append(media_id)
except Exception as e:
logger.warning(f"Error uploading image {e}")
headers["Idempotency-Key"] = random_string_generator(16)
if media_ids:
payload["media_ids[]"] = media_ids
try:
if update_id:
response = put(url + "/" + update_id, headers=headers, data=payload)