123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- <?php
- /* this file will fetch and render the posts of a timeline based
- on the options of the user_settings cookie and the url query.
-
- a "timeline" may be something like TWKN or just a single post
- */
- $thread = timeline(array_merge($tl, $user_settings));
- /*
- if the timeline requested is the first part of an user profile it will render first
- the user profile header, i may move this to it's own place in the future but
- for now it's here.
- */
- if (isset($_GET['user']) && (!isset($_GET['next']) && !isset($_GET['since']))) {
- list($info, $rel) = user_info($_GET['user']);
- $template = themes("get","templates/profileheader.txt");
- $profile['mainColor'] = averageColor($info['avatar']);
- $profile['header'] = $info['header_static'];
-
- /* display user buttons (block, mute, list, etc) for loged in users only */
- $profile['top'] = ($logedin ? "<span id='" . $info['id'] . "' class='profileButton profileMenu' style='position:relative;'>
-
- <div class='menu' style='width:80px; position:absolute; background-color:yellow; top:25px; display:none;'>
- <div id='" . $info['id'] . "' class='profileButton " . ($rel[0]['muting'] ? "un" : "") . "mute' style='width:100%; border-radius:0px;'>" . ($rel[0]['muting'] ? " Unmute" : " Mute") . "</div>
- <div id='" . $info['id'] . "' class='profileButton " . ($rel[0]['blocking'] ? "un" : "") . "block' style='width:100%; border-radius:0px;'>" . ($rel[0]['blocking'] ? " Unblock" : " Block") . "</div>
- </div>
-
- </span>" : "");
-
- if ($logedin && $rel[0]['following']) {
- $profile['top'] .= "<span id='" . $info['id'] . "' class='profileButton listmenu' style='position:relative;'>Lists 
- <div class='menu' style='width:120px; position:absolute; background-color:yellow; top:25px; left:00px; display:none;'><ul>";
- $userlist = api_get("accounts/" . $info['id'] . "/lists");
- $listids = array();
- foreach ($userlist as $lst) {
- $listids[] = $lst['id'];
- }
- $lists = api_get("/lists");
- foreach ($lists as $list) {
- $profile['top'] .= "<a href='?action=addtolist&user=" . $info['id'] . "&list=" . $list['id'] . "' id='" . $info['id'] . "' list='" . $list['id'] . "' class='" . (in_array($list['id'], $listids) ? 'rutl' : 'autl') . "' onClick='return false;'><li>" . $list['title'] . "</li></a>";
- }
- $profile['top'] .= "<a href='?page=lists' class='ldr' onClick='return false;'><li>Manage Lists</li></a>";
- $profile['top'] .= "
- </ul></div>
- </span>";
- }
- if ($logedin) {
- if ($rel[0]['following']) {
- $label = " Following";
- $class = "unfollow";
- }
- else {
- if ($info['locked']) {
- if ($rel[0]['requested']) {
- $label = " Follow Requested";
- $class = "unfollow";
- }
- else {
- $label = " Request Follow";
- $class = "follow";
- }
- }
- else {
- $label = " Follow";
- $class = "follow";
- }
- }
- $profile['top'] .= "<span id='" . $info['id'] . "' class='profileButton $class'>$label</span>";
- }
-
- /* The NSFW button is available even to non logged in users, the value is stored in a cookie */
- $profile['top'] .= "<span id='" . $info['id'] . "' class='profileButton " . (in_array($info['id'], $user_settings['nsfw']) ? "unnsfw" : "nsfw") . "'>" . (in_array($info['id'], $user_settings['nsfw']) ? "NSFW <span class='fontello'></span>" : "NSFW <span class='fontello'></span>") . "</span>";
- /* display some indicators (blocked, muting, etc) for loged in users only */
- if ($logedin) {
- $profile['bottom'] = "
- " . ($info['locked'] ? "<span class='profileButton' style='background-color: rgba(255,255,255,.5);'> Locked</span>" : "") . "
- " . ($rel[0]['followed_by'] ? "<span class='profileButton' style='background-color: rgba(255,255,255,.5);'> Follows You</span>" : "") . "
- " . ($rel[0]['blocking'] ? "<span class='profileButton' style='background-color: rgba(255,255,255,.5);'> Blocked</span>" : "") . "
- " . ($rel[0]['muting'] ? "<span class='profileButton' style='background-color: rgba(255,255,255,.5);'> Muted</span>" : "") . "
- ";
- }
- else {
- $profile['bottom'] = "";
- }
- /* some values are processed from the profile and stored in the $profile array*/
- $profile['avatar'] = $info['avatar'];
- $profile['name'] = emojify($info['display_name'], $info['emojis'], 40);
- $profile['acct'] = $info['acct'];
- $profile['url'] = $info['url'];
- $profile['note'] = emojify(trim($info['note']) , $info['emojis']);
- $profile['statuses'] = $info['statuses_count'];
- $profile['following'] = $info['following_count'];
- $profile['followers'] = $info['followers_count'];
- /* now we replace the text of the index of $profile array with the contents of the index
- in the fetched template */
- foreach ($profile as $key => $value) {
- $template = str_replace(":$key:", $value, $template);
- }
- echo $template;
- }
- elseif (!isset($_GET['next']) && !isset($_GET['since'])) {
- echo "<div class='element'></div>";
- }
- /*
- if the timeline array is empty or the content is not a post, we just display an error message.
- */
- if ((!isset($thread[0]['id']) && !empty($thread)) || !is_array($thread)) {
- //echo "<div class='element'><div class='avatar'></div><span class='button error'> Error loading the timeline. " . json_encode($thread) . "</span></div>";
- } else {
- $e = 0;
- /* process all the posts on the timeline */
- foreach ($thread as $elem) {
- $post = array();
-
- /* pid is the ABSOLUTE id of a post, not linked to the relative id,
- a retweet has a different absolute id than the post that was retweeted */
- $post['pid'] = $elem['id'];
- $post['replyto'] = "";
- $post['rt'] = "";
- /* if the post is a retweet, we'll flag it as such and fetch the data of the post entity
- from the "reblog" key
- */
- if ($elem['reblog'] != null) {
-
- if ($user_settings['reblog'] == 'off'){
- continue;
- }
-
- $post['name'] = (empty($elem['reblog']['account']['display_name']) ? $elem['reblog']['account']['acct'] : emojify($elem['reblog']['account']['display_name'], $elem['reblog']['account']['emojis'], 20));
- $post['uid'] = $elem['reblog']['account']['id'];
- $post['acct'] = '';//$elem['reblog']['account']['acct'];
- $post['handle'] = explode("@",$elem['reblog']['account']['acct'])[0];
-
- $post['replyto'] = "<span>" . ($elem['reblog']['in_reply_to_id'] ? " <a class='fontello link preview ldr' target='_blank' id='" . $elem['reblog']['in_reply_to_id'] . "' href='?thread=" . $elem['reblog']['in_reply_to_id'] . "'></a>" : "") . "</span>";
- $post['rt'] = "<div style='display:inline-block; font-family:fontello, sans-serif; vertical-align:top;'> by <img src='" . $elem['account']['avatar'] . "' width=20 style='border-radius:5px; vertical-align:middle;'> <span class='user' id='" . $elem['account']['id'] . "'><a class='link ldr' style='font-size:12px;' id='" . $elem['account']['id'] . "' href='?user=" . $elem['account']['id'] . "'><span>@" . explode("@", $elem['account']['acct']) [0] . "</a></span></div>";
- $elem = $elem['reblog'];
- }
- else {
- $post['name'] = (empty($elem['account']['display_name']) ? $elem['account']['acct'] : emojify($elem['account']['display_name'], $elem['account']['emojis'], 20));
- $post['uid'] = $elem['account']['id'];
- $post['acct'] = "(@".$elem['account']['acct'].")";
- $post['handle'] = explode("@",$elem['account']['acct'])[0];
- $post['replyto'] = "<span>" . ($elem['in_reply_to_id'] ? " <a class='fontello link preview ldr' target='_blank' id='" . $elem['in_reply_to_id'] . "' href='?thread=" . $elem['in_reply_to_id'] . "'></a>" : "") . "</span>";
- }
- /* We skip the post if it contains any of the muted words */
- foreach($user_settings['mtwords'] as $word){
- if(contains($elem['content'],trim($word))){
- continue 2;
- }
- }
- /* if the poster ID was flagged as NSFW by the user, the post is flagged
- as sensitive by default */
- if (in_array($elem["account"]['id'], $user_settings['nsfw'])) {
- $elem['sensitive'] = true;
- }
- /* if the settings say to avoid showing posts with NSFW content, we skip to the next post */
- if ($user_settings['explicit'] == "hide" && $elem['sensitive'] == true && $tl['mode'] != "thread") {
- continue;
- }
-
- /* if this thread has been hidden by the user, we skip to the next one
- note that the "conversation_id" post key is only available with pleroma servers
- */
- if (@in_array($elem["pleroma"]['conversation_id'], $user_settings['hide'])) {
- continue;
- }
- /* the $json array stores some data about the thread that is embedded inside the
- html of the post and is mostly used by the javascript portion of the FE. It stores
- the id of the post, the visibility and who was mentioned in the post.
- */
- $json['id'] = $elem['id'];
- $json['scope'] = $elem['visibility'];
- if ($logedin) {
- $pos['mentions'] = "";
- $array = $elem["mentions"];
- $json['mentions'] = ($user_settings['acct'] == $elem["account"]['acct'] ? "" : "@" . $elem["account"]['acct']) . " ";
- if (!empty($array)) {
- foreach ($array as $mnt) {
- if ($mnt['acct'] != $user_settings['acct'] && $mnt['acct'] != $elem['account']['acct']) {
- $json['mentions'] .= "@" . $mnt['acct'] . " ";
- }
- }
- }
- }
- $post['json'] = json_encode($json);
- /* the options menu of the post */
- $post['menu'] = "<ul>";
- if ($logedin) {
- $post['menu'] .= ($elem['account']['id'] == $user_settings['uid'] ? "<li><a href='?action=delete&thread=" . $elem['id'] . "' onClick='return false;' class='delete fontello' id=':id:'> Delete Post</a></li>" : "");
- $post['menu'] .= "<li><a href='?action=compose"e=" . $elem['id'] . "' onClick='return false;' class='quote fontello' id='" . $elem['id'] . "' style='background-color:transparent;'> Quote Post</a></li>";
- $post['menu'] .= ($elem['account']['id'] != $user_settings['uid'] ? "<li><a href='?action=mute&user=" . $elem['account']['id'] . "' onClick='return false;' class='mute fontello' id='" . $elem['account']['id'] . "' style='background-color:transparent;'> Mute User</a></li>" : "");
- $post['menu'] .= ($elem['account']['id'] != $user_settings['uid'] ? "<li><a href='?action=mute&thread=" . $elem['account']['id'] . "' onClick='return false;' class='muteconv fontello' id='" . $elem['id'] . "' style='background-color:transparent;'> Drop Thread</a></li>" : "");
- $post['menu'] .= (isset($user_settings['pleroma']) ? "<li><a href='?action=hide&thread=" . $elem['pleroma']['conversation_id'] . "' onClick='return false;' class='hide fontello' id='" . $elem['pleroma']['conversation_id'] . "' style='background-color:transparent;'> Hide Thread</a></li>" : "");
- $post['menu'] .= "<li><a href='?action=bookmark&thread=" . $elem['account']['id'] . "' onClick='return false;' class='" . ($elem['bookmarked'] == true ? "un" : "") . "bookmark fontello' id='" . $elem['id'] . "' style='background-color:transparent;'> " . ($elem['bookmarked'] == true ? "Unb" : "B") . "ookmark</a></li>";
- $post['menu'] .= ($elem['account']['id'] != $user_settings['uid'] ? "<li><a href='?action=nsfw&user=" . $elem['account']['id'] . "' onClick='return false;' class='nsfw fontello' id='" . $elem['account']['id'] . "' style='background-color:transparent;'> User is NSFW</a></li>" : "");
- }
- $post['menu'] .= "<li><a target='_blank' href='" . $elem['url'] . "' class='original link fontello' style='background-color:transparent;'> Original Note</a></li>";
- $post['menu'] .= "</ul>";
- $post['style'] = "";
- $post['id'] = $elem['id'];
- $post['avatar'] = $elem['account']['avatar'];
- $post['text'] = processText($elem);
-
- if (!empty($elem['poll'])){
- $post['text'] .= "<div class='poll' id='".$elem['poll']['id']."' ".($elem['poll']['multiple'] ? "multiple" : "").">";
- $post['text'] .= renderPoll($elem);
- $post['text'] .= "</div>";
- }
-
- $post['spoiler'] = "";
- $post['hidden'] = "";
- if ($user_settings['unrollcw'] == 'off'){
- $post['spoiler'] = (empty($elem['spoiler_text']) ? "" : "<div class='spoiler' style='font-weight:bold;font-size:15px;'>" . emojify($elem['spoiler_text'], $elem['emojis'], 40) . "<a style='display:block;'>Click here to reveal</a></div>");
- $post['hidden'] = (empty($elem['spoiler_text']) ? "" : "hidden");
- } else {
- $post['spoiler'] = (empty($elem['spoiler_text']) ? "" : "<div style='font-weight:bold;font-size:15px;'>" . emojify($elem['spoiler_text'], $elem['emojis'], 40) . "</div>");
- }
- $post['media'] = "";
- $urls = get_urls(strip_tags($elem['content'], '<br><br \>'));
- /* embed videos in the post via invidio.us if there are youtube links */
- if (!empty($urls)) {
- foreach ($urls as $url) {
- parse_str(parse_url($url, PHP_URL_QUERY) , $my_array_of_vars);
- if (isset($my_array_of_vars['v'])) {
- $post['media'] = "<embed class='desktop' width='620' height='415' src='https://youtube.com/embed/" . $my_array_of_vars['v'] . "'>";
- }
- }
- }
- /* embed the media attachments to the post... */
- if (!empty($elem['media_attachments'])) {
- /* ...only if there are attachments and the user hasn't turned off the attachments in the settings */
- if ($user_settings['attach'] != "off"){
- $images = count($elem['media_attachments']);
- $class = ($images === 1 ? "" : ($images > 4 ? "class='smaller'" : "class='small'"));
- $m = 1;
- foreach ($elem['media_attachments'] as $file) {
- $ext = explode(".", $file['url']);
- $ext = end($ext);
- $ext = explode("?", $ext) [0];
- if (in_array($ext,array('webm','mp4','ogv')) || $file['type'] == "video") {
- $post['media'] .= "<div style='overflow:hidden; float:left; margin:2px;' $class><video preload='metadata' style='text-align:center; max-width:100%; max-height:100%;' controls ".($user_settings['videoloop'] == "on" ? "loop" : "").">
- <source src='" . $file['url'] . "' type='video/".($ext == "ogv" ? "ogg" : $ext)."'>
- </video></div>
- ";
- }
- elseif (in_array($ext,array('mp3','ogg','oga','opus')) || $file['type'] == "audio") {
- $post['media'] .= "<div style='text-align:center; width:100%;'><audio controls>
- <source src='" . $file['url'] . "' type='audio/$ext'>
- Your browser does not support the audio tag.
- </audio> </div>";
- }
- elseif (in_array($ext,array('jpg','jpeg','png','gif','apng','svg','webp')) || $file['type'] == "image") {
- /* we'll either hide the attachment or assign a css class depending on the user's settings */
-
- /* if the post is marked as sensitive and nsfw hiding isn't turned off, we'll blur the image */
- if ($elem['sensitive'] == true && $user_settings['explicit'] != 'off') {
- //$post['media'] .= " <div style='overflow:hidden; float:left; margin:2px;background-color:#".(($class != "") || ($elem['sensitive'] == true && $user_settings['explicit'] != 'off') ? averageColor($file['url']) : "000")."!important; ".($images === 1 ? "width:100%;" : "max-width:100%; max-height:100%;")."' $class>
- $post['media'] .= " <div style='overflow:hidden; float:left; margin:2px;background-color:#".(($class != "") || ($elem['sensitive'] == true && $user_settings['explicit'] != 'off') ? "000" : "000")."!important; ".($images === 1 ? "width:100%;" : "max-width:100%; max-height:100%;")."' $class>
- <div class='toggleblur' style='height:25px;'> Blur</div>
- <a target='_blank' href='" . $file['url'] . "' onClick='return false;' style='width:100%;' class='blur'>
- <noscript><img src='" . $file['url'] . "' style='width:100%;'></noscript>
- <img " . ($e < 2 ? "src='" . $file['url'] . "'" : "data-src='" . $file['url'] . "'") . " class='lazyload' style='".($images === 1 ? "width:100%;" : "max-width:100%; max-height:100%;")." vertical-align:middle;'>
- </a>
- <a target='_blank' href='" . $file['url'] . "' onClick='return false;' class='open-lightbox' style='display:none;'>
- <img src='" . $file['url'] . "' class='lazyload' style='width:100%;'>
- </a>
- </div>";
- }
- else {
- /* If the post was sensitive and wasn't caught by the nsfw filter and
- didn't got blurred, then the image will be shown normally */
- $post['media'] .= "<div style='margin:0px; ".($images == 3 && $m == 3 ? "width:100% !important;" : "")."background-color:#".($class != "" ? "000" : "000").";' $class><a target='_blank' href='" . $file['url'] . "' onClick='return false;' class='open-lightbox'><img " . ($e < 2 ? "src='" . $file['url'] . "'" : "data-src='" . $file['url'] . "'") . " class='lazyload' style='" . ($images === 1 ? "width:100%;" : "max-width:100%; max-height:100%;") . " vertical-align:middle;'><noscript><img src='" . $file['url'] . "' style='width:100%;'></noscript></a></div>";
- // $post['media'] .= "<div style='margin:0px; ".($images == 3 && $m == 3 ? "width:100% !important;" : "")."background-color:#".($class != "" ? averageColor($file['url']) : "000").";' $class><a target='_blank' href='" . $file['url'] . "' onClick='return false;' class='open-lightbox'><img " . ($e < 2 ? "src='" . $file['url'] . "'" : "data-src='" . $file['url'] . "'") . " class='lazyload' style='" . ($images === 1 ? "width:100%;" : "max-width:100%; max-height:100%;") . " vertical-align:middle;'><noscript><img src='" . $file['url'] . "' style='width:100%;'></noscript></a></div>";
- }
- } else {
- $post['media'] .= "<center><table><tr><td><a href='".$file['remote_url']."' download><img src='img/doc.png' width=40 border=0></a></td><td><a href='".$file['url']."' target='_blank'>".$file['description']."</a></td></tr></table></center>";
-
- }
- $m++;
- }
- } else {
- /* if the user turned off attachments we'll only show a link to it */
- $post['text'] .= "<br><br>\n";
- foreach ($elem['media_attachments'] as $file) {
- $post['text'] .= "<span class='fontello'></span><a href='".$file['url']."' target='_blank' onClick='return false;' class='open-lightbox'>See attachment ".($elem['sensitive'] == true ? "(NSFW)" : "")."</a><br>\n";
- }
- }
- }
- /* the code of the post footer (date, visibility and like/reblog buttons */
- $post['footer'] = "<div style='float:left;'>
- <a style='text-decoration:none;' class='ldr postAge' id='".strtotime($elem['created_at'])."' target='_blank' href='?thread=" . $elem['id'] . "' title='".gmdate("d/m/y H:i", strtotime($elem['created_at']))."'>" .time_elapsed_string($elem['created_at']) . "</a> - <span class='fontello ".$elem['visibility']."'></span> <span class='fontello ". ($elem['sensitive'] == true ? "sensitive" : "")."'> </span>
- </div>
- <div class='post_buttons' id='" . $elem['id'] . "'>
- " . ($logedin ? "<div class='felem'><a onClick='return false' class='replyform' href='?thread=" . $elem['id'] . "' style='font-family:fontello; vertical-align:middle;' alt='reply'></a></div>" : "") . "
- <div class='felem'><a onClick='return false' " . ($logedin ? "class='" . ($elem['favourited'] == true ? "unfav" : "fav") . "' href='?action=true&mode=".($elem['favourited'] == true ? "off" : "true")."&fav=" . $elem['id'] . "'" : "class='notAllowed'") . " style='font-family:fontello; vertical-align:middle;'> <span>" . $elem['favourites_count'] . "</span></a></div>
- <div class='felem'><a onClick='return false' " . ($logedin && ($elem['visibility'] == "public" || $elem['visibility'] == "unlisted") ? "class='" . ($elem['reblogged'] == true ? "unreblog" : "reblog") . "' href='?action=true&mode=".($elem['reblogged'] == true ? "off" : "on")."&reblog=" . $elem['id'] . "'" : "class='notAllowed'") . " style='font-family:fontello; vertical-align:middle;'> <span>" . $elem['reblogs_count'] . "</span></a></div>
- <div class='felem'><a class='replies' onClick='return false' href='?thread=" . $elem['id'] . "' style='font-family:fontello; vertical-align:middle;'> <span>" . $elem['replies_count'] . "</span></a></div>
- </div>";
- $post['form'] = ($tl['mode'] == 'thread' && $logedin ? str_replace(array(
- ":id:",
- ":content:"
- ) , array(
- $elem['id'],
- $json['mentions']
- ) , themes("get","templates/replyform.txt")) : "");
- $post['ancestors'] = " ";
- $post['descendants'] = " ";
- $post['notes'] = "";
- /* if the timeline is a single post, we'll fetch the replies and notes */
- if ($tl['mode'] == 'thread') {
- $replies = ($tl['mode'] == "thread" ? getreplies($tl['thread']) : false);
- $notes = ($tl['mode'] == "thread" ? getnotes($tl['thread']) : false);
- foreach ($replies as $e) {
- if ($e['mode'] == 'ancestor') {
- $post['ancestors'] .= render_reply($e['content']);
- }
- else {
- $post['descendants'] .= render_reply($e['content']);
- }
- }
- if ($notes) {
- foreach ($notes as $note) {
- $post['notes'] .= "<div id='" . $note[1]['id'] . "'>
- <a href='?user=" . $note[1]['id'] . "' class='ldr' title='" . $note[1]['acct'] . "'>
- <div class='nte' style='background-image:url(" . $note[1]['avatar'] . ");'>
- <div class='nte_type' style='background-color:" . ($note[0] == "fav" ? "red" : "green") . "'><span>" . ($note[0] == "fav" ? "" : "") . "</span></div>
- </div>
- </a>
- </div>";
- }
- }
- }
- if ((empty($elem['media_attachments']) && $post['media'] == "") || (!(empty($elem['media_attachments']) && $post['media'] == "") && $user_settings['attach'] == "off")) {
- $post['template'] = themes("get","templates/textpost.txt");
- }
- else {
- if ($logedin){
- $post['template'] = themes("get","templates/post.txt");
- } else {
- $post['template'] = themes("get","templates/post_logout.txt");
- }
- }
- foreach ($post as $key => $value) {
- $post['template'] = str_replace(":$key:", $value, $post['template']);
- }
- echo $post['template'];
- unset($post);
- $e++;
- $next = $elem['id'];
- }
- if ((!isset($_GET['next']) || (isset($_GET['next']) && !isset($_GET['ajax']))) && !isset($_GET['since']) && !isset($_GET['thread'])) {
- $query = http_build_query(array_filter(array(
- 'user' => (isset($tl['user']) ? $tl['user'] : false) ,
- 'mode' => $tl['mode']
- )));
- if ($tl['mode'] != "search"){
- echo "<div class='element'><div class='avatar' style='height:0px;'></div><div class='loadmore' style='display:table-cell; height:50px; line-height:50px;'><a class='link' onClick='return false;' style='margin:5px;' href='?next=$next&" . $query . "'>Load More Posts</a></div></div>";
- }
- }
- }
- ?>
|