Add Mastodon integration!
This commit is contained in:
@ -15,8 +15,14 @@ $config = [
|
||||
];
|
||||
|
||||
$integrations = [
|
||||
# Discord
|
||||
'discord_webhook_enabled' => 'false',
|
||||
'discord_webhook_name' => 'PTD Uploadinator',
|
||||
'discord_webhook_avatar' => '/images/site/web-app-manifest-192x192.webp',
|
||||
'discord_webhook_url' => 'https://discord.com/api/webhooks/1/1'
|
||||
|
||||
# Mastodon
|
||||
'mastodon_post_enabled' => 'false',
|
||||
'mastodon_post_instance' => 'https://mastodon.online',
|
||||
'mastodon_post_token' => ''
|
||||
];
|
||||
|
@ -3,4 +3,4 @@ if (!defined('Such_a_good_girl')) {
|
||||
die("Direct access not allowed.");
|
||||
}
|
||||
|
||||
define( 'PTD_VERSION', '3.3.0' );
|
||||
define('PTD_VERSION', '3.4.0');
|
103
upload/includes/integrations/mastodon_post.php
Normal file
103
upload/includes/integrations/mastodon_post.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
function send_mastodon_post(string $filename, DateTime $takenDate, string $year, string $month, string $copyright): void
|
||||
{
|
||||
global $integrations;
|
||||
|
||||
if (empty($integrations['mastodon_post_instance']) || empty($integrations['mastodon_post_token'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prot = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 ? "https" : "http";
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$imageUrl = "$prot://$host/images/$year/$month/fulls/$filename";
|
||||
$takenFormatted = $takenDate->format('F j, Y \a\t g:i A');
|
||||
$caption = "New image added!\nTaken on $takenFormatted";
|
||||
$imagePath = $_SERVER['DOCUMENT_ROOT'] . "/images/$year/$month/fulls/$filename";
|
||||
|
||||
$media_id = null;
|
||||
|
||||
if (file_exists($imagePath)) {
|
||||
$ch = curl_init("{$integrations['mastodon_post_instance']}/api/v2/media");
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt(
|
||||
$ch, CURLOPT_HTTPHEADER, [
|
||||
"Authorization: Bearer {$integrations['mastodon_post_token']}"
|
||||
]
|
||||
);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt(
|
||||
$ch, CURLOPT_POSTFIELDS, [
|
||||
'file' => new CURLFile($imagePath)
|
||||
]
|
||||
);
|
||||
$response = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($code >= 200 && $code < 300) {
|
||||
$data = json_decode($response, true);
|
||||
$media_id = $data['id'] ?? null;
|
||||
} else {
|
||||
error_log("Mastodon media upload failed: HTTP $code, response: $response");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wait_for_media_ready($media_id, $integrations['mastodon_post_instance'], $integrations['mastodon_post_token'])) {
|
||||
error_log("Mastodon media ID $media_id not ready in time.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$status_data = [
|
||||
"status" => $caption,
|
||||
"language" => "en",
|
||||
"visibility" => "public",
|
||||
];
|
||||
|
||||
if ($media_id) {
|
||||
$status_data['media_ids'] = [$media_id];
|
||||
}
|
||||
|
||||
$headers = [
|
||||
"Authorization: Bearer {$integrations['mastodon_post_token']}",
|
||||
"Content-Type: application/json"
|
||||
];
|
||||
|
||||
$ch = curl_init("{$integrations['mastodon_post_instance']}/api/v1/statuses");
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($status_data));
|
||||
$response = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($code < 200 || $code >= 300) {
|
||||
error_log("Mastodon post failed: HTTP $code, response: $response");
|
||||
}
|
||||
}
|
||||
|
||||
function wait_for_media_ready(string $media_id, string $instance, string $token, int $timeout = 15): bool
|
||||
{
|
||||
$start = time();
|
||||
do {
|
||||
sleep(1);
|
||||
$ch = curl_init("$instance/api/v1/media/$media_id");
|
||||
curl_setopt(
|
||||
$ch, CURLOPT_HTTPHEADER, [
|
||||
"Authorization: Bearer $token"
|
||||
]
|
||||
);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$media = json_decode($response, true);
|
||||
if (!empty($media['url'])) {
|
||||
return true;
|
||||
}
|
||||
} while (time() - $start < $timeout);
|
||||
|
||||
return false;
|
||||
}
|
@ -148,5 +148,8 @@ if (!empty($integrations['discord_webhook_enabled']) && $integrations['discord_w
|
||||
include_once 'includes/integrations/discord_webhook.php';
|
||||
send_discord_webhook($filename, $exifDate, $year, $month, $copyright, $hexcolor);
|
||||
}
|
||||
|
||||
if (!empty($integrations['mastodon_post_enabled']) && $integrations['mastodon_post_enabled'] === 'true') {
|
||||
include_once 'includes/integrations/mastodon_post.php';
|
||||
send_mastodon_post($filename, $exifDate, $year, $month, $copyright);
|
||||
}
|
||||
echo 'Upload successful';
|
||||
|
Reference in New Issue
Block a user