Alcea
|
4d1afd6e72
|
Add files via upload
Read all profileinfo + ava from profileinfo.json
|
2025-07-20 15:35:22 +02:00 |
|
Alcea
|
a2856a6d33
|
Add files via upload
Router Revamp to serve tsgs and emoji in tags
----
if (preg_match('/^\/' . $username . '\/status\/([a-z0-9\-]+)$/', $uri, $m)) {
$postId = $m[1];
$post = null; $date = ''; $hash = '';
foreach ($data as $entry)
foreach ($entry as $d => $c)
if ("$d-" . substr(md5($c['value']), 0, 8) === $postId) {
$post = $c; $date = $d; $hash = substr(md5($c['value']), 0, 8); break 2;
}
if (!$post) {
http_response_code(404);
echo "Not found";
exit;
}
// Construct noteId
$noteId = "$baseUrl/$username/status/{$date}-$hash";
// Extract content
$content = $post['value'];
// Prepare tags (hashtags, mentions, emoji tags)
$tags = [];
$emojiTags = [];
$hashtags = [];
$mentions = [];
// Extract hashtags: #hashtag
preg_match_all('/#(\w+)/', $content, $hashtags);
foreach ($hashtags[1] as $hashtag) {
$tags[] = [
"type" => "Hashtag",
"name" => "#$hashtag",
"href" => "$baseUrl/tags/$hashtag"
];
}
// Extract mentions: @username
preg_match_all('/@(\w+)/', $content, $mentions);
foreach ($mentions[1] as $mention) {
// Not directly used in tags, but can be added if needed
}
// Extract emoji tags: :emoji:
preg_match_all('/:([\w\+\-]+):/', $content, $emojiTags);
foreach ($emojiTags[1] as $emoji) {
// Assuming emoji images are stored on a path like "/z_files/emojis/{emoji}.gif"
$tags[] = [
"type" => "Emoji",
"name" => ":$emoji:",
"icon" => [
"type" => "Image",
"mediaType" => "image/gif",
"url" => "$baseUrl/z_files/emojis/$emoji.gif"
]
];
}
// Determine if client accepts JSON
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
if (str_contains($accept, 'application/activity+json') || str_contains($accept, 'application/ld+json')) {
header('Content-Type: application/activity+json');
echo json_encode([
'@context' => [
'https://www.w3.org/ns/activitystreams',
[
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'toot' => 'http://joinmastodon.org/ns#',
'featured' => [
'@id' => 'toot:featured',
'@type' => '@id'
]
]
],
'id' => $noteId,
'type' => 'Note',
'published' => date(DATE_ATOM, strtotime($date)),
'attributedTo' => "$baseUrl/$username",
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content' => $content,
'contentMap' => [
'und' => $content,
'html' => nl2br($content) // Convert newlines to <br> for HTML
],
'tag' => $tags,
], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
exit;
}
// Otherwise, return an HTML redirect after 1 second
header('Content-Type: text/html');
$redirectUrl = "https://alceawis.com#" . $noteId;
echo <<<HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Redirecting…</title>
<meta http-equiv="refresh" content="1; url=$redirectUrl">
</head>
<body>
<p>Redirecting to <a href="$redirectUrl">$redirectUrl</a>…</p>
</body>
</html>
HTML;
exit;
}
if ($uri === "/$username/followers" || $uri === "/$username/followers/") {
header('Content-Type: application/activity+json');
header('Vary: Accept');
$followers = file_exists(__DIR__ . '/followers.json') ? json_decode(file_get_contents(__DIR__ . '/followers.json'), true) : [];
echo json_encode(['@context'=>'https://www.w3.org/ns/activitystreams','id'=>"$baseUrl/$username/followers",'type'=>'OrderedCollection','totalItems'=>count($followers),'orderedItems'=>$followers], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
exit;
}
|
2025-07-20 12:23:17 +02:00 |
|
Alcea
|
441d6307fe
|
Add files via upload
Pull profile info from json
(Attempted some fixes for shorthand remote server emoj rendering suchas 🤣 :RJ_RedJohn_TheMentalist: :confused_dog:
But alas...
https://alceawis.com/alceawis/status/20250719-e29c54df
https://alceawis.com/alceawis/status/20250719-1ab45011
|
2025-07-19 22:32:48 +02:00 |
|
Alcea
|
41d0596d66
|
Add files via upload
Replace status redirect handler ro resirect to instsnce ststus AND serve json for 2 seconds
if (preg_match('/^\/' . $username . '\/status\/([a-z0-9\-]+)$/', $uri, $m)) {
$postId = $m[1];
$post = null; $date = ''; $hash = '';
foreach ($data as $entry)
foreach ($entry as $d => $c)
if ("$d-" . substr(md5($c['value']),0,8) === $postId) {
$post = $c; $date = $d; $hash = substr(md5($c['value']),0,8); break 2;
}
if (!$post) {
http_response_code(404);
echo "Not found";
exit;
}
$noteId = "$baseUrl/$username/status/{$date}-$hash";
// Determine if client accepts JSON
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
if (str_contains($accept, 'application/activity+json') || str_contains($accept, 'application/ld+json')) {
header('Content-Type: application/activity+json');
echo json_encode([
'@context' => 'https://www.w3.org/ns/activitystreams',
'id' => $noteId,
'type' => 'Note',
'published' => date(DATE_ATOM, strtotime($date)),
'attributedTo' => "$baseUrl/$username",
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content' => $post['value'],
'contentMap' => ['und' => $post['value']],
], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
exit;
}
// Otherwise, return an HTML redirect after 1 second
header('Content-Type: text/html');
$redirectUrl = "https://alceawis.com#" . $noteId;
echo <<<HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Redirecting…</title>
<m eta ht. tp-equiv="refresh" content="1; url=$re. directUrl">
</head>
<body>
<p>Redirecting to <a href="$redirectUrl">$redirectUrl</a>…</p>
</body>
</html>
HTML;
exit;
}
|
2025-07-19 09:30:59 +02:00 |
|
Alcea
|
7226b2c6a2
|
Add files via upload
Sending Reply notifications works now !
--------------
/* ---------- build outbox ---------- */
$lastNoteId = null;
foreach ($data as $entry) {
foreach ($entry as $date => $content) {
$hash = substr(md5($content['value']), 0, 8);
$text = formatEmojis($content['value']);
$inReplyTo = null;
$mentionTag = null;
$mentionAcct = null;
if (preg_match('/💬(https?:\/\/[^\s💬]+)💬/', $text, $match)) {
$inReplyTo = $match[1];
$lines = explode("\n", $text);
array_shift($lines);
$text = implode("\n", $lines);
}
// Extract hashtags
$hashtags = array_filter(array_map('trim', explode(',', $content['hashtags'] ?? '')));
// Handle @mention if replying to someone
if ($inReplyTo && preg_match('~https?://([^/]+)/@([a-zA-Z0-9_]+)~', $inReplyTo, $matches)) {
$mentionDomain = $matches[1];
$mentionUser = $matches[2];
$mentionAcct = "$mentionUser@$mentionDomain";
$mentionUrl = "https://$mentionDomain/@$mentionUser";
$mentionText = "@$mentionAcct ";
if (strpos($text, $mentionText) !== 0) {
$text = $mentionText . $text;
}
// Create Mention tag object
$mentionTag = [
'type' => 'Mention',
'href' => $mentionUrl,
'name' => "@$mentionAcct"
];
}
// Format quotes and links
$quotedText = formatQuotes($text);
$htmlText = preg_replace(
'~(https?://[^\s<]+)~i',
'<a href="$1" target="_blank" rel="nofollow noopener noreferrer">$1</a>',
$quotedText
);
// Convert hashtags to tag links
$htmlText = preg_replace_callback('/#([\w-]+)/', function($matches) use ($domain) {
$tag = $matches[1];
$url = "https://$domain/tags/" . urlencode($tag);
return "<a href=\"$url\" rel=\"tag nofollow noopener noreferrer\">#" . htmlspecialchars($tag) . "</a>";
}, $htmlText);
$htmlText = nl2br($htmlText);
// Build hashtag tag objects
$tags = array_map(function($tag) use ($domain) {
return [
'type' => 'Hashtag',
'name' => "#$tag",
'href' => "https://$domain/tags/$tag"
];
}, $hashtags);
// Extract emoji shortcodes and create tag objects
preg_match_all('/:([a-zA-Z0-9_]+):/', $content['value'], $emojiMatches);
foreach ($emojiMatches[1] as $shortcode) {
$tags[] = [
'type' => 'Emoji',
'name' => ":$shortcode:",
'icon' => [
'type' => 'Image',
'mediaType' => 'image/gif',
'url' => "https://$domain/z_files/emojis/$shortcode.gif"
]
];
}
// Add mention tag if applicable
if ($mentionTag) {
$tags[] = $mentionTag;
}
// Compose Note ID
$noteId = "$baseUrl/$username/status/{$date}-$hash";
// Build the Note object
$note = [
'id' => $noteId,
'type' => 'Note',
'published' => date(DATE_ATOM, strtotime($date)),
'attributedTo' => "$baseUrl/$username",
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content' => $htmlText,
'contentMap' => [
'und' => $text,
'html' => $htmlText,
],
'tag' => $tags,
];
// Add inReplyTo if exists
if ($inReplyTo) {
$note['inReplyTo'] = $inReplyTo;
}
$outboxItems[] = $note;
// Send activity only if not already pushed
if (!in_array($noteId, $pushed)) {
sendCreateActivity($note);
$pushed[] = $noteId;
file_put_contents($pushedFile, json_encode($pushed, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}
}
// Log last pushed note
if (!empty($pushed)) {
$lastPushedUrl = end($pushed);
foreach ($outboxItems as $item) {
if ($item['id'] === $lastPushedUrl) {
$noteText = $item['contentMap']['und'] ?? '[No text]';
$inReplyTo = $item['inReplyTo'] ?? 'None';
if (!file_exists('outbox.log')) {
file_put_contents('outbox.log', '');
}
$logEntry = sprintf(
"[%s] New post created\nStatus URL: %s\nReply To: %s\nContent:\n%s\n\n",
date('Y-m-d H:i:s'),
$lastPushedUrl,
$inReplyTo,
$noteText
);
//file_put_contents('outbox.log', $logEntry, FILE_APPEND | LOCK_EX);
break;
}
}
}
|
2025-07-19 00:02:23 +02:00 |
|
Alcea
|
d6fea241fa
|
Add files via upload
Reimplemented emoji array tags *phew*
foreach ($data as $entry) {
foreach ($entry as $date => $content) {
$hash = substr(md5($content['value']), 0, 8);
$text = formatEmojis($content['value']);
$inReplyTo = null;
if (preg_match('/💬(https?:\/\/[^\s💬]+)💬/', $text, $match)) {
$inReplyTo = $match[1];
$lines = explode("\n", $text);
array_shift($lines);
$text = implode("\n", $lines);
}
$hashtags = array_filter(array_map('trim', explode(',', $content['hashtags'] ?? '')));
//$escapedText = htmlspecialchars($text);
//$quotedText = formatQuotes($escapedText);
$quotedText = formatQuotes($text);
$htmlText = preg_replace(
'~(https?://[^\s<]+)~i',
'<a href="$1" target="_blank" rel="nofollow noopener noreferrer">$1</a>',
$quotedText
);
$htmlText = preg_replace_callback('/#([\w-]+)/', function($matches) use ($domain) {
$tag = $matches[1];
$url = "https://$domain/tags/" . urlencode($tag);
return "<a href=\"$url\" rel=\"tag nofollow noopener noreferrer\">#" . htmlspecialchars($tag) . "</a>";
}, $htmlText);
$htmlText = nl2br($htmlText);
$tags = array_map(function($tag) use ($domain) {
return [
'type' => 'Hashtag',
'name' => "#$tag",
'href' => "https://$domain/tags/$tag"
];
}, $hashtags);
preg_match_all('/:([a-zA-Z0-9_]+):/', $content['value'], $emojiMatches);
$emojiTags = [];
foreach ($emojiMatches[1] as $shortcode) {
$emojiTags[] = [
'type' => 'Emoji',
'name' => ":$shortcode:",
'icon' => [
'type' => 'Image',
'mediaType' => 'image/gif',
'url' => "https://$domain/z_files/emojis/$shortcode.gif"
]
];
}
$tags = array_merge($tags, $emojiTags);
$noteId = "$baseUrl/$username/status/{$date}-$hash";
$note = [
'id' => $noteId,
'type' => 'Note',
'published' => date(DATE_ATOM, strtotime($date)),
'attributedTo' => "$baseUrl/$username",
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content' => $htmlText,
'contentMap' => [
'und' => $text,
'html' => $htmlText,
],
'tag' => $tags,
];
if ($inReplyTo) {
$note['inReplyTo'] = $inReplyTo;
}
$outboxItems[] = $note;
if (!in_array($noteId, $pushed)) {
sendCreateActivity($note);
$pushed[] = $noteId;
file_put_contents($pushedFile, json_encode($pushed, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}
}
|
2025-07-18 04:19:10 +02:00 |
|
Alcea
|
91b153b721
|
Add files via upload
Allow replying if a 💬url💬 is in text body (to it)
/* ---------- build outbox ---------- */
foreach ($data as $entry) {
foreach ($entry as $date => $content) {
$hash = substr(md5($content['value']), 0, 8);
$text = formatEmojis($content['value']);
// 💬 inReplyTo detection
$inReplyTo = null;
if (preg_match('/💬\s*(https?:\/\/[^\s💬]+)\s*💬/', $text, $match)) {
$inReplyTo = trim($match[1]);
$text = trim(str_replace($match[0], '', $text)); // optionally remove 💬URL💬 from post
}
$hashtags = array_filter(array_map('trim', explode(',', $content['hashtags'] ?? '')));
$quoted = formatQuotes($text);
$htmlText = preg_replace('~(https?://[^\s<]+)~i', '<a href="$1" target="_blank" rel="nofollow noopener noreferrer">$1</a>', $quoted);
$htmlText = preg_replace_callback('/#([\w-]+)/', fn($m) => "<a href=\"https://$GLOBALS[domain]/tags/" . urlencode($m[1]) . "\" rel=\"tag nofollow noopener noreferrer\">#" . htmlspecialchars($m[1]) . "</a>", $htmlText);
$htmlText = nl2br($htmlText);
$tags = array_map(fn($tag) => ['type'=>'Hashtag','name'=>"#$tag",'href'=>"https://$GLOBALS[domain]/tags/$tag"], $hashtags);
preg_match_all('/:([a-zA-Z0-9_]+):/', $content['value'], $emo);
foreach ($emo[1] as $sc)
$tags[] = ['type'=>'Emoji','name'=>":$sc:",'icon'=>['type'=>'Image','mediaType'=>'image/gif','url'=>"https://$GLOBALS[domain]/z_files/emojis/$sc.gif"]];
$noteId = "$baseUrl/$username/status/{$date}-$hash";
$note = [
'id' => $noteId,
'url' => $noteId,
'type' => 'Note',
'published' => date(DATE_ATOM, strtotime($date)),
'attributedTo' => "$baseUrl/$username",
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content' => $htmlText,
'contentMap' => ['und' => $text,'html' => $htmlText],
'tag' => $tags,
'locked' => false,
'bot' => false,
'discoverable' => true,
'group' => false,
'manuallyApprovesFollowers' => false,
];
if ($inReplyTo) {
$note['inReplyTo'] = $inReplyTo;
}
$outboxItems[] = $note;
if (!in_array($noteId, $pushed)) {
sendCreateActivity($note);
$pushed[] = $noteId;
}
}
}
file_put_contents($pushedFile, json_encode($pushed, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
2025-07-16 11:29:07 +02:00 |
|
Alcea
|
89050347a4
|
Add files via upload
Force discoverability in posts
'locked' => false,
'bot' => false,
'discoverable' => true,
'group' => false,
|
2025-07-15 03:21:16 +02:00 |
|
Alcea
|
53dc0d5107
|
Add files via upload
Allow direct mentions
|
2025-07-13 18:31:20 +02:00 |
|
Alcea
|
3ba1c057a5
|
Add files via upload
|
2025-07-13 09:57:16 +02:00 |
|
Alcea
|
636ac2c446
|
Add files via upload
|
2025-07-12 22:58:20 +02:00 |
|
Alcea
|
ca37cb4966
|
Add files via upload
Added interaction logging and a rudimentary notification system
|
2025-07-12 14:48:29 +02:00 |
|
Alcea
|
bfceb1d47c
|
Add files via upload
Added htmlspecialchars fix in quotes
|
2025-07-12 10:49:31 +02:00 |
|
Alcea
|
2174c47f4f
|
Add files via upload
Quote Posts added
|
2025-07-12 07:16:33 +02:00 |
|
Alcea
|
473fed886a
|
Add files via upload
Added PostGET for individual statuses via hash
|
2025-07-11 21:05:57 +02:00 |
|
Alcea
|
8c4f72b50f
|
Add files via upload
|
2025-07-11 15:45:02 +02:00 |
|
alceawisteria
|
c45a404e3a
|
Upload files to "/"
Can follow user remotely now
|
2025-07-09 23:05:20 +02:00 |
|
alceawisteria
|
a973aaeedf
|
Upload files to "/"
|
2025-07-08 20:15:51 +02:00 |
|