note: basic support of image attachments
This commit is contained in:
parent
0f6c19cf19
commit
9a8389cd49
6 changed files with 70 additions and 11 deletions
|
@ -92,6 +92,16 @@
|
||||||
</span>
|
</span>
|
||||||
<h6>{{ note.title|default:'' }}</h6>
|
<h6>{{ note.title|default:'' }}</h6>
|
||||||
<p>{{ note.content|linebreaks }}</p>
|
<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 %}
|
{% endfor %}
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Migration(migrations.Migration):
|
||||||
("title", models.TextField(blank=True, default=None, null=True)),
|
("title", models.TextField(blank=True, default=None, null=True)),
|
||||||
("content", models.TextField()),
|
("content", models.TextField()),
|
||||||
("sensitive", models.BooleanField(default=False)),
|
("sensitive", models.BooleanField(default=False)),
|
||||||
("attachements", models.JSONField(default=list)),
|
("attachments", models.JSONField(default=list)),
|
||||||
(
|
(
|
||||||
"item",
|
"item",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
|
|
|
@ -228,7 +228,7 @@ class Piece(PolymorphicModel, UserOwnedObjectMixin):
|
||||||
return pp.post_id if pp else None
|
return pp.post_id if pp else None
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def latest_post(self):
|
def latest_post(self) -> "Post | None":
|
||||||
pk = self.latest_post_id
|
pk = self.latest_post_id
|
||||||
return Takahe.get_post(pk) if pk else None
|
return Takahe.get_post(pk) if pk else None
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Note(Content):
|
||||||
title = models.TextField(blank=True, null=True, default=None)
|
title = models.TextField(blank=True, null=True, default=None)
|
||||||
content = models.TextField(blank=False, null=False)
|
content = models.TextField(blank=False, null=False)
|
||||||
sensitive = models.BooleanField(default=False, null=False)
|
sensitive = models.BooleanField(default=False, null=False)
|
||||||
attachements = models.JSONField(default=list)
|
attachments = models.JSONField(default=list)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def html(self):
|
def html(self):
|
||||||
|
@ -41,12 +41,23 @@ class Note(Content):
|
||||||
@override
|
@override
|
||||||
@classmethod
|
@classmethod
|
||||||
def params_from_ap_object(cls, post, obj, piece):
|
def params_from_ap_object(cls, post, obj, piece):
|
||||||
return {
|
params = {
|
||||||
"title": obj.get("title", post.summary),
|
"title": obj.get("title", post.summary),
|
||||||
"content": obj.get("content", "").strip(),
|
"content": obj.get("content", "").strip(),
|
||||||
"sensitive": obj.get("sensitive", post.sensitive),
|
"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
|
@override
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -66,15 +77,21 @@ class Note(Content):
|
||||||
return ShelfMember.objects.filter(item=self.item, owner=self.owner).first()
|
return ShelfMember.objects.filter(item=self.item, owner=self.owner).first()
|
||||||
|
|
||||||
def to_mastodon_params(self):
|
def to_mastodon_params(self):
|
||||||
return {
|
params = {
|
||||||
"spoiler_text": self.title,
|
"spoiler_text": self.title,
|
||||||
"content": self.content,
|
"content": self.content,
|
||||||
"sensitive": self.sensitive,
|
"sensitive": self.sensitive,
|
||||||
# "attachements": self.attachements,
|
|
||||||
"reply_to_toot_url": (
|
"reply_to_toot_url": (
|
||||||
self.shelfmember.get_mastodon_repost_url() if self.shelfmember else None
|
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):
|
def to_post_params(self):
|
||||||
return {
|
return {
|
||||||
|
@ -84,4 +101,5 @@ class Note(Content):
|
||||||
"reply_to_pk": (
|
"reply_to_pk": (
|
||||||
self.shelfmember.latest_post_id if self.shelfmember else None
|
self.shelfmember.latest_post_id if self.shelfmember else None
|
||||||
),
|
),
|
||||||
|
# not passing "attachments" so it won't change
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import re
|
import re
|
||||||
from typing import cast
|
from typing import TYPE_CHECKING, cast
|
||||||
|
|
||||||
import mistune
|
import mistune
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from catalog.models import Item
|
||||||
|
from users.models import User
|
||||||
|
|
||||||
_mistune_plugins = [
|
_mistune_plugins = [
|
||||||
"url",
|
"url",
|
||||||
"strikethrough",
|
"strikethrough",
|
||||||
|
@ -50,3 +54,11 @@ def _spolier(s: str) -> str:
|
||||||
|
|
||||||
def render_text(s: str) -> str:
|
def render_text(s: str) -> str:
|
||||||
return _spolier(s).strip().replace("\n", "<br>")
|
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)
|
||||||
|
)
|
||||||
|
|
|
@ -262,14 +262,16 @@ def post_toot2(
|
||||||
reply_to_toot_url: str | None = None,
|
reply_to_toot_url: str | None = None,
|
||||||
sensitive: bool = False,
|
sensitive: bool = False,
|
||||||
spoiler_text: str | None = None,
|
spoiler_text: str | None = None,
|
||||||
|
attachments: list = [],
|
||||||
):
|
):
|
||||||
headers = {
|
headers = {
|
||||||
"User-Agent": USER_AGENT,
|
"User-Agent": USER_AGENT,
|
||||||
"Authorization": f"Bearer {user.mastodon_token}",
|
"Authorization": f"Bearer {user.mastodon_token}",
|
||||||
"Idempotency-Key": random_string_generator(16),
|
"Idempotency-Key": random_string_generator(16),
|
||||||
}
|
}
|
||||||
|
base_url = "https://" + get_api_domain(user.mastodon_site)
|
||||||
response = None
|
response = None
|
||||||
url = "https://" + get_api_domain(user.mastodon_site) + API_PUBLISH_TOOT
|
url = base_url + API_PUBLISH_TOOT
|
||||||
payload = {
|
payload = {
|
||||||
"status": content,
|
"status": content,
|
||||||
"visibility": get_toot_visibility(visibility, user),
|
"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)
|
reply_to_id = get_status_id_by_url(reply_to_toot_url)
|
||||||
if reply_to_id:
|
if reply_to_id:
|
||||||
payload["in_reply_to_id"] = reply_to_id
|
payload["in_reply_to_id"] = reply_to_id
|
||||||
# if media_id:
|
|
||||||
# payload["media_ids[]"] = [media_id]
|
|
||||||
if spoiler_text:
|
if spoiler_text:
|
||||||
payload["spoiler_text"] = spoiler_text
|
payload["spoiler_text"] = spoiler_text
|
||||||
if sensitive:
|
if sensitive:
|
||||||
payload["sensitive"] = True
|
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:
|
try:
|
||||||
if update_id:
|
if update_id:
|
||||||
response = put(url + "/" + update_id, headers=headers, data=payload)
|
response = put(url + "/" + update_id, headers=headers, data=payload)
|
||||||
|
|
Loading…
Add table
Reference in a new issue