fix(main): Fixed error in hashtag display

This commit is contained in:
2025-06-02 17:22:00 +02:00
parent 3bb33ca379
commit 3e1255ccdc

View File

@ -5,6 +5,8 @@ import logging
import requests import requests
import threading import threading
import smtplib import smtplib
import re
import unicodedata
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from io import BytesIO from io import BytesIO
from mastodon import Mastodon from mastodon import Mastodon
@ -61,6 +63,45 @@ def should_send_email(on_success: bool):
return (mode == "all") or (mode == "errors" and not on_success) return (mode == "all") or (mode == "errors" and not on_success)
def extract_facets_utf8(text: str):
import re
facets = []
def get_byte_range(char_start, char_end):
byte_start = len(text[:char_start].encode("utf-8"))
byte_end = len(text[:char_end].encode("utf-8"))
return byte_start, byte_end
# Hashtags
for match in re.finditer(r"#(\w+)", text):
tag = match.group(1)
char_start, char_end = match.span()
byte_start, byte_end = get_byte_range(char_start, char_end)
facets.append({
"index": {"byteStart": byte_start, "byteEnd": byte_end},
"features": [{
"$type": "app.bsky.richtext.facet#tag",
"tag": tag
}]
})
# Links
for match in re.finditer(r"https?://[^\s]+", text):
url = match.group(0)
char_start, char_end = match.span()
byte_start, byte_end = get_byte_range(char_start, char_end)
facets.append({
"index": {"byteStart": byte_start, "byteEnd": byte_end},
"features": [{
"$type": "app.bsky.richtext.facet#link",
"uri": url
}]
})
return facets
def generate_email_html(status: str, title: str, link: str, error_message: str = None) -> str: def generate_email_html(status: str, title: str, link: str, error_message: str = None) -> str:
color = "#2e7d32" if status == "success" else "#d32f2f" color = "#2e7d32" if status == "success" else "#d32f2f"
bg_color = "#f5f5f5" if status == "success" else "#fff3f3" bg_color = "#f5f5f5" if status == "success" else "#fff3f3"
@ -170,7 +211,9 @@ def post_to_bluesky(title, link, tags):
if hashtags: if hashtags:
message += f"\n\n{hashtags}" message += f"\n\n{hashtags}"
# Try rich embed facets = extract_facets_utf8(message) # <-- NEU
# Versuche OG-Vorschau
try: try:
og_title, image_url = fetch_og_data(link) og_title, image_url = fetch_og_data(link)
if og_title and image_url: if og_title and image_url:
@ -194,17 +237,18 @@ def post_to_bluesky(title, link, tags):
blob = client.upload_blob(BytesIO(img_resp.content)) blob = client.upload_blob(BytesIO(img_resp.content))
embed["external"]["thumb"] = blob.blob embed["external"]["thumb"] = blob.blob
client.send_post(text=message, embed=embed) client.send_post(text=message, embed=embed, facets=facets) # <-- facets hier
logger.info(f"✅ Posted to Bluesky with preview.") logger.info(f"✅ Posted to Bluesky with preview.")
return return
except Exception as e: except Exception as e:
logger.error(f"❌ Error uploading preview to Bluesky: {e}") logger.error(f"❌ Error uploading preview to Bluesky: {e}")
# Fallback to text-only post # Fallback: Nur Text, aber mit Facets
client.send_post(text=message) client.send_post(text=message, facets=facets) # <-- facets hier
logger.info(f"💡 Posted to Bluesky without preview.") logger.info(f"💡 Posted to Bluesky without preview.")
def extract_post_date(entry): def extract_post_date(entry):
date_fields = [ date_fields = [
entry.get("published"), entry.get("published"),
@ -252,9 +296,19 @@ def main():
title = entry.get("title", "").strip() title = entry.get("title", "").strip()
link = entry.get("link", "").strip() link = entry.get("link", "").strip()
def sanitize_tag(tag):
tag = tag.lower()
tag = unicodedata.normalize("NFKD", tag).encode("ascii", "ignore").decode("ascii")
tag = re.sub(r"\W+", "", tag)
return tag
tags = [] tags = []
if "tags" in entry: if "tags" in entry:
tags = [tag["term"] for tag in entry.tags if "term" in tag] raw_tags = [
tag.get("term") if isinstance(tag, dict) else getattr(tag, "term", None)
for tag in entry.tags
]
tags = [sanitize_tag(t) for t in raw_tags if t]
if tags: if tags:
hashtags = " ".join(f"#{tag}" for tag in tags) hashtags = " ".join(f"#{tag}" for tag in tags)