feat: massive performance and logic improvements

This commit is contained in:
2026-02-23 17:17:53 +01:00
parent 96db0131ad
commit a749a6b6aa
2 changed files with 46 additions and 49 deletions

View File

@@ -4,6 +4,7 @@
SPDX-FileCopyrightText: 2019 Björn Schießle SPDX-FileCopyrightText: 2019 Björn Schießle
--> -->
{{ if ne .Params.page true }} {{ if ne .Params.page true }}
<hr />
<div class="comments-container"> <div class="comments-container">
<h5>Comments</h5> <h5>Comments</h5>
<noscript> <noscript>

View File

@@ -40,8 +40,8 @@ function write_db($db, $data, $id) {
} }
$file['toots'] = $data; $file['toots'] = $data;
$file['timestamp'] = time(); $file['timestamp'] = time();
// encode and write file // encode and write file (no pretty print for performance)
$encoded = json_encode($file, JSON_PRETTY_PRINT); $encoded = json_encode($file);
file_put_contents($db, $encoded, LOCK_EX); file_put_contents($db, $encoded, LOCK_EX);
} }
/* delete file */ /* delete file */
@@ -81,22 +81,25 @@ function read_db($db, &$data, $cachetime, &$cachebreak, $id) {
/* TOOT FUNCTIONS */ /* TOOT FUNCTIONS */
function collectToots($instance, $uid, $min_id, $searchurl) { function collectToots($instance, $uid, $min_id, $searchurl) {
$raw = file_get_contents("$instance/api/v1/accounts/$uid/statuses?exclude_reblogs=true&exclude_replies=true&limit=50&min_id=$min_id"); $raw = @file_get_contents("$instance/api/v1/accounts/$uid/statuses?exclude_reblogs=true&exclude_replies=true&limit=50&min_id=$min_id");
if ($raw === false) {
debug("Failed to fetch toots from API");
return array();
}
$json_complete = json_decode($raw, true); $json_complete = json_decode($raw, true);
$json = array(); $json = array();
foreach ($json_complete as $toot) { foreach ($json_complete as $toot) {
$json[] = array('id' => $toot['id'], 'date' => $toot['created_at'] ,'url' => analyzeToot($instance, $toot['id'], $searchurl)); $url = analyzeToot($toot['content'], $toot['id'], $searchurl);
$json[] = array('id' => $toot['id'], 'date' => $toot['created_at'] ,'url' => $url);
} }
return($json); return($json);
} }
/* Find out if a toot contains the searched URL */ /* Find out if a toot contains the searched URL */
function analyzeToot($instance, $id, $searchurl) { function analyzeToot($content, $id, $searchurl) {
debug("Searching for $searchurl in $id"); debug("Searching for $searchurl in $id");
$raw = file_get_contents("$instance/api/v1/statuses/$id");
$json = json_decode($raw, true);
// search for $searchurl inside of <a> tags, until (and excluding) a " // search for $searchurl inside of <a> tags, until (and excluding) a "
preg_match("|$searchurl.+?(?=\")|i", $json['content'], $matches); preg_match("|$searchurl.+?(?=\")|i", $content, $matches);
if(!empty($matches)) { if(!empty($matches)) {
return(strtolower($matches[0])); // take first match inside toot return(strtolower($matches[0])); // take first match inside toot
@@ -123,33 +126,29 @@ function filterComments($descendants, $root, &$result) {
} }
return $result; return $result;
} }
/* get /context of toot */ /* get /context of toot and extract stats - combined to reduce API calls */
function tootContext($instance, $id, &$result) { function tootContextAndStats($instance, $id, &$result) {
$raw = file_get_contents("$instance/api/v1/statuses/$id/context"); debug("Fetching context and stats for ID $id");
$json = json_decode($raw, true);
filterComments($json['descendants'], $id, $result); // Fetch context (descendants/replies)
} $raw_context = @file_get_contents("$instance/api/v1/statuses/$id/context");
/* extract stats info from toot */ if ($raw_context !== false) {
function filterStats($stats) { $json_context = json_decode($raw_context, true);
$result = [ filterComments($json_context['descendants'], $id, $result);
'reblogs' => (int)$stats['reblogs_count'], } else {
'favs' => (int)$stats['favourites_count'], debug("Failed to fetch context for $id");
'replies' => (int)$stats['replies_count'], }
'url' => $stats['url']
]; // Fetch stats
return $result; $raw_stats = @file_get_contents("$instance/api/v1/statuses/$id");
} if ($raw_stats !== false) {
/* for toot, extract interesting statistics */ $json_stats = json_decode($raw_stats, true);
function tootStats($instance, $id, &$result) { $result['stats']['reblogs'] = (int)$json_stats['reblogs_count'];
debug("Checking ID $id"); $result['stats']['favs'] = (int)$json_stats['favourites_count'];
$raw = file_get_contents("$instance/api/v1/statuses/$id"); $result['stats']['replies'] = (int)$json_stats['replies_count'];
$json = json_decode($raw, true); $result['stats']['url'] = $json_stats['url'];
$newStats = filterStats($json); } else {
$result['stats']['reblogs'] += $newStats['reblogs']; debug("Failed to fetch stats for $id");
$result['stats']['favs'] += $newStats['favs'];
$result['stats']['replies'] += $newStats['replies'];
if (empty($result['stats']['url'])) {
$result['stats']['url'] = $newStats['url'];
} }
} }
@@ -202,19 +201,17 @@ $result_empty = ['comments' => [], 'stats' => ['reblogs' => 0, 'favs' => 0, 'rep
$result = $result_empty; $result = $result_empty;
/* check if URL from $search exists in $toots */ /* check if URL from $search exists in $toots */
$id = array_keys( $found_id = null;
array_filter( foreach ($toots as $toot) {
array_column($toots, 'url'), if (!empty($toot['url']) && strpos($toot['url'], $search) !== false) {
function ($value) use ($search) { $found_id = $toot['id']; // will keep the oldest (last in array)
return (strpos($value, $search) !== false); }
} }
)
); if ($found_id === null) {
if (empty($id)) {
debug("Blog URL \"$search\" has not been found"); debug("Blog URL \"$search\" has not been found");
} else { } else {
// if multiple toots with the searched URL exist, take the oldest one (largest array index) $id = $found_id;
$id = $toots[end($id)]['id'];
/* read cached comments, or reload new comments if cached data too old */ /* read cached comments, or reload new comments if cached data too old */
$cachebreak = false; $cachebreak = false;
@@ -228,9 +225,8 @@ if (empty($id)) {
$result = $result_empty; $result = $result_empty;
read_db($dbc, $result, $ctc, $cachebreak, $id); read_db($dbc, $result, $ctc, $cachebreak, $id);
/* Extract comments and stats from toot */ /* Extract comments and stats from toot */
tootContext($instance, $id, $result); tootContextAndStats($instance, $id, $result);
tootStats($instance, $id, $result); // Always count replies manually for accuracy
// FIXME: At the moment the API doesn't return the correct replies count so I count it manually
$result['stats']['replies'] = count($result['comments']); $result['stats']['replies'] = count($result['comments']);
$result['stats']['root'] = $id; $result['stats']['root'] = $id;