feat: support defining Mastodon toot URL

This commit is contained in:
2026-02-24 11:55:42 +01:00
parent 330925edce
commit 67d92eba01
4 changed files with 100 additions and 22 deletions

View File

@@ -62,6 +62,31 @@ Comments are loaded automatically via JavaScript when visitors view a blog post.
- Queries the PHP backend to find matching Mastodon toots
- Displays replies as comments with full formatting
### Optional: Direct Toot URL (Recommended for Performance)
For better performance, you can specify the Mastodon toot URL directly in your post's front matter:
```yaml
---
title: "My Post Title"
mastodon_toot_url: "https://mastodon.social/@username/113456789012345678"
---
```
**Benefits:**
- Skips the entire toot search phase
- Reduces API calls significantly
- Faster page loads
- Works across different Mastodon instances
- Ensures the correct toot is always used
**When to use:**
- For any post where you know the Mastodon toot URL
- Especially recommended for popular or archived posts
- When you've shared the post on a different Mastodon instance
If no `mastodon_toot_url` is provided, the system automatically falls back to searching for toots containing the post URL.
### Force Cache Refresh
To manually clear and rebuild the cache:

View File

@@ -30,3 +30,4 @@
<script>var MastodonUser="{{ .Site.Params.mastodoncomments.user }}"</script>
<script>var BlogRegex="{{ .Site.Params.mastodoncomments.regex }}"</script>
<script>var CommentsContact="{{ .Site.Params.mastodoncomments.contact }}"</script>
<script>var MastodonTootUrl="{{ .Params.mastodon_toot_url }}"</script>

View File

@@ -28,12 +28,18 @@ $(document).ready(function() {
debugLog('Searching for comments for: ' + RelPermalink);
// Check if a direct Mastodon toot URL is provided
var ajaxData = { search: RelPermalink };
if (MastodonTootUrl && MastodonTootUrl !== "") {
// Pass the full URL to PHP so it can extract instance and ID
ajaxData.toot_url = MastodonTootUrl;
debugLog('Using predefined Mastodon toot URL: ' + MastodonTootUrl);
}
$.ajax({
url: "/comments/getcomments.php",
type: "get",
data: {
search : RelPermalink
},
data: ajaxData,
success: function(data) {
// Enable debug logging if backend has debug enabled
if (data.debug === true) {

View File

@@ -10,8 +10,11 @@ $instance = $config['mastodon-instance'];
$uid = $config['user-id'];
$searchurl = $config['search-url'];
$search = isset($_GET['search']) ? strtolower($_GET['search']) : '';
$toot_url = isset($_GET['toot_url']) ? $_GET['toot_url'] : null;
$force_refresh = isset($_GET['force_refresh']) && $_GET['force_refresh'] == '1';
$debug_on = $config['debug'];
debug("Request parameters - search: $search, toot_url: " . ($toot_url ? $toot_url : "not provided") . ", force_refresh: " . ($force_refresh ? "yes" : "no"));
/* cache files */
$ctt = $config['cache_toots'];
$dbt = "cache-toots.json";
@@ -45,6 +48,19 @@ function debug($data) {
}
}
/* Parse Mastodon toot URL to extract instance and toot ID */
function parseTootUrl($url) {
// Expected format: https://instance.example/@username/1234567890
// or: https://instance.example/users/username/statuses/1234567890
if (preg_match('|^(https?://[^/]+)/.*/(\d+)$|i', $url, $matches)) {
return [
'instance' => $matches[1],
'id' => $matches[2]
];
}
return null;
}
/* CACHE FUNCTIONS */
/* write data to file */
function write_db($db, $data, $id) {
@@ -170,12 +186,41 @@ function tootContextAndStats($instance, $id, &$result) {
* START PROGRAM
***************/
/* check whether the cached file containing all toots is older than max. cache time */
// this at the same time loads the cached DB, either way
$cachebreak = $force_refresh; // Force cache break if requested
read_db($dbt, $toots, $ctt, $cachebreak, false);
// create empty $result template
$result_empty = ['comments' => [], 'stats' => ['reblogs' => 0, 'favs' => 0, 'replies' => 0, 'url' => '', 'root' => 0]];
$result = $result_empty;
if ($cachebreak) {
/* If toot_url is provided, skip the toot search entirely */
$toot_instance = $instance; // Default to config instance
$id = null; // Initialize
if ($toot_url) {
$parsed = parseTootUrl($toot_url);
if ($parsed) {
$id = $parsed['id'];
$toot_instance = $parsed['instance'];
debug("Toot URL provided: $toot_url");
debug("Extracted - Instance: $toot_instance, ID: $id");
// When using a custom instance, include instance hash in cache filename to avoid collisions
if ($toot_instance !== $instance) {
$instance_hash = md5($toot_instance);
$dbc = "cache-comments_%id-{$instance_hash}.json";
debug("Using instance-specific cache file for non-default instance");
}
} else {
debug("Failed to parse toot URL: $toot_url");
$toot_url = null; // Fall back to search
}
}
if (!$toot_url) {
/* check whether the cached file containing all toots is older than max. cache time */
// this at the same time loads the cached DB, either way
$cachebreak = $force_refresh; // Force cache break if requested
read_db($dbt, $toots, $ctt, $cachebreak, false);
if ($cachebreak) {
/* Collect all the toots */
/* get id of latest cached toot, and set as $min_id */
debug("Toots cache outdated. Checking for new toots");
@@ -208,24 +253,25 @@ if ($cachebreak) {
}
} else {
debug("Toots cache is up-to-date");
}
}
// create empty $result
$result_empty = ['comments' => [], 'stats' => ['reblogs' => 0, 'favs' => 0, 'replies' => 0, 'url' => '', 'root' => 0]];
$result = $result_empty;
/* check if URL from $search exists in $toots */
$found_id = null;
foreach ($toots as $toot) {
if (!empty($toot['url']) && strpos($toot['url'], $search) !== false) {
$found_id = $toot['id']; // will keep the oldest (last in array)
}
}
/* check if URL from $search exists in $toots */
$found_id = null;
foreach ($toots as $toot) {
if (!empty($toot['url']) && strpos($toot['url'], $search) !== false) {
$found_id = $toot['id']; // will keep the oldest (last in array)
if ($found_id === null) {
debug("Blog URL \"$search\" has not been found");
} else {
$id = $found_id;
}
}
if ($found_id === null) {
debug("Blog URL \"$search\" has not been found");
} else {
$id = $found_id;
/* Process comments if we have a toot ID (either from URL or search) */
if ($id) {
/* read cached comments, or reload new comments if cached data too old */
$cachebreak = false;
@@ -239,7 +285,7 @@ if ($found_id === null) {
$result = $result_empty;
read_db($dbc, $result, $ctc, $cachebreak, $id);
/* Extract comments and stats from toot */
tootContextAndStats($instance, $id, $result);
tootContextAndStats($toot_instance, $id, $result);
// Always count replies manually for accuracy
$result['stats']['replies'] = count($result['comments']);
$result['stats']['root'] = $id;