Update mastodonapi.php

This commit is contained in:
simonpipe 2026-05-27 07:54:37 +02:00
parent ffd25e65cc
commit 6ad7d5a6ea

View file

@ -2,7 +2,7 @@
// Mastodonapi extension, https://codeberg.org/simonpipe/yellow-mastodonapi // Mastodonapi extension, https://codeberg.org/simonpipe/yellow-mastodonapi
class YellowMastodonapi { class YellowMastodonapi {
const VERSION = "0.9.6"; const VERSION = "0.9.7";
public $yellow; // access to API public $yellow; // access to API
// Initialize extension // Initialize extension
@ -34,7 +34,7 @@ class YellowMastodonapi {
echo "Mastodon Import gestartet...\n"; echo "Mastodon Import gestartet...\n";
$count = $this->updateMastodonPosts(); $count = $this->updateMastodonPosts();
if ( $count===false ) { if ( $count===false ) {
echo "Fehler: API nicht erreichbar oder falsche ID.\n"; echo "Fehler: API nicht erreichbar, falsche ID oder Zugriff verweigert.\n";
return 500; return 500;
} }
echo "Erfolg: " . $count . " neue Posts verarbeitet.\n"; echo "Erfolg: " . $count . " neue Posts verarbeitet.\n";
@ -75,25 +75,32 @@ class YellowMastodonapi {
$statusSetting = $this->yellow->system->get("mastodonapiStatus"); $statusSetting = $this->yellow->system->get("mastodonapiStatus");
$maxAgeHours = intval($this->yellow->system->get("mastodonapiMaxAge")); $maxAgeHours = intval($this->yellow->system->get("mastodonapiMaxAge"));
$limit = intval($this->yellow->system->get("mastodonapiLimit")); $limit = intval($this->yellow->system->get("mastodonapiLimit"));
if ( empty($instanceUrl) || empty($accountId) ) return false; if ( empty($instanceUrl) || empty($accountId) ) return false;
$apiUrl = rtrim($instanceUrl, "/") . "/api/v1/accounts/" . $accountId . "/statuses?limit=" . $limit; $apiUrl = rtrim($instanceUrl, "/") . "/api/v1/accounts/" . $accountId . "/statuses?limit=" . $limit;
$headers = array("User-Agent: YellowMastodonapi/" . self::VERSION);
// FIX: Browser-ähnlicher User-Agent, da Snac strikt blockiert
$headers = array("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) YellowMastodonapi/" . self::VERSION);
if ( !empty($accessToken) ) $headers[] = "Authorization: Bearer " . $accessToken; if ( !empty($accessToken) ) $headers[] = "Authorization: Bearer " . $accessToken;
$ch = curl_init($apiUrl); $ch = curl_init($apiUrl);
curl_setopt_array($ch, array( curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 30, CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => $headers, CURLOPT_HTTPHEADER => $headers,
CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYPEER => false, // FIX: Kompatibilität für GoToSocial/Snac erhöht
CURLOPT_SSL_VERIFYHOST => 2 CURLOPT_SSL_VERIFYHOST => 0
)); ));
$json = curl_exec($ch); $json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); curl_close($ch);
if ( $json===false || $httpCode < 200 || $httpCode >= 300 ) return false; if ( $json===false || $httpCode < 200 || $httpCode >= 300 ) return false;
$posts = json_decode($json, true); $posts = json_decode($json, true);
if ( !is_array($posts) ) return false; if ( !is_array($posts) ) return false;
$postsCreated = 0; $postsCreated = 0;
foreach ( $posts as $post ) { foreach ( $posts as $post ) {
if ( !empty($post["reblog"]) || ( !empty($post["reblogged"]) && $post["reblogged"]===true ) ) continue; if ( !empty($post["reblog"]) || ( !empty($post["reblogged"]) && $post["reblogged"]===true ) ) continue;
@ -105,6 +112,7 @@ class YellowMastodonapi {
} }
$tags = array_column($post["tags"] ?? array(), "name"); $tags = array_column($post["tags"] ?? array(), "name");
if ( !empty($hashtag) && !in_array(strtolower($hashtag), array_map("strtolower", $tags)) ) continue; if ( !empty($hashtag) && !in_array(strtolower($hashtag), array_map("strtolower", $tags)) ) continue;
$title = $this->generateTitle($contentHtml); $title = $this->generateTitle($contentHtml);
$titleSlug = $this->generateTitleSlug($title); $titleSlug = $this->generateTitleSlug($title);
$fileName = date("Y-m-d", strtotime($createdAt)) . "-" . $titleSlug . ".md"; $fileName = date("Y-m-d", strtotime($createdAt)) . "-" . $titleSlug . ".md";
@ -152,21 +160,17 @@ class YellowMastodonapi {
if (!is_dir($dirPath)) mkdir($dirPath, 0755, true); if (!is_dir($dirPath)) mkdir($dirPath, 0755, true);
// Dateiname etwas robuster ermitteln
$fileName = basename(parse_url($imageUrl, PHP_URL_PATH)); $fileName = basename(parse_url($imageUrl, PHP_URL_PATH));
// Fallback falls Dateiname keine Endung hat (Mastodon-spezifisch)
if (!strpos($fileName, '.')) { if (!strpos($fileName, '.')) {
$fileName .= ".jpg"; $fileName .= ".jpg";
} }
$fullPath = $dirPath . $fileName; $fullPath = $dirPath . $fileName;
// Bestehende Datei nur akzeptieren, wenn sie nicht leer ist
if (file_exists($fullPath) && filesize($fullPath) > 0) return $fileName; if (file_exists($fullPath) && filesize($fullPath) > 0) return $fileName;
$ch = curl_init($imageUrl); $ch = curl_init($imageUrl);
// Browser-ähnlicher User-Agent hilft gegen CDNs
$headers = ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) YellowMastodonAPI"]; $headers = ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) YellowMastodonAPI"];
$accessToken = $this->yellow->system->get("mastodonapiAccessToken"); $accessToken = $this->yellow->system->get("mastodonapiAccessToken");
@ -179,7 +183,8 @@ class YellowMastodonapi {
CURLOPT_FOLLOWLOCATION => true, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 30, CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => $headers, CURLOPT_HTTPHEADER => $headers,
CURLOPT_SSL_VERIFYPEER => false, // Erhöht die Kompatibilität massiv CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 0
]); ]);
$imgData = curl_exec($ch); $imgData = curl_exec($ch);