mirror of
https://github.com/sorenpeter/timeline.git
synced 2026-03-11 12:42:17 +00:00
Gallery is now working, with some hickups still
This commit is contained in:
parent
6c69dd89af
commit
c65003e3db
9 changed files with 148 additions and 478 deletions
|
|
@ -34,7 +34,7 @@ $routes = [
|
|||
'/login' => 'login.php',
|
||||
'/logout' => 'logout.php',
|
||||
'/profile' => 'profile.php',
|
||||
'/profile' => 'profile.php',
|
||||
'/gallery' => 'gallery.php',
|
||||
//'/profile/([a-zA-Z0-9_-]+)' => 'profile.php',
|
||||
'/conv/([a-zA-Z0-9]{7})' => 'conv.php', // matches only twtHash of exactly 7 alphanumeric characters
|
||||
'/post/([a-zA-Z0-9]{7})' => 'post.php', // matches only twtHash of exactly 7 alphanumeric characters
|
||||
|
|
|
|||
459
libs/twtxt.php
459
libs/twtxt.php
|
|
@ -1,875 +1,452 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
|
||||
$config = parse_ini_file('private/config.ini');
|
||||
|
||||
|
||||
|
||||
if ($config['debug_mode']) {
|
||||
|
||||
ini_set('display_errors', '1');
|
||||
|
||||
ini_set('display_startup_errors', '1');
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class TwtxtFile {
|
||||
|
||||
public $mainURL = ''; // First found URL
|
||||
|
||||
public $URLs = [];
|
||||
|
||||
public $nick = '';
|
||||
|
||||
public $avatar = '';
|
||||
|
||||
public $emoji = '';
|
||||
|
||||
public $description = '';
|
||||
|
||||
public $lang = 'en'; // Default language
|
||||
|
||||
public $links = [];
|
||||
|
||||
public $following = [];
|
||||
|
||||
public $twts = [];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Twt {
|
||||
|
||||
public $originalTwtStr;
|
||||
|
||||
public $hash;
|
||||
|
||||
public $fullDate;
|
||||
|
||||
public $displayDate;
|
||||
|
||||
public $content;
|
||||
|
||||
public $replyToHash;
|
||||
|
||||
public $mentions;
|
||||
|
||||
public $avatar;
|
||||
|
||||
public $emoji;
|
||||
|
||||
public $nick;
|
||||
|
||||
public $mainURL;
|
||||
|
||||
public $images;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# https://stackoverflow.com/a/39360281/13173382
|
||||
|
||||
# Confirm that this temorary fix is not skipping something
|
||||
|
||||
/*
|
||||
|
||||
stream_context_set_default([
|
||||
|
||||
'ssl' => [
|
||||
|
||||
'peer_name' => 'generic-server',
|
||||
|
||||
'verify_peer' => FALSE,
|
||||
|
||||
'verify_peer_name' => FALSE,
|
||||
|
||||
'allow_self_signed' => TRUE
|
||||
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSLVERSION, 4);
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* The function searches for a key-value pair in a string and returns the value if found.
|
||||
|
||||
*
|
||||
|
||||
* @param keyToFind The key we want to find in the string.
|
||||
|
||||
* @param string The string in which to search for the key-value pair.
|
||||
|
||||
*
|
||||
|
||||
* @return the value of the key that matches the given keyToFind in the given string. If a match is
|
||||
|
||||
* found, the function returns the value of the key as a string after trimming any whitespace. If no
|
||||
|
||||
* match is found, the function returns null.
|
||||
|
||||
*/
|
||||
|
||||
function getSingleParameter($keyToFind, $string) {
|
||||
|
||||
if (!str_contains($string, $keyToFind)) {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$pattern = '/\s*' . $keyToFind . '\s*=\s*([^#\n]+)/';
|
||||
|
||||
//$pattern = '/\s*' . $keyToFind . '\s*=\s*([^\s#]+)/'; // Only matches the first word
|
||||
|
||||
preg_match($pattern, $string, $matches);
|
||||
|
||||
|
||||
|
||||
if (isset($matches[1])) {
|
||||
|
||||
return trim($matches[1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getDoubleParameter($keywordToFind, $string) {
|
||||
|
||||
// Returns string or null
|
||||
|
||||
$pattern = '/#\s*' . preg_quote($keywordToFind, '/') . '\s*=\s*(\S+)\s*(\S+)/';
|
||||
|
||||
// Matches "# <keyword> = <value> <value>"
|
||||
|
||||
preg_match($pattern, $string, $matches);
|
||||
|
||||
|
||||
|
||||
if (isset($matches[1]) && isset($matches[2])) {
|
||||
|
||||
$result = array($matches[1], $matches[2]);
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getReplyHashFromTwt(string $twtString): string {
|
||||
|
||||
// Extract the text between parentheses using regular expressions
|
||||
|
||||
$pattern = '/\(#([^\)]+)\)/'; // Matches "(#<text>)"
|
||||
|
||||
preg_match($pattern, $twtString, $matches);
|
||||
|
||||
|
||||
|
||||
if (isset($matches[1])) {
|
||||
|
||||
$textBetweenParentheses = $matches[1];
|
||||
|
||||
return $textBetweenParentheses;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getMentionsFromTwt(string $twtString) {
|
||||
|
||||
$pattern = '/@<([^>]+)\s([^>]+)>/'; // Matches "@<nick url>"
|
||||
|
||||
function getImagesFromTwt(string $twtString) {
|
||||
$pattern = '/(<img[^>]+>)/i';
|
||||
preg_match_all($pattern, $twtString, $matches, PREG_SET_ORDER);
|
||||
|
||||
|
||||
|
||||
$result = array();
|
||||
|
||||
|
||||
|
||||
foreach ($matches as $match) {
|
||||
|
||||
$nick = $match[1];
|
||||
|
||||
$url = $match[2];
|
||||
|
||||
$result[] = array("nick" => $nick, "url" => $url);
|
||||
|
||||
$result[] = array($match[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
function getMentionsFromTwt(string $twtString) {
|
||||
$pattern = '/@<([^>]+)\s([^>]+)>/'; // Matches "@<nick url>"
|
||||
preg_match_all($pattern, $twtString, $matches, PREG_SET_ORDER);
|
||||
|
||||
$result = array();
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$nick = $match[1];
|
||||
$url = $match[2];
|
||||
$result[] = array("nick" => $nick, "url" => $url);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function replaceMentionsFromTwt(string $twtString): string {
|
||||
|
||||
// Example input: 'Hello @<eapl.mx https://eapl.mx/twtxt.txt>, how are you? @<nick https://server.com/something/twtxt.txt>';
|
||||
|
||||
// Example output: Hello <a href="?url=https://eapl.mx/twtxt.txt">@eapl.mx@eapl.mx/twtxt.txt</a>, how are you? <a href="?url=https://server.com/something/twtxt.txt">@nick@server.com/something/twtxt.txt</a>
|
||||
|
||||
|
||||
|
||||
$pattern = '/@<([^ ]+)\s([^>]+)>/';
|
||||
|
||||
//$replacement = '<a href="/?url=$2">@$1</a>';
|
||||
|
||||
$replacement = '<a href="'.str_replace("/index.php", "", $_SERVER["SCRIPT_NAME"]).'/?profile=$2">@$1</a>';
|
||||
$replacement .= '<a href="$2" class="webmention"></a>'; // Adds a hidden link direcly to the twtxt.txt of the mentioned target
|
||||
|
||||
#$twtString = '@<nick https://eapl.mx/twtxt.txt>';
|
||||
|
||||
#$pattern = '/@<([^ ]+) ([^>]+)>/';
|
||||
|
||||
#$replacement = '@$1';
|
||||
|
||||
$result = preg_replace($pattern, $replacement, $twtString);
|
||||
|
||||
return $result;
|
||||
|
||||
|
||||
|
||||
// from https://github.com/hxii/picoblog/blob/master/picoblog.php
|
||||
|
||||
//$pattern = '/\@<([a-zA-Z0-9\.]+)\W+(https?:\/\/[^>]+)>/';
|
||||
|
||||
//return preg_replace($pattern,'<a href="$2">@$1</a>',$twtString);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function replaceLinksFromTwt(string $twtString) {
|
||||
|
||||
|
||||
|
||||
// TODO: Make this NOT match with `inline code` to avoid links in code-snippets
|
||||
|
||||
// 1. Look into how yarnd handles this
|
||||
|
||||
|
||||
|
||||
// Regular expression pattern to match URLs
|
||||
|
||||
$pattern = '/(?<!\S)(\b(https?|ftp|gemini|spartan|gopher):\/\/\S+|\b(?!:\/\/)\w+(?:\.\w+)+(?:\/\S+)?)(?!\S)/';
|
||||
|
||||
|
||||
|
||||
// Replace URLs with clickable links
|
||||
|
||||
$replacement = '<a href="$1">$1</a>';
|
||||
|
||||
$result = preg_replace($pattern, $replacement, $twtString);
|
||||
|
||||
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function replaceMarkdownLinksFromTwt(string $twtString) {
|
||||
|
||||
$pattern = '/\[([^\]]+)\]\(([^)]+)\)/';
|
||||
|
||||
|
||||
|
||||
$replacement = '<a href="$2">$1</a>';
|
||||
|
||||
$result = preg_replace($pattern, $replacement, $twtString);
|
||||
|
||||
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function replaceImagesFromTwt(string $twtString) {
|
||||
|
||||
$pattern = '/!\[(.*?)\]\((.*?)\)/';
|
||||
|
||||
//$replacement = '<img src="$2" alt="$1">';
|
||||
|
||||
$replacement = '<a href="$2"><img src="$2" alt="$1"></a>';
|
||||
|
||||
$result = preg_replace($pattern, $replacement, $twtString);
|
||||
|
||||
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function replaceTagsFromTwt(string $twtString) {
|
||||
|
||||
$pattern = '/#(\w+)?/';
|
||||
|
||||
$replacement = '<a href="#">#\1</a>'; // Dummy link
|
||||
|
||||
//$replacement = '<a href="?tag=$1" class="tag">#${1}</a>';
|
||||
|
||||
$result = preg_replace($pattern, $replacement, $twtString);
|
||||
|
||||
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function getTimeElapsedString($timestamp, $full = false) {
|
||||
|
||||
$now = new DateTime;
|
||||
|
||||
$ago = new DateTime;
|
||||
|
||||
$ago->setTimestamp($timestamp);
|
||||
|
||||
|
||||
|
||||
$agoText = 'ago';
|
||||
|
||||
if ($now < $ago) {
|
||||
|
||||
$agoText = 'in the future';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$diff = $now->diff($ago);
|
||||
|
||||
|
||||
|
||||
//$diff->w = floor($diff->d / 7);
|
||||
|
||||
$w = floor($diff->d / 7);
|
||||
|
||||
$d = $diff->d - ($w * 7);
|
||||
|
||||
//$diff->d -= $diff->w * 7;
|
||||
|
||||
|
||||
|
||||
$string = array(
|
||||
|
||||
'y' => 'year',
|
||||
|
||||
'm' => 'month',
|
||||
|
||||
'w' => 'week',
|
||||
|
||||
'd' => 'day',
|
||||
|
||||
'h' => 'hour',
|
||||
|
||||
'i' => 'minute',
|
||||
|
||||
's' => 'second',
|
||||
|
||||
);
|
||||
|
||||
foreach ($string as $k => &$v) { // k is key, and v is value... Obviously
|
||||
|
||||
if ($k === 'w') {
|
||||
|
||||
if ($w) {
|
||||
|
||||
$v = $w . ' ' . $v . ($w > 1 ? 's' : '');
|
||||
|
||||
} else {
|
||||
|
||||
unset($string[$k]);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ($diff->$k) {
|
||||
|
||||
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
|
||||
|
||||
} else {
|
||||
|
||||
unset($string[$k]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!$full) $string = array_slice($string, 0, 1);
|
||||
|
||||
return $string ? implode(', ', $string) . " $agoText" : 'just now';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCachedFileContentsOrUpdate($fileURL, $cacheDurationSecs = 15) {
|
||||
|
||||
# TODO: Process the Warning
|
||||
|
||||
# Warning: file_get_contents(https://eapl.mx/twtxt.net):
|
||||
|
||||
# failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in
|
||||
|
||||
|
||||
|
||||
$cacheFilePath = getCachedFileName($fileURL);
|
||||
|
||||
|
||||
|
||||
// Check if cache file exists and it's not expired
|
||||
|
||||
if (file_exists($cacheFilePath) && (time() - filemtime($cacheFilePath)) < $cacheDurationSecs) {
|
||||
|
||||
return file_get_contents($cacheFilePath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// File doesn't exist in cache or has expired, so fetch and cache it
|
||||
|
||||
$contents = file_get_contents($fileURL);
|
||||
|
||||
file_put_contents($cacheFilePath, $contents);
|
||||
|
||||
|
||||
|
||||
return $contents;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCachedFileContents($filePath) {
|
||||
|
||||
$cacheFile = getCachedFileName($filePath);
|
||||
|
||||
|
||||
|
||||
// Check if cache file exists and it's not expired
|
||||
|
||||
if (file_exists($cacheFile)) {
|
||||
|
||||
return file_get_contents($cacheFile);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function updateCachedFile($filePath, $cacheDurationSecs = 15) {
|
||||
|
||||
$cacheFilePath = getCachedFileName($filePath);
|
||||
|
||||
|
||||
|
||||
// File doesn't exist in cache or has expired, so fetch and cache it
|
||||
|
||||
// TODO: Seems it's not working right!
|
||||
|
||||
$fileDoesntExist = !file_exists($cacheFilePath);
|
||||
|
||||
$fileIsOld = false;
|
||||
|
||||
if (!$fileDoesntExist) {
|
||||
|
||||
$fileIsOld = !((time() - filemtime($cacheFilePath)) < $cacheDurationSecs);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($fileDoesntExist || $fileIsOld) {
|
||||
|
||||
#echo "Loading Cached file $cacheFilePath<br>\n";
|
||||
|
||||
$contents = @file_get_contents($filePath);
|
||||
|
||||
|
||||
|
||||
if ($contents === false) {
|
||||
|
||||
// File loaded with errors, skip saving it
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
file_put_contents($cacheFilePath, $contents);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getTwtsFromTwtxtString($url) {
|
||||
|
||||
$fileContent = getCachedFileContents($url);
|
||||
|
||||
|
||||
|
||||
if (is_null($fileContent)) {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
$fileContent = mb_convert_encoding($fileContent, 'UTF-8');
|
||||
|
||||
|
||||
|
||||
$fileLines = explode("\n", $fileContent);
|
||||
|
||||
|
||||
|
||||
$twtxtData = new TwtxtFile();
|
||||
|
||||
|
||||
|
||||
foreach ($fileLines as $currentLine) {
|
||||
|
||||
// Remove empty lines
|
||||
|
||||
if (empty($currentLine)) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (str_starts_with($currentLine, '#')) {
|
||||
|
||||
// Check if comments (starting with #) have some metadata
|
||||
|
||||
if (!is_null(getSingleParameter('url', $currentLine))) {
|
||||
|
||||
$currentURL = getSingleParameter('url', $currentLine);
|
||||
|
||||
|
||||
|
||||
if (empty($twtxtData->URLs)) {
|
||||
|
||||
$twtxtData->mainURL = $currentURL;
|
||||
|
||||
}
|
||||
|
||||
$twtxtData->URLs[] = $currentURL;
|
||||
|
||||
}
|
||||
|
||||
if (!is_null(getSingleParameter('nick', $currentLine))) {
|
||||
|
||||
$twtxtData->nick = getSingleParameter('nick', $currentLine);
|
||||
|
||||
}
|
||||
|
||||
if (!is_null(getSingleParameter('avatar', $currentLine))) {
|
||||
|
||||
$twtxtData->avatar = getSingleParameter('avatar', $currentLine);
|
||||
|
||||
}
|
||||
|
||||
if (!is_null(getSingleParameter('emoji', $currentLine))) {
|
||||
|
||||
$twtxtData->emoji = getSingleParameter('emoji', $currentLine);
|
||||
|
||||
}
|
||||
|
||||
if (!is_null(getSingleParameter('lang', $currentLine))) {
|
||||
|
||||
$twtxtData->lang = getSingleParameter('lang', $currentLine);
|
||||
|
||||
}
|
||||
|
||||
if (!is_null(getSingleParameter('description', $currentLine))) {
|
||||
|
||||
$twtxtData->description = getSingleParameter('description', $currentLine);
|
||||
|
||||
// TODO - FIX BUG: only takes first word!
|
||||
|
||||
}
|
||||
|
||||
if (!is_null(getSingleParameter('follow', $currentLine))) {
|
||||
|
||||
$twtxtData->following[] = getSingleParameter('follow', $currentLine);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!str_starts_with($currentLine, '#')) {
|
||||
|
||||
$explodedLine = explode("\t", $currentLine);
|
||||
|
||||
if (count($explodedLine) >= 2) {
|
||||
|
||||
$dateStr = $explodedLine[0];
|
||||
|
||||
$twtContent = $explodedLine[1];
|
||||
|
||||
|
||||
|
||||
$twtContent = replaceMentionsFromTwt($twtContent);
|
||||
|
||||
|
||||
|
||||
// Convert HTML problematic characters
|
||||
|
||||
//$twtContent = htmlentities($twtContent); // TODO: Messing up rendering of @mentions #BUG
|
||||
|
||||
|
||||
|
||||
// Replace the Line separator character (U+2028)
|
||||
|
||||
// \u2028 is \xE2 \x80 \xA8 in UTF-8
|
||||
|
||||
// Check here: https://www.mclean.net.nz/ucf/
|
||||
|
||||
//$twtContent = str_replace("\xE2\x80\xA8", "<br>\n", $twtContent);
|
||||
|
||||
|
||||
|
||||
// For some reason I was having trouble finding this nomenclature
|
||||
|
||||
// that's why I leave the UTF-8 representation for future reference
|
||||
|
||||
$twtContent = str_replace("\u{2028}", "\n<br>\n", $twtContent);
|
||||
|
||||
|
||||
|
||||
//$twtContent = replaceMarkdownLinksFromTwt($twtContent);
|
||||
|
||||
//$twtContent = replaceImagesFromTwt($twtContent);
|
||||
|
||||
$twtContent = Slimdown::render($twtContent);
|
||||
|
||||
$twtContent = replaceLinksFromTwt($twtContent); // TODO:
|
||||
|
||||
|
||||
|
||||
// Get and remote the hash
|
||||
|
||||
// Get and remove the hash
|
||||
$hash = getReplyHashFromTwt($twtContent);
|
||||
|
||||
if ($hash) {
|
||||
|
||||
$twtContent = str_replace("(#$hash)", '', $twtContent);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: Make ?tag= filtering feature
|
||||
|
||||
//$twtContent = replaceTagsFromTwt($twtContent);
|
||||
|
||||
|
||||
|
||||
// TODO: Get mentions
|
||||
|
||||
$mentions = getMentionsFromTwt($twtContent);
|
||||
|
||||
|
||||
|
||||
// Get Lang metadata
|
||||
|
||||
|
||||
|
||||
if (($timestamp = strtotime($dateStr)) === false) {
|
||||
|
||||
//echo "The string ($dateStr) is incorrect";
|
||||
|
||||
// Incorrect date string, skip this twt
|
||||
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
$displayDate = getTimeElapsedString($timestamp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: Only 1 twt by second is allowed here
|
||||
|
||||
$twt = new Twt();
|
||||
|
||||
|
||||
|
||||
$twt->originalTwtStr = $currentLine;
|
||||
|
||||
$twt->hash = getHashFromTwt($currentLine, $twtxtData->mainURL);
|
||||
|
||||
$twt->fullDate = date('j F Y h:i:s A', $timestamp) . ' (UTC)';
|
||||
|
||||
$twt->displayDate = $displayDate;
|
||||
|
||||
$twt->content = $twtContent;
|
||||
|
||||
$twt->replyToHash = $hash;
|
||||
|
||||
$twt->mentions = $mentions;
|
||||
|
||||
$twt->avatar = $twtxtData->avatar;
|
||||
|
||||
$twt->emoji = $twtxtData->emoji;
|
||||
|
||||
$twt->nick = $twtxtData->nick;
|
||||
|
||||
$twt->mainURL = $twtxtData->mainURL;
|
||||
|
||||
|
||||
|
||||
$twtxtData->twts[$timestamp] = $twt;
|
||||
|
||||
// TODO: Interpret the content as markdown -- @DONE using Slimdown.php above
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $twtxtData;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function insertFollowingURL($urlString) {
|
||||
|
||||
// Check if it's a valid URL
|
||||
|
||||
// Retrieve the nickname, if didn't find a nick, ask for one
|
||||
|
||||
|
||||
|
||||
$originalCode = '
|
||||
|
||||
Lorem ipsum dolor sit amet,
|
||||
|
||||
#~~~#
|
||||
|
||||
consectetur adipiscing elit.';
|
||||
|
||||
|
||||
|
||||
$text = '#~~~#';
|
||||
|
||||
$newText = '123' . PHP_EOL . $text;
|
||||
|
||||
$result = str_replace('#~~~#', $newText, $originalCode);
|
||||
|
||||
|
||||
|
||||
echo $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCachedFileName($filePath) {
|
||||
|
||||
return __DIR__ . '/../private/cache/' . hash('sha256', $filePath); // TODO: make better path
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!function_exists('str_starts_with')) {
|
||||
|
||||
function str_starts_with($haystack, $needle) {
|
||||
|
||||
return (string)$needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('str_ends_with')) {
|
||||
|
||||
function str_ends_with($haystack, $needle) {
|
||||
|
||||
return $needle !== '' && substr($haystack, -strlen($needle)) === (string)$needle;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('str_contains')) {
|
||||
|
||||
function str_contains($haystack, $needle) {
|
||||
|
||||
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
51
partials/__img_posts.php
Normal file
51
partials/__img_posts.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Gallery render of images posted to a twtxt.txt -- by darch.dk (2022)
|
||||
https://www.reddit.com/r/css/comments/8vmo4u/problem_fitting_image_to_css_grid/
|
||||
*/
|
||||
|
||||
echo '<div class="gallery">';
|
||||
|
||||
foreach ($twts as $twt) {
|
||||
$img_array = getImagesFromTwt($twt->content);
|
||||
|
||||
foreach ($img_array as $img) {
|
||||
//echo '<a href="'.$baseURL.'/post/'.$twt->hash.'">'.$img[0].'</a>';
|
||||
// Workaround until cache issue is resolved
|
||||
echo '<a href="'.$baseURL.'/?profile='.$twt->mainURL.'#'.$twt->hash.'">'.$img[0].'</a>';
|
||||
}
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// old way from Pixelblog, for refernece/inspiration
|
||||
|
||||
// Loop through each post and extract date and entry text:
|
||||
|
||||
foreach ($img_posts as $post) {
|
||||
|
||||
$date = preg_filter('/^(?<date>[^\t]+)\t(?<entry>.+)/', '\1', $post);
|
||||
$entry = preg_filter('/^(?<date>[^\t]+)\t(?<entry>.+)/', '\2', $post);
|
||||
$text_only = preg_filter('/!\[(.*?)\]\((.*?)\)/', '\1', $entry); // this gives the post without the markdown img links (not sure why, but it works)
|
||||
$text_only = trim($text_only);
|
||||
$text_only = strip_tags($text_only);
|
||||
|
||||
preg_match_all('/!\[(?<alt>.*?)\]\((?<url>.*?)\)/', $entry, $img_array);
|
||||
//echo '<pre>'; print_r($img_array); echo '</pre>'; // FOR DEBUGING
|
||||
|
||||
foreach ($img_array['url'] as $img => $val) {
|
||||
$url = $img_array['url'][$img];
|
||||
//$alt = $img_array['alt'][$img];
|
||||
echo '<a href="'.$baseURL.'/?id='.$date.'"><img src="'.$url.'" alt="'.$text_only.'" title="'.$text_only.'" loading=lazy></a>';
|
||||
//echo '<a href="' . $base_url . '?id=' . $date . '"><img src="' . $base_url . 'system/thumb.php?src=' . $url . '&size=600x&crop=1" alt="' . $text_only . '" title="' . $text_only . '" loading=lazy></a>';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
?>
|
||||
|
|
@ -19,7 +19,7 @@ $profile = getTwtsFromTwtxtString($config['public_txt_url']);
|
|||
<p>
|
||||
<a href="<?= $baseURL ?>">
|
||||
<img class="avatar" src="<?= $profile->avatar ?>" alt="" loading="lazy">
|
||||
<!-- Timeline for --><?= $profile->nick ?></a>@<?= parse_url($profile->mainURL, PHP_URL_HOST); ?>
|
||||
<?= $profile->nick ?></a>@<?= parse_url($profile->mainURL, PHP_URL_HOST); ?>
|
||||
</p>
|
||||
<nav>
|
||||
|
||||
|
|
@ -31,11 +31,13 @@ $profile = getTwtsFromTwtxtString($config['public_txt_url']);
|
|||
<li><a href="<?= $baseURL ?>/refresh?url=<?= $url ?>">Refresh</a></li>
|
||||
<li><a href="<?= $baseURL ?>/following">Following <?php // echo count($twtFollowingList); ?></a></li>
|
||||
<li><a href="<?= $baseURL ?>/add">Add feed</a></li>
|
||||
<li><a href="<?= $baseURL ?>/?profile=<?=$url ?>">Profile</a></li>
|
||||
<li><a href="<?= $baseURL ?>?profile=<?=$url ?>">Profile</a></li>
|
||||
<li><a href="<?= $baseURL ?>/gallery?profile=<?= $profile->mainURL ?>">Gallery</a></li>
|
||||
<li><a href="<?= $baseURL ?>/logout">Log Out</a></li>
|
||||
<?php /*}*/ } else { ?>
|
||||
<li><a href="<?= $baseURL ?>?profile=<?= $url ?>">Profile</a></li>
|
||||
<li><a href="<?= $baseURL ?>/gallery?profile=<?= $profile->mainURL ?>">Gallery</a></li>
|
||||
<li><a href="<?= $baseURL ?>/following">Following <?php // echo count($twtFollowingList); ?></a></li>
|
||||
<li><a href="<?= $baseURL ?>/?profile=<?= $url ?>">Profile</a></li>
|
||||
<li><a href="<?= $baseURL ?>/login">Log in</a></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -6,31 +6,33 @@ if (!empty($_GET['profile'])) {
|
|||
}
|
||||
$profile = getTwtsFromTwtxtString($url);
|
||||
|
||||
$profileURL = $baseURL.'/?profile='.$profile->mainURL;
|
||||
|
||||
?>
|
||||
|
||||
<div class="profile">
|
||||
|
||||
<a href="<?= $profile->mainURL ?>">
|
||||
<a href="<?= $profileURL ?>">
|
||||
<img class="avatar" src="<?= $profile->avatar ?>" alt="" loading="lazy">
|
||||
</a>
|
||||
|
||||
<div>
|
||||
<a href="<?= $profile->mainURL ?>" class="author">
|
||||
<a href="<?= $profileURL ?>" class="author">
|
||||
<strong><?= $profile->nick ?></strong>@<?= parse_url($profile->mainURL, PHP_URL_HOST); ?>
|
||||
</a>
|
||||
|
||||
<p><?= $profile->description ?></p>
|
||||
|
||||
<small>
|
||||
<!-- <a href="">Posts</a> | -->
|
||||
<a href="<?= $profileURL ?>">Posts</a> |
|
||||
<!-- <a href="">Replies</a> | -->
|
||||
<!-- <a href="">Gallery</a> | -->
|
||||
<a href="<?= $baseURL ?>/gallery?profile=<?= $profile->mainURL ?>">Gallery</a>
|
||||
|
||||
<!-- <span class="right"> -->
|
||||
<span class="right">
|
||||
<!-- <a href="following.php">Following <?php echo count($twtFollowingList); ?></a> | -->
|
||||
<a target="_blank" href="<?= $profile->mainURL ?>"></i><?= $profile->mainURL ?></a>
|
||||
(<a href="https://yarn.social">How to follow</a>)
|
||||
<!-- </span> -->
|
||||
</span>
|
||||
|
||||
</small>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
</center> -->
|
||||
|
||||
<?php foreach ($twts as $twt) { ?>
|
||||
<article class="post-entry">
|
||||
<article class="post-entry" id="<?= $twt->hash ?>">
|
||||
<a href="<?= $baseURL ?>/?profile=<?= $twt->mainURL ?>">
|
||||
<img src='<?= $twt->avatar ?>' class="avatar" onerror="this.onerror=null;this.src='imgs/image_not_found.png';">
|
||||
</a>
|
||||
|
|
|
|||
29
style.css
29
style.css
|
|
@ -183,10 +183,6 @@ article .twt-msg {
|
|||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
article .twt-msg a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
article .twt-msg > blockquote {
|
||||
margin: 0;
|
||||
border-left: thick solid grey;
|
||||
|
|
@ -217,9 +213,6 @@ article small a:visited {
|
|||
|
||||
}
|
||||
|
||||
article small a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* === New Post Form === */
|
||||
|
||||
|
|
@ -242,4 +235,26 @@ footer {
|
|||
border-top: thin solid grey;
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* == Gallery ===================== */
|
||||
|
||||
.gallery {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto ;
|
||||
display: grid;
|
||||
grid-gap: 0.75rem;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
/*grid-auto-rows: 225px;*/
|
||||
/*grid-auto-flow: dense;*/
|
||||
}
|
||||
|
||||
.gallery a img {
|
||||
/* https://web.dev/aspect-ratio/ */
|
||||
aspect-ratio: 1 / 1;
|
||||
width: 100%;
|
||||
/*height: 100%;*/
|
||||
object-fit: cover;
|
||||
/*background-color: var(--border-color);*/
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
|
@ -1,28 +1,51 @@
|
|||
<!-- PHP: GET CONFIG --><?php include '../config.php' ?>
|
||||
<?php
|
||||
require_once("partials/base.php");
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/css" media="all" href="../layout/default.css?v=1.1">
|
||||
<link rel="stylesheet" type="text/css" media="all" href="../custom.css?v=1.1">
|
||||
<title><?=$title?> - Gallery</title>
|
||||
</head>
|
||||
<body>
|
||||
$title = "Gallery - ".$title;
|
||||
|
||||
<!-- PHP: GET HEADER --><?php include $base_path.'layout/header.php';?>
|
||||
|
||||
<!-- PHP: GET PROFILE CARD --><?php include $base_path.'layout/profile.php';?>
|
||||
include_once 'partials/header.php';
|
||||
?>
|
||||
|
||||
|
||||
<!-- PHP: PROFILE CARD -->
|
||||
<?php
|
||||
if (!empty($_GET['profile'])) { // Show twts for some user
|
||||
$twtsURL = $_GET['profile'];
|
||||
|
||||
// TODO: Give a propper error if feed is not valid
|
||||
if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
|
||||
die('Not a valid URL');
|
||||
}
|
||||
|
||||
// $parsedTwtxtFile = getTwtsFromTwtxtString($twtsURL);
|
||||
if (!is_null($parsedTwtxtFile)) {
|
||||
$parsedTwtxtFiles[$parsedTwtxtFile->mainURL] = $parsedTwtxtFile;
|
||||
include 'partials/profile.php';
|
||||
}
|
||||
} else {
|
||||
// code...
|
||||
//$filecontent = file('../twtxt.txt');
|
||||
$twtsURL = file($profile->mainURL);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<!-- PHP: GALLERY -->
|
||||
<div class="gallery">
|
||||
|
||||
<?php include $base_path.'system/gallery.php' ?>
|
||||
<?php
|
||||
foreach ($twts as $twt) {
|
||||
$img_array = getImagesFromTwt($twt->content);
|
||||
|
||||
foreach ($img_array as $img) {
|
||||
//echo '<a href="'.$baseURL.'/post/'.$twt->hash.'">'.$img[0].'</a>';
|
||||
// Workaround until cache issue is resolved
|
||||
echo '<a href="'.$baseURL.'/?profile='.$twt->mainURL.'#'.$twt->hash.'">'.$img[0].'</a>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- PHP: GET FOOTER --><?php include $base_path.'layout/footer.php';?>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<!-- PHP: FOOTER --><?php include_once 'partials/footer.php';?>
|
||||
Loading…
Reference in a new issue