[
'method' => 'GET',
'header' => [
'User-Agent: MastofetchBot/1.0 (+https://mastofetch.vercel.app)',
],
'timeout' => 10 // in seconds
]
];
// The actual fetching process
$context = stream_context_create($opts);
$response = @file_get_contents($fullUrl, false, $context);
if ($response === false) {
return [];
}
$data = json_decode($response, true);
return is_array($data) ? $data : [];
}
function fetchFromAnyInstance($instances, $limit = 10, $maxAttempts = 5)
{
$tried = [];
for ($i = 0; $i < $maxAttempts; $i++) {
$url = $instances[array_rand($instances)];
if (in_array($url, $tried)) continue;
$tried[] = $url;
$posts = fetchPostsFromMastodon($url, $limit);
if (!empty($posts)) {
return $posts;
}
}
return [];
}
// The decoding process
function decodeEntities($text)
{
return html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
// Decoding the profile picture of the Mastodon user
function getAuthorProfileImage($account)
{
return $account['avatar'];
}
// Decoding the time and date of the posts and encoding it as the estimated length of time between you seeing the post and the time it was posted
function getTimeElapsedString($datetime)
{
$now = new DateTime("now", new DateTimeZone("UTC"));
$ago = new DateTime($datetime, new DateTimeZone("UTC"));
$diff = $now->diff($ago);
$string = [
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
];
foreach ($string as $k => &$v) {
if ($diff->$k) {
$v = $diff->$k . ' ' . ($diff->$k > 1 ? $v . 's' : $v);
} else {
unset($string[$k]);
}
}
return $string ? implode(', ', array_slice($string, 0, 1)) . ' ago' : 'just now';
}
// Includes some safety protections like sanitization
if (isset($_GET['ajax']) && $_GET['ajax'] === '1') {
$exclude = filter_input(INPUT_GET, 'exclude', FILTER_SANITIZE_URL);
$posts = fetchFromAnyInstance($instances, 10);
// The encoding of the lazyload next post items
foreach ($posts as $post) {
// 🚫 Skip sensitive posts
if (!empty($post['sensitive']) && $post['sensitive'] === true) {
continue;
}
$authorProfileImage = getAuthorProfileImage($post['account']);
echo "
";
echo "
";
$profileUrl = htmlspecialchars($post['account']['url'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
$displayName = htmlspecialchars($post['account']['display_name'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
echo "
{$displayName}
";
echo "
Posted " . getTimeElapsedString($post['created_at']) . "
";
echo "
" . strip_tags(decodeEntities($post['content']), '
') . "
";
if (!empty($post['media_attachments'])) {
foreach ($post['media_attachments'] as $attachment) {
if ($attachment['type'] === 'image') {
echo "
";
} elseif ($attachment['type'] === 'video') {
echo "
";
}
}
}
echo "
";
}
exit;
}
// 5 Posts from the 1st instance will initially appear then the rest will appear during the lazyload
$firstInstance = $instances[array_rand($instances)];
$initialPosts = fetchFromAnyInstance($instances, 5);
?>
Mastofetch - Catch the fediverse in your hands
";
echo "
";
$profileUrl = htmlspecialchars($post['account']['url'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
$displayName = htmlspecialchars($post['account']['display_name'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
echo "
{$displayName}
Posted " . getTimeElapsedString($post['created_at']) . "
";
echo "
" . strip_tags(decodeEntities($post['content']), '
') . "
";
if (!empty($post['media_attachments'])) {
foreach ($post['media_attachments'] as $attachment) {
if ($attachment['type'] === 'image') {
echo "
";
} elseif ($attachment['type'] === 'video') {
echo "
";
}
}
}
echo "
";
}
?>
Loading posts...