Alcea
5cd51f6d1e
Add files via upload
2025-07-20 19:57:28 +02:00
Alcea
524c4c80b4
Add files via upload
2025-07-20 19:03:06 +02:00
Alcea
f5b9e8f411
Add files via upload
2025-07-20 16:41:05 +02:00
Alcea
4d1afd6e72
Add files via upload
...
Read all profileinfo + ava from profileinfo.json
2025-07-20 15:35:22 +02:00
Alcea
30de670dce
Add files via upload
...
Set indexable to true too
$profileObject = [
'@context' => 'https://www.w3.org/ns/activitystreams ',
'id' => "$baseUrl/$username",
'type' => 'Person',
'name' => 'Alcea Bot',
'discoverable' => true, // Update the discoverable field
'locked' => false,
'bot' => false,
// Add any other fields you need to update
'preferredUsername' => $username,
'summary' => formatDescriptionLinks($description),
'icon' => [
'type' => 'Image',
'mediaType' => 'image/gif',
'url' => $imageUrl,
],
'inbox' => "$baseUrl/$username/inbox",
'outbox' => "$baseUrl/$username/outbox",
'followers' => "$baseUrl/$username/followers",
'publicKey' => [
'id' => "$baseUrl/$username#main-key",
'owner' => "$baseUrl/$username",
'publicKeyPem' => @file_get_contents(__DIR__ . '/public.pem'),
'publicKeyPem' => @file_get_contents(__DIR__ . '/public.pem'),
],
'fields' => $fields,
'discoverability' => 'public', // <-- Here is the key for discoverability
'indexable' => 'true',
];
2025-07-20 14:17:59 +02:00
Alcea
40222cd970
Add files via upload
...
Post php to post directly without update sync
2025-07-20 14:03: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
30d1459100
Add files via upload
2025-07-20 02:44:06 +02:00
Alcea
b1266304f1
Add files via upload
...
<button class="json-btn" data-json-url="${post.id}" style="padding:5px 10px; cursor:pointer;background: rgba(255, 105, 180, 0.7); border: none;border-radius: 12px;color: white;font-weight: bold;transition: background 0.3s ease;"> Show JSON</button>
<!--Show--Json-->
<script>
(function() {
const modalHTML = `
<div id="jsonModal" style="
display:none;
position:fixed;
top:0; left:0;
width:100vw; height:100vh;
background:rgba(0,0,0,0.5);
justify-content:center;
align-items:center;
z-index:1000;
">
<div style="
background:#fff;
padding:1em;
max-width:90%;
max-height:80vh;
overflow:auto;
border-radius:5px;
position:relative;
width: 90%;
max-width: 600px;
" onclick="event.stopPropagation()">
<button id="copyJsonBtn" style="
position:absolute; top:10px; right:10px;
padding:5px 10px; cursor:pointer;
background: rgba(255, 105, 180, 0.7); /* pink with 70% opacity */
border: none;
border-radius: 12px; /* rounded corners */
color: white;
font-weight: bold;
transition: background 0.3s ease;
" disabled>Copy</button>
<pre id="jsonContent" style="
white-space:pre-wrap;
font-size:0.85em;
margin-top: 40px;
user-select: text;
"></pre>
</div>
</div>
`;
const tempDiv = document.createElement('div');
tempDiv.innerHTML = modalHTML;
document.body.appendChild(tempDiv.firstElementChild);
const copyBtn = document.getElementById('copyJsonBtn');
const content = document.getElementById('jsonContent');
copyBtn.addEventListener('click', () => {
if (copyBtn.disabled) return;
const textToCopy = content.textContent;
if (!textToCopy) return;
navigator.clipboard.writeText(textToCopy)
.then(() => {
copyBtn.textContent = 'Copied!';
setTimeout(() => copyBtn.textContent = 'Copy', 1500);
})
.catch(() => {
copyBtn.textContent = 'Failed to copy';
setTimeout(() => copyBtn.textContent = 'Copy', 1500);
});
});
})();
document.addEventListener('click', async (e) => {
const modal = document.getElementById('jsonModal');
const copyBtn = document.getElementById('copyJsonBtn');
const content = document.getElementById('jsonContent');
if (e.target === modal) {
modal.style.display = 'none';
return;
}
if (e.target.matches('.json-btn')) {
const url = e.target.getAttribute('data-json-url');
if (!url) {
content.textContent = '❌ Invalid JSON URL.';
modal.style.display = 'flex';
copyBtn.disabled = true;
return;
}
content.textContent = 'Loading...';
modal.style.display = 'flex';
copyBtn.disabled = true;
try {
const res = await fetch(url, { headers: { 'Accept': 'application/activity+json' } });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
content.textContent = JSON.stringify(data, null, 2);
copyBtn.disabled = false;
copyBtn.textContent = 'Copy';
} catch (err) {
content.textContent = `❌ Failed to load JSON:\n${err.message}`;
copyBtn.disabled = true;
copyBtn.textContent = 'Copy';
}
}
});
</script>
2025-07-19 23:38:06 +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
77456cc46a
Add files via upload
2025-07-19 17:13:01 +02:00
Alcea
fc27e71492
Add files via upload
...
Added Fediverse Reply Button & Modal
2025-07-19 16:18:20 +02:00
Alcea
cedbc339ee
Add files via upload
...
Add instance perma link via
postElement.appendChild(quoteBlock);
}
//link2acws
// Function to decode surrogate pairs and Unicode escapes from JSON string literal
function decodeUnicodeEscapes(str) {
return str.replace(/\\u([\dA-Fa-f]{4})/g, (_, hex) =>
String.fromCharCode(parseInt(hex, 16))
);
}
if (value.includes("•acws")) {
// Step 1: decode the literal Unicode escapes (\ud809\udc2b) to real characters
const decodedValue = decodeUnicodeEscapes(value);
const formattedValue = decodedValue.replace(/𒐫(.*?)𒐫/g, '<blockquote>$1</blockquote>');
const dateClean = date.replace(/-/g, '');
const hash = CryptoJS.MD5(formattedValue).toString().substring(0, 8);
const permalink = `https://alceawis.com/alceawis/status/${dateClean}-${hash} `;
// Step 4: create and append link
const link = document.createElement('a');
link.href = permalink;
link.target = "_blank";
link.textContent = 'Permalink';
link.classList.add('btn2');
postElement.appendChild(link);
}
postElement.appendChild(hashtagsElement);
2025-07-19 15:49:47 +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
1d172455eb
Add files via upload
2025-07-17 12:24:29 +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
8d0f4d11bb
Add files via upload
2025-07-16 01:41:59 +02:00
Alcea
51cb44529a
Add files via upload
...
updateprofile.phpxwill now change discoverable:true
$profileObject = [
'@context' => 'https://www.w3.org/ns/activitystreams ',
'id' => "$baseUrl/$username",
'type' => 'Person',
'name' => 'Alcea Bot',
'discoverable' => true, // Update the discoverable field
'locked' => false,
'bot' => false,
// Add any other fields you need to update
'preferredUsername' => $username,
'summary' => formatDescriptionLinks($description),
'icon' => [
'type' => 'Image',
'mediaType' => 'image/gif',
'url' => $imageUrl,
],
2025-07-16 00:27:25 +02:00
Alcea
452fef3290
Add files via upload
2025-07-15 12:52:57 +02:00
Alcea
2315132d68
Add files via upload
...
Add time key to json for future ref
2025-07-15 12:02:00 +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
9c35de99c4
Add files via upload
...
Timekey for updatejson
2025-07-15 02:11:14 +02:00
Alcea
6e20ee73b3
Add files via upload
2025-07-15 01:33:27 +02:00
Alcea
90d02f346f
Add files via upload
...
Instance endpoint
2025-07-14 10:11:30 +02:00
Alcea
65a22d963b
Add files via upload
2025-07-14 09:53:08 +02:00
Alcea
da241c40a7
Add files via upload
...
Compatibility for nodeinfo
2025-07-14 09:35:27 +02:00
Alcea
5ed9b492e8
Add files via upload
2025-07-14 09:34:57 +02:00
Alcea
53dc0d5107
Add files via upload
...
Allow direct mentions
2025-07-13 18:31:20 +02:00
Alcea
0e323e81fa
Add files via upload
...
Tool to update remote user info
2025-07-13 16:27:55 +02:00
Alcea
96e40fd9d9
Add files via upload
2025-07-13 13:46:05 +02:00
Alcea
277a32248e
Add files via upload
2025-07-13 12:54:01 +02:00
Alcea
44e86fb401
Add files via upload
...
Nested Replies
2025-07-13 12:31:14 +02:00
Alcea
92a759e5d2
Add files via upload
...
Personalized Timeline
2025-07-13 10:49:33 +02:00
Alcea
3ba1c057a5
Add files via upload
2025-07-13 09:57:16 +02:00
Alcea
224652dab8
Add files via upload
2025-07-13 08:16:52 +02:00
Alcea
3fe8752b3d
Add files via upload
...
Better check when
return preg_replace('/𒐫(.*?)𒐫/u', '<blockquote>$1</blockquote>', $text);
to prevent posting just emoji to json
Added before after for user to confirm
2025-07-13 08:04:06 +02:00
Alcea
2ef091e148
Add files via upload
...
Only redirect status posts to renderer if direcrly from alceawis root domain
2025-07-13 07:49:40 +02:00
Alcea
fe11e33f6d
Add files via upload
2025-07-13 07:42:06 +02:00
Alcea
636ac2c446
Add files via upload
2025-07-12 22:58:20 +02:00
Alcea
822460d2cf
Add files via upload
2025-07-12 21:23:41 +02:00
Alcea
7386500670
Add files via upload
2025-07-12 20:52:43 +02:00
Alcea
d3376d5c6a
Add files via upload
2025-07-12 17:00:57 +02:00
Alcea
5e802b33a3
Add files via upload
2025-07-12 15:49:18 +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
7a11bcb29c
Add files via upload
2025-07-12 14:04:34 +02:00
Alcea
bfceb1d47c
Add files via upload
...
Added htmlspecialchars fix in quotes
2025-07-12 10:49:31 +02:00
Alcea
d5289fc575
Add files via upload
...
Fixing users redirect to actual user with htaccess
Hope this won't break things...
2025-07-12 09:58:11 +02:00
Alcea
6f6a3db4d2
Add files via upload
2025-07-12 09:47:09 +02:00