functions.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. <?php
  2. /* this file stores all of the functions that are used
  3. over all of the other files. */
  4. ini_set("log_errors", 1);
  5. $srv = $user_settings['instance'];
  6. //$token = ($token != false ? msc($token,'d') : false);
  7. $token = ($token != false ? $token : false);
  8. /* the purpose of this function is to encode the auth token
  9. it is not used for now */
  10. function msc($string, $action = 'e') {
  11. // you may change these values to your own
  12. $secret_key = 'yAmfVhZwm0749FSY24dC';
  13. $secret_iv = 'm37uvAeKjYLKdI1lPkcJ';
  14. $output = false;
  15. $encrypt_method = "AES-256-CBC";
  16. $key = hash('sha256', $secret_key);
  17. $iv = substr(hash('sha256', $secret_iv) , 0, 16);
  18. if ($action == 'e') {
  19. $output = base64_encode(openssl_encrypt($string, $encrypt_method, $key, 0, $iv));
  20. }
  21. else if ($action == 'd') {
  22. $output = openssl_decrypt(base64_decode($string) , $encrypt_method, $key, 0, $iv);
  23. }
  24. return $output;
  25. }
  26. /* this function extracts the urls from a text and return them in an array */
  27. function get_urls($input) {
  28. $pattern = '$(https?://[a-z0-9_./?=&-~]+)(?![^<>]*>)$i';
  29. if (preg_match_all($pattern, $input, $matches)) {
  30. list($dummy, $links) = ($matches);
  31. return $links;
  32. }
  33. return false;
  34. }
  35. /* this function replaces the emoji codes in a text with the correspondent emojis
  36. of the specified instance, returns the html code with the emojis in the specified size*/
  37. function emoji($text, $size = 30, $srv) {
  38. $data = json_decode(file_get_contents("https://$srv/api/v1/custom_emojis") , true) [0]['url'];
  39. $u = explode("/", $data);
  40. array_pop($u);
  41. $url = implode("/", $u);
  42. $text = str_replace("http:", "http;", $text);
  43. $text = str_replace("https:", "https;", $text);
  44. $text = preg_replace('~:([a-z0-9_]+):~', "<img src='$url/$1.png' height=$size style='vertical-align: middle;'>", $text);
  45. $text = str_replace("http;", "http:", $text);
  46. $text = str_replace("https;", "https:", $text);
  47. return $text;
  48. }
  49. /* this is the same as above but is used on other places, like user bios and places where the
  50. shortcodes and the emoji url is defined in the same place */
  51. function emojify($string, $emojis, $size = 40) {
  52. foreach ($emojis as $emoji) {
  53. $string = str_replace(":" . $emoji['shortcode'] . ":", "<img alt='" . $emoji['shortcode'] . "' title='" . $emoji['shortcode'] . "' src='" . $emoji['static_url'] . "' height=$size style='vertical-align: middle;'>", $string);
  54. }
  55. return $string;
  56. }
  57. function emoji_list($val){
  58. $emojilist = api_get("/custom_emojis");
  59. $c = 0;
  60. foreach ($emojilist as $emoji){
  61. if (starts_with($emoji['shortcode'],$val) && $c < 50){
  62. $return .= "<img style='margin:1px;' src='".$emoji['static_url']."' class='emoji' title='".$emoji['shortcode']."' height=40>";
  63. $c++;
  64. }
  65. }
  66. if ($c < 50){
  67. foreach ($emojilist as $emoji){
  68. if ((contains($emoji['shortcode'],$val) && !starts_with($emoji['shortcode'],$val)) && $c < 50){
  69. $return .= "<img style='margin:1px;' src='".$emoji['static_url']."' class='emoji' title='".$emoji['shortcode']."' height=40>";
  70. $c++;
  71. }
  72. }
  73. }
  74. return $return;
  75. }
  76. function starts_with($string,$search){
  77. if (substr(strtolower($string),0,strlen($search)) == strtolower($search)){
  78. return true;
  79. }
  80. return false;
  81. }
  82. function contains($string,$search){
  83. if (is_numeric(strpos(strtolower($string),strtolower($search)))){
  84. return true;
  85. }
  86. return false;
  87. }
  88. /* this function fetches the context (the previous posts and replies) of a specified post
  89. $post = ID of the post.
  90. */
  91. function context($post) {
  92. global $srv;
  93. global $token;
  94. $curl = curl_init();
  95. curl_setopt($curl, CURLOPT_URL, "https://$srv/api/v1/statuses/$post/context");
  96. if (!is_null($token)) {
  97. curl_setopt($curl, CURLOPT_HTTPHEADER, array(
  98. 'Authorization: Bearer ' . $token
  99. ));
  100. }
  101. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  102. $result = curl_exec($curl);
  103. curl_close($curl);
  104. return $result;
  105. }
  106. /* this function just reduces an image to a 1x1 pixel image to get the overall color.
  107. */
  108. function averageColor($url) {
  109. @$image = imagecreatefromstring(file_get_contents($url));
  110. if (!$image) {
  111. $mainColor = "CCCCCC";
  112. }
  113. else {
  114. $thumb = imagecreatetruecolor(1, 1);
  115. imagecopyresampled($thumb, $image, 0, 0, 0, 0, 1, 1, imagesx($image) , imagesy($image));
  116. $mainColor = strtoupper(dechex(imagecolorat($thumb, 0, 0)));
  117. }
  118. return $mainColor;
  119. }
  120. /* this function fetches all the data from a profile (bio, username, relationships, etc) */
  121. function user_info($user) {
  122. global $user_settings;
  123. $info = api_get("accounts/" . $user);
  124. $rel = api_get("accounts/relationships?id=" . $user);
  125. return array(
  126. $info,
  127. $rel
  128. );
  129. }
  130. function api_getv2($url) {
  131. global $srv;
  132. global $token;
  133. $curl = curl_init();
  134. curl_setopt($curl, CURLOPT_URL, "https://$srv/api/v2/" . $url);
  135. if (!is_null($token)) {
  136. curl_setopt($curl, CURLOPT_HTTPHEADER, array(
  137. 'Authorization: Bearer ' . $token
  138. ));
  139. }
  140. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  141. $result = curl_exec($curl);
  142. curl_close($curl);
  143. return json_decode($result, true);
  144. }
  145. /* a function to make an authenticated general GET api call to the logged-in instance */
  146. function api_get($url) {
  147. global $srv;
  148. global $token;
  149. $curl = curl_init();
  150. curl_setopt($curl, CURLOPT_URL, "https://$srv/api/v1/" . $url);
  151. if (!is_null($token)) {
  152. curl_setopt($curl, CURLOPT_HTTPHEADER, array(
  153. 'Authorization: Bearer ' . $token
  154. ));
  155. }
  156. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  157. $result = curl_exec($curl);
  158. curl_close($curl);
  159. return json_decode($result, true);
  160. }
  161. /* a function to make an authenticated general POST api call to the logged-in instance */
  162. function api_post($url, $array) {
  163. global $srv;
  164. global $token;
  165. $cSession = curl_init();
  166. curl_setopt($cSession, CURLOPT_HEADER, false);
  167. curl_setopt($cSession, CURLOPT_POST, 1);
  168. curl_setopt($cSession, CURLOPT_URL, "https://$srv/api/v1/" . $url);
  169. if (!is_null($token)) {
  170. curl_setopt($cSession, CURLOPT_HTTPHEADER, array(
  171. 'Authorization: Bearer ' . $token
  172. ));
  173. }
  174. curl_setopt($cSession, CURLOPT_POSTFIELDS, http_build_query($array));
  175. curl_setopt($cSession, CURLOPT_RETURNTRANSFER, true);
  176. $result = curl_exec($cSession);
  177. curl_close($cSession);
  178. return json_decode($result, true);
  179. }
  180. /* a function to make general DELETE api calls to the logged-in instance*/
  181. function api_delete($url, $array) {
  182. global $srv;
  183. global $token;
  184. $cSession = curl_init();
  185. curl_setopt($cSession, CURLOPT_HEADER, false);
  186. curl_setopt($cSession, CURLOPT_POST, 1);
  187. curl_setopt($cSession, CURLOPT_URL, "https://$srv/api/v1/" . $url);
  188. curl_setopt($cSession, CURLOPT_CUSTOMREQUEST, "DELETE");
  189. if (!is_null($token)) {
  190. curl_setopt($cSession, CURLOPT_HTTPHEADER, array(
  191. 'Authorization: Bearer ' . $token
  192. ));
  193. }
  194. curl_setopt($cSession, CURLOPT_POSTFIELDS, http_build_query($array));
  195. curl_setopt($cSession, CURLOPT_RETURNTRANSFER, true);
  196. $result = curl_exec($cSession);
  197. curl_close($cSession);
  198. return json_decode($result, true);
  199. }
  200. /* this function is used to generate the html code of a reply */
  201. function render_reply($item) {
  202. global $user_settings;
  203. global $logedin;
  204. global $srv;
  205. $reply['mode'] = "";
  206. if (isset($item['type']) && $item['type'] == 'ancestor') {
  207. $reply['mode'] = "ancestor";
  208. }
  209. $reply['id'] = $item['id'];
  210. $reply['uid'] = $item['account']['id'];
  211. $reply['name'] = emojify($item['account']['display_name'], $item['account']['emojis'], 15);
  212. $reply['acct'] = $item['account']['acct'];
  213. $reply['avatar'] = $item['account']['avatar'];
  214. $reply['menu'] = "<ul>";
  215. if ($logedin) {
  216. $reply['menu'] .= ($item['account']['id'] == $user_settings['uid'] ? "<li><a href='?action=delete&thread=" . $item['id'] . "' onClick='return false;' class='delete fontello' id='" . $item['id'] . "'>&#xe80e; Delete Post</a></li>" : "");
  217. $reply['menu'] .= ($item['account']['id'] != $user_settings['uid'] ? "<li><a href='?action=mute&user=" . $item['account']['id'] . "' onClick='return false;' class='mute fontello' id='" . $item['account']['id'] . "' style='background-color:transparent;'>&#xe81b; Mute User</a></li>" : "");
  218. $reply['menu'] .= ($item['account']['id'] != $user_settings['uid'] ? "<li><a href='?action=nsfw&user=" . $item['account']['id'] . "' onClick='return false;' class='nsfw fontello' id='" . $item['account']['id'] . "' style='background-color:transparent;'>&#xe829; User is NSFW</a></li>" : "");
  219. }
  220. $reply['menu'] .= "<li><a target='_blank' href='" . $item['url'] . "' class='link fontello' style='background-color:transparent;'>&#xf14c; Original Note</a></li>";
  221. $reply['menu'] .= "</ul>";
  222. $json['id'] = $item['id'];
  223. $json['scope'] = $item['visibility'];
  224. if ($logedin) {
  225. $json['mentions'] = "";
  226. $array = $item["mentions"];
  227. $json['mentions'] = ($user_settings['acct'] == $item["account"]['acct'] ? "" : "@" . $item["account"]['acct']) . " ";
  228. if (!empty($array)) {
  229. foreach ($array as $mnt) {
  230. if ($mnt['acct'] != $user_settings['acct']) {
  231. $json['mentions'] .= "@" . $mnt['acct'] . " ";
  232. }
  233. }
  234. }
  235. }
  236. $reply['json'] = json_encode($json);
  237. $reply['replyto'] = ($item['in_reply_to_id'] ? " <a class='fontello link preview ldr' target='_blank' id='" . $item['in_reply_to_id'] . "' href='?thread=" . $item['in_reply_to_id'] . "'>&#xf112;</a> " : "");
  238. $reply['text'] = processText($item);
  239. $public = "&#xe83c;";
  240. $private = "&#xe819;";
  241. $unlisted = "&#xe816;";
  242. $direct = "&#xf0e0;";
  243. $reply['date'] = "<a style='text-decoration:none;color:darkgray;' target='_blank' href='" . $item['url'] . "'><span class='fontello'>&#xe817;</span></a> - <a class='ldr' style='text-decoration:none;color:darkgray;' target='_blank' href='?thread=" . $item['id'] . "&instance=$srv" . "'>" . date("d/m/y H:i", strtotime($item['created_at'])) . "</a> - <span class='fontello' style='color:darkgray;'>" . $$item['visibility'] . "</span>";
  244. $reply['media'] = "";
  245. if (!empty($item['media_attachments'])) {
  246. $reply['media'] = "<div style='width:170px; display:inline-block; float:left; margin-right:15px; '>";
  247. $images = count($item['media_attachments']);
  248. $class = ($images > 1 ? "class='icon'" : "");
  249. foreach ($item['media_attachments'] as $file) {
  250. $ext = explode(".", $file['url']);
  251. $ext = end($ext);
  252. $ext = explode("?", $ext) [0];
  253. if ($ext == 'mp4' || $ext == 'webm') {
  254. $reply['media'] .= "<div style='text-align:center; width:100%;'><video preload='metadata' width='100%' controls ".($user_settings['videoloop'] == "on" ? "loop" : "").">
  255. <source src='" . $file['url'] . "' type='video/$ext'>
  256. </video></div>
  257. ";
  258. }
  259. elseif ($ext == 'mp3' || $ext == 'ogg') {
  260. $reply['media'] .= "<div style='text-align:center; width:100%;'><audio controls>
  261. <source src='" . $file['url'] . "' type='audio/$ext'>
  262. Your browser does not support the audio tag.
  263. </audio> </div>";
  264. }
  265. else {
  266. if ($item['sensitive'] == true && $user_settings['explicit'] != 'off') {
  267. $reply['media'] .= "<div style='overflow:hidden; float:left; margin:2px;' $class><a target='_blank' href='" . $file['url'] . "' onClick='return false;' class='blur'><noscript><img src='" . $file['url'] . "' style='width:100%;'></noscript><img " . "data-src='" . $file['url'] . "'" . " class='' style='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='' style='width:100%;'></a></div>";
  268. }
  269. else {
  270. $reply['media'] .= "<div style='margin:0px;' $class><a target='_blank' href='" . $file['url'] . "' onClick='return false;' class='open-lightbox'><img src='" . $file['url'] . "'" . " class='' style='max-width:100%; max-height:100%; vertical-align:middle;'><noscript><img src='" . $file['url'] . "' style='width:100%;'></noscript></a></div>";
  271. }
  272. }
  273. }
  274. $reply['media'] .= "</div>";
  275. }
  276. $reply['buttons'] = "
  277. " . ($logedin ? "<div class='felem'><a onClick='return false' class='replyform' href='?thread=" . $item['id'] . "' style='font-family:fontello'>&#xf112;</a></div>" : "") . "
  278. <div class='felem'><a onClick='return false' " . ($logedin ? "class='" . ($item['favourited'] == true ? "unfav" : "fav") . "' href='?action=fav&thread=" . $item['id'] . "'" : "") . " style='font-family:fontello'>&#xe802; <span>" . $item['favourites_count'] . "</span></a></div>
  279. <div class='felem'><a onClick='return false' " . ($logedin && $item['visibility'] == "public" ? "class='" . ($item['reblogged'] == true ? "unreblog" : "reblog") . "' href='?action=reblog&thread=" . $item['id'] . "'" : "") . " style='font-family:fontello'>&#xe83a; <span>" . $item['reblogs_count'] . "</span></a></div>
  280. ";
  281. $result = themes("get","templates/reply.txt");
  282. foreach ($reply as $key => $elem) {
  283. $result = str_replace(":$key:", $elem, $result);
  284. }
  285. return $result;
  286. }
  287. /* a function to fav or unfav a specified post */
  288. function favourite($post, $mode) {
  289. $result = api_post(($mode == true ? "statuses/$post/favourite" : "statuses/$post/unfavourite"),array());
  290. if (isset($result['favourites_count'])) {
  291. return $result['favourites_count'];
  292. }
  293. else {
  294. return "error";
  295. }
  296. }
  297. /* a function to reblog or unreblog a specified post */
  298. function reblog($post, $mode) {
  299. $result = api_post(($mode == true ? "statuses/$post/reblog" : "statuses/$post/unreblog"),array());
  300. if (isset($result['reblog']['reblogs_count'])) {
  301. return $result['reblog']['reblogs_count'];
  302. }
  303. elseif (isset($result['reblogs_count'])) {
  304. return $result['reblogs_count'];
  305. }
  306. else {
  307. return "error";
  308. }
  309. }
  310. /* function to delete a post */
  311. function delpost($id) {
  312. global $srv;
  313. global $token;
  314. if (!is_null($token)) {
  315. $curl = curl_init();
  316. curl_setopt($curl, CURLOPT_HEADER, false);
  317. curl_setopt($curl, CURLOPT_POST, 1);
  318. curl_setopt($curl, CURLOPT_URL, "https://$srv/api/v1/statuses/$id");
  319. curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
  320. curl_setopt($curl, CURLOPT_HTTPHEADER, array(
  321. 'Authorization: Bearer ' . $token
  322. ));
  323. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  324. $result = curl_exec($curl);
  325. curl_close($curl);
  326. $result = json_decode($result, true);
  327. if (empty($result)) {
  328. return "1";
  329. }
  330. else {
  331. return "0";
  332. }
  333. }
  334. }
  335. /* function to send a new post to the logged in instance
  336. it takes the media ids as an array */
  337. function sendpost($text, $media, $reply, $markdown = false, $scope, $sensitive, $spoiler = false) {
  338. global $srv;
  339. global $token;
  340. if (!is_null($token)) {
  341. $cSession = curl_init();
  342. curl_setopt($cSession, CURLOPT_URL, "https://$srv/api/v1/statuses");
  343. curl_setopt($cSession, CURLOPT_RETURNTRANSFER, true);
  344. curl_setopt($cSession, CURLOPT_POST, 1);
  345. curl_setopt($cSession, CURLOPT_HTTPHEADER, array(
  346. 'Authorization: Bearer ' . $token
  347. ));
  348. $query = "";
  349. $query .= "status=" . urlencode(html_entity_decode($text, ENT_QUOTES)) . "&visibility=" . $scope;;
  350. if (!is_null($reply) && $reply != "null") {
  351. $query .= "&in_reply_to_id=" . $reply;
  352. }
  353. if ($markdown == true) {
  354. $query .= "&content_type=text/markdown";
  355. }
  356. if ($sensitive == 'true') {
  357. $query .= "&sensitive=true";
  358. }
  359. if ($spoiler == true) {
  360. $query .= "&spoiler_text=" . $spoiler;
  361. }
  362. if (!is_null($media)) {
  363. foreach ($media as $mid) {
  364. $query .= "&media_ids[]=" . $mid;
  365. }
  366. }
  367. curl_setopt($cSession, CURLOPT_POSTFIELDS, $query);
  368. $result = curl_exec($cSession);
  369. curl_close($cSession);
  370. return $result;
  371. }
  372. else {
  373. return false;
  374. }
  375. }
  376. /* uploads a file to the logged in instance.
  377. the function takes the file from the local storage */
  378. function uploadpic($file) {
  379. global $srv;
  380. global $token;
  381. if (!is_null($token)) {
  382. $mime = get_mime($file);
  383. $info = pathinfo($file);
  384. $name = $info['basename'];
  385. $output = new CURLFile($file, $mime, $name);
  386. do {
  387. $cSession = curl_init();
  388. curl_setopt($cSession, CURLOPT_URL, "https://$srv/api/v1/media");
  389. curl_setopt($cSession, CURLOPT_RETURNTRANSFER, true);
  390. curl_setopt($cSession, CURLOPT_POST, 1);
  391. curl_setopt($cSession, CURLOPT_HTTPHEADER, array(
  392. 'Authorization: Bearer ' . $token
  393. ));
  394. curl_setopt($cSession, CURLOPT_POSTFIELDS, array(
  395. 'file' => $output
  396. ));
  397. $result = curl_exec($cSession);
  398. } while (empty($result));
  399. curl_close($cSession);
  400. $array = json_decode($result, true);
  401. $ext = explode(".", $array['url']);
  402. $ext = end($ext);
  403. $ext = explode("?", $ext) [0];
  404. if (in_array($ext, array(
  405. 'jpg',
  406. 'jpeg',
  407. 'gif',
  408. 'png',
  409. 'svg'
  410. ))) {
  411. $file = $array['url'];
  412. }
  413. else {
  414. $file = "img/doc.png";
  415. }
  416. return json_encode(array(
  417. $array['id'],
  418. $file
  419. ));
  420. }
  421. else {
  422. return false;
  423. }
  424. }
  425. /* this is used to register DashFE as an application on an instance
  426. mostly used when logging in
  427. */
  428. function register_app($instance) {
  429. global $setting;
  430. $cSession = curl_init();
  431. curl_setopt($cSession, CURLOPT_URL, "https://$instance/api/v1/apps");
  432. curl_setopt($cSession, CURLOPT_RETURNTRANSFER, true);
  433. curl_setopt($cSession, CURLOPT_HEADER, false);
  434. curl_setopt($cSession, CURLOPT_POST, 1);
  435. curl_setopt($cSession, CURLOPT_POSTFIELDS, http_build_query(array(
  436. 'client_name' => $setting['appname'],
  437. 'redirect_uris' => $setting['url'],
  438. 'scopes' => 'read write follow'
  439. )));
  440. $result = curl_exec($cSession);
  441. curl_close($cSession);
  442. return json_decode($result, true);
  443. }
  444. /* This function will fetch and render all the notifications since an $id
  445. or get a list of all past notification ($max notifications specified)
  446. */
  447. function getnotif($id = false, $max = false) {
  448. global $srv;
  449. global $token;
  450. global $user_settings;
  451. $n = "";
  452. $notif = api_get("notifications?" . ($id == false ? "limit=9&" : "") . ($id != false ? ($max == true ? "max_id=$id" : "since_id=$id") : ""));
  453. if (!empty($notif)) {
  454. foreach ($notif as $post) {
  455. if (!isset($post["type"])){
  456. break;
  457. }
  458. $user = "<a class='link ldr uname' style='font-size:12px;' href='?user=" . $post['account']['id'] . "'>" . emojify($post['account']['display_name'], $post['account']['emojis'], 10) . "</a>";
  459. $preview = "";
  460. $buttons = "";
  461. $media = "";
  462. if ($post["type"] == "pleroma:emoji_reaction"){
  463. continue;
  464. }
  465. switch ($post["type"]) {
  466. case "mention":
  467. if ($post['status']['in_reply_to_id'] == null) {
  468. $type = "<span class='fontello' style='color:#62C2CC; font-size:10px;'>&#xf10d;</span>";
  469. $string = "mentioned you in a post";
  470. $preview = "<a style='text-decoration:none;' class='ldr text' href='?thread=" . $post['status']['id'] . "' target='_blank'><span style='display:block; opacity:1; font-size:10px; line-height:12px;'>" . emojify(strip_tags(trim($post['status']['content']) , '<br><br \>') , $post['status']['emojis'], 15) . "</span></a>";
  471. $media = (!empty($post['status']['media_attachments']) ? "<a style='text-decoration:none;' class='ldr' href='?thread=" . $post['status']['id'] . "' target='_blank'><div class='notifpic' style='flex: 0 0 60px; background-size:cover; background-image:url(" . $post['status']['media_attachments'][0]['url'] . ");'></div></a>" : "");
  472. }
  473. else {
  474. $type = "<span class='fontello' style='color:#62C2CC; font-size:10px;'>&#xf112;</span>";
  475. $string = "replied to your post";
  476. $preview = "<a style='text-decoration:none;' class='ldr text' href='?thread=" . $post['status']['id'] . "' target='_blank'><span style='display:block; opacity:1; font-size:10px; line-height:12px;'>" . emojify(strip_tags(trim($post['status']['content']) , '<br><br \>') , $post['status']['emojis'], 15) . "</span></a>";
  477. $media = (!empty($post['status']['media_attachments']) ? "<div class='notifpic' style='flex: 0 0 60px; background-size:cover; background-image:url(" . $post['status']['media_attachments'][0]['url'] . ");'></div>" : "");
  478. }
  479. $array = $post['status']["mentions"];
  480. $mentions = ($user_settings['acct'] == $post['status']['account']['acct'] ? "" : "@" . $post['status']['account']['acct']) . " ";
  481. if (!empty($array)) {
  482. foreach ($array as $mnt) {
  483. if ($mnt['acct'] != $user_settings['acct']) {
  484. $mentions .= "@" . $mnt['acct'] . " ";
  485. }
  486. }
  487. }
  488. $buttons = "<div class='post_buttons' id='" . $post['status']['id'] . "' style='position:absolute; right:10px; bottom:10px; border-radius:60px; padding:5px;'>
  489. <div class='felem'><a onClick='return false' class='quickreply' id='" . $post['status']['id'] . "' data-mentions='" . $mentions . "' href='?thread=" . $post['status']['id'] . "' style='font-family:fontello'>&#xe824;</a></div>
  490. <div class='felem'><a onClick='return false' class='" . ($post['status']['favourited'] == true ? "unfav" : "fav") . "' href='?action=fav&thread=" . $post['status']['id'] . "'" . " style='font-family:fontello'>&#xe802;</a></div>
  491. <div class='felem'><a onClick='return false' " . ($post['status']['visibility'] == "public" || $post['status']['visibility'] == "unlisted" ? "class='" . ($post['status']['reblogged'] == true ? "unreblog" : "reblog") . "' href='?action=reblog&thread=" . $post['status']['id'] . "'" : "") . " style='font-family:fontello'>&#xe83a;</a></div></div>";
  492. break;
  493. case "favourite":
  494. $type = "<span class='fontello' style='color:#F17022; font-size:10px;'>&#xe802;</span>";
  495. $string = "favourited your post";
  496. $preview = "<a style='text-decoration:none;' class='ldr text' href='?thread=" . $post['status']['id'] . "' target='_blank'><span style='display:block; opacity:1; font-size:10px; line-height:12px;'>" . (!empty($post['status']['content']) ? emojify(strip_tags(trim($post['status']['content']) , '<br><br \>') , $post['status']['emojis'], 15) : "Favourited your image") . "</span></a>";
  497. $media = (!empty($post['status']['media_attachments']) ? "<div class='notifpic' style='flex: 0 0 60px; background-size:cover; background-image:url(" . $post['status']['media_attachments'][0]['url'] . ");'></div>" : "");
  498. break;
  499. case "reblog":
  500. $type = "<span class='fontello' style='color:#D1DC29; font-size:10px;'>&#xe826;</span>";
  501. $string = "reblogged your post";
  502. $preview = "<a style='text-decoration:none;' class='ldr text' href='?thread=" . $post['status']['id'] . "' target='_blank'><span style='display:block; opacity:1; font-size:10px; line-height:12px;'>" . (!empty($post['status']['content']) ? emojify(strip_tags(trim($post['status']['content']) , '<br><br \>') , $post['status']['emojis'], 15) : "Reblogged your image") . "</span></a>";
  503. @$media = (!is_null($post['status']['media_attachments']) ? "<div class='notifpic' style='flex: 0 0 60px; background-size:cover; background-image:url(" . $post['status']['media_attachments'][0]['url'] . ");'></div>" : "");
  504. break;
  505. case "follow":
  506. list($info, $rel) = user_info($post["account"]["id"]);
  507. $type = "<span class='fontello' style='color:#FDB813; font-size;10px;'>&#xf234;</span>";
  508. $preview = "started following you";
  509. if ($rel[0]['following']) {
  510. $label = "&#xe80c; Following";
  511. $class = "unfollow";
  512. }
  513. else {
  514. if ($info['locked']) {
  515. if ($rel[0]['requested']) {
  516. $label = "&#xe806; Follow Requested";
  517. $class = "unfollow";
  518. }
  519. else {
  520. $label = "&#xe806; Request Follow";
  521. $class = "follow";
  522. }
  523. }
  524. else {
  525. $label = "&#xf234; Follow";
  526. $class = "follow";
  527. }
  528. }
  529. $buttons .= "<div class='post_buttons' style='position:absolute; right:10px; bottom:10px; border-radius:60px; padding:5px;'><span id='" . $info['id'] . "' class='profileButton $class' style='background-color:white; font-family:sans,fontello ;font-size:13px;'>$label</span></div>";
  530. break;
  531. }
  532. $n .= "
  533. <div class='notif " . ($id == false ? "" : "new") . "' id='" . $post['id'] . "'>
  534. <div class='notifContents'>
  535. <div style='flex: 0 0 60px; background-size:cover; background-image:url(" . $post['account']['avatar'] . "); border-radius:5px;'></div>
  536. <div style='flex: 1; padding-left:5px; padding-right:5px; word-break: break-word; overflow:hidden;'>
  537. <span>$type <span style='font-size:12px; font-weight:bold;'>$user</span></span>
  538. " . trim($preview) . "
  539. $buttons
  540. </div>
  541. $media
  542. </div>
  543. </div>
  544. ";
  545. }
  546. return $n;
  547. }
  548. }
  549. /* this function will get all the notes (reblogs and favs) that has an specified post */
  550. function getnotes($thread) {
  551. global $user_settings;
  552. global $token;
  553. global $srv;
  554. global $setting;
  555. global $logedin;
  556. @$reb = array(
  557. json_decode(file_get_contents("https://$srv/api/v1/statuses/" . $thread . "/reblogged_by") , true)
  558. );
  559. @$fab = array(
  560. json_decode(file_get_contents("https://$srv/api/v1/statuses/" . $thread . "/favourited_by") , true)
  561. );
  562. $limit = (count($reb[0]) > count($fab[0]) ? count($reb[0]) - 1 : count($fab[0]) - 1);
  563. $notes = array();
  564. $index = 0;
  565. for ($i = 0;$i <= $limit;$i++) {
  566. if (isset($reb[0][$i])) {
  567. $notes[$index][0] = "reb";
  568. $notes[$index][1] = $reb[0][$i];
  569. $index++;
  570. }
  571. if (isset($fab[0][$i])) {
  572. $notes[$index][0] = "fav";
  573. $notes[$index][1] = $fab[0][$i];
  574. $index++;
  575. }
  576. }
  577. return $notes;
  578. }
  579. /* this function will fetch all the replies that a post have
  580. or will fetch only the ones after a specified ($since) post id
  581. */
  582. function getreplies($thread, $since = false) {
  583. global $user_settings;
  584. global $token;
  585. global $srv;
  586. global $setting;
  587. global $logedin;
  588. $context = json_decode(context($thread) , true);
  589. $array = array();
  590. if (!empty($context['ancestors'])) {
  591. if ($since == false) {
  592. foreach ($context['ancestors'] as $elem) {
  593. $elem['type'] = 'ancestor';
  594. $array[] = $elem;
  595. }
  596. }
  597. }
  598. $flag = 0;
  599. if (!empty($context['descendants'])) {
  600. foreach ($context['descendants'] as $elem) {
  601. if (($since != false && $flag == 1) || $since == false) {
  602. $elem['type'] = 'descendant';
  603. $array[] = $elem;
  604. }
  605. if ($since != false && $elem['id'] == $since) {
  606. $flag = 1;
  607. }
  608. }
  609. }
  610. $replies = array();
  611. foreach ($array as $item) {
  612. $reply['mode'] = "";
  613. if ($item['type'] == 'ancestor') {
  614. $reply['mode'] = "ancestor";
  615. }
  616. $replies[] = array(
  617. 'mode' => $reply['mode'],
  618. 'content' => $item
  619. );
  620. }
  621. return $replies;
  622. }
  623. /* this function takes some options from the init.php file and the user_settings cookie
  624. and fetches all the posts of the appropiate timeline */
  625. function timeline($query) {
  626. global $token;
  627. global $srv;
  628. $notes = "";
  629. $media = ($query['text'] == "on" ? "" : "&only_media=true");
  630. $next = ($query['next'] ? "&max_id=" . $query['next'] : ($query['since'] ? "&since_id=" . $query['since'] : ""));
  631. switch ($query['mode']) {
  632. case "home":
  633. $array = api_get("timelines/home?limit=25{$media}{$next}");
  634. break;
  635. case "federated":
  636. $array = api_get("timelines/public?limit=25{$media}{$next}");
  637. break;
  638. case "tag":
  639. $array = api_get("timelines/tag/" . $query['tag'] . "?limit=25{$media}{$next}");
  640. break;
  641. case "local":
  642. $array = api_get("timelines/public?limit=25&local=true{$media}{$next}");
  643. break;
  644. case "user":
  645. $array = api_get("accounts/" . $query['user'] . "/statuses?limit=25{$media}{$next}");
  646. break;
  647. case "thread":
  648. $array = array(
  649. api_get("statuses/" . $query['thread'])
  650. );
  651. break;
  652. case "favourites":
  653. $array = api_get("favourites?limit=25{$media}{$next}");
  654. break;
  655. case "direct":
  656. $array = api_get("timelines/direct?limit=25{$next}");
  657. break;
  658. case "list":
  659. $array = api_get("timelines/list/" . $query['list'] . "?limit=25{$next}");
  660. break;
  661. case "bookmarks":
  662. $array = api_get("bookmarks?limit=25{$next}");
  663. break;
  664. case "search":
  665. $array = api_getv2("search?limit=40&q=".$query['search']."{$next}")['statuses'];
  666. break;
  667. case "account":
  668. $info = api_get("accounts/verify_credentials");
  669. $array = api_get("accounts/" . $info['id'] . "/statuses?limit=25{$media}{$next}");
  670. break;
  671. default:
  672. $array = api_get("timelines/public?limit=25{$media}{$next}");
  673. break;
  674. }
  675. if (!is_array($array)) {
  676. return false;
  677. }
  678. $next = end($array) ['id'];
  679. $thread = array();
  680. foreach ($array as $elem) {
  681. if ($query['replies'] == "on" || $query['mode'] == "thread") {
  682. $thread[] = $elem;
  683. }
  684. else {
  685. if ($elem['in_reply_to_id'] == null) {
  686. $thread[] = $elem;
  687. }
  688. }
  689. }
  690. return array(
  691. $thread,
  692. $next
  693. );
  694. }
  695. /* this function takes in a whole post entity and spits out the HTMLfied text of the post
  696. with the urls and @handles linkified and all the emojis replaced */
  697. function processText($elem) {
  698. global $user_settings;
  699. require_once "vendor/simple_html_dom.php";
  700. $content = trim(html_entity_decode($elem['content'],ENT_QUOTES));
  701. if (!empty($content)) {
  702. $html = str_get_html($content);
  703. foreach ($html->find('a') as $lnk) {
  704. foreach ($elem['media_attachments'] as $f) {
  705. if (is_numeric(strpos($f['description'],explode("…",$lnk->innertext)[0]))) {
  706. $content = str_replace($lnk->outertext . "<br/>", null, $content);
  707. $content = str_replace("<br/>" . $lnk->outertext, null, $content);
  708. $content = str_replace($lnk->outertext, null, $content);
  709. }
  710. }
  711. if (is_numeric(strpos($lnk->href, $user_settings['instance'])) || in_array($lnk->class, array(
  712. "u-url mention",
  713. "hashtag"
  714. )) || $lnk->rel == "tag") {
  715. $content = str_replace($lnk->outertext, $lnk->innertext, $content);
  716. }
  717. else {
  718. $prv = $lnk->outertext;
  719. $lnk->target = '_blank';
  720. $lnk->class = 'link external';
  721. $content = str_replace($prv, $lnk->outertext, $content);
  722. }
  723. }
  724. }
  725. $result = strip_tags($content, '<br><p><strong><a><em><strike>');
  726. $result = str_replace('<br />', ' <br>', $result);
  727. //$result = str_replace('&#39;', "'", $result);
  728. foreach ($elem['mentions'] as $mention) {
  729. $result = str_replace("@" . $mention['username'], "<span class='user' id='" . $mention['id'] . "'><a href='?user=" . $mention['id'] . "' class='link ldr' onClick='return false;'>@" . $mention['username'] . "</a></span>", $result);
  730. }
  731. //$result = preg_replace("/(?<!=\")(\b[\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/", "<a target=\"_blank\" class='external' style='color:navy;' href=\"$1\">$1</a>", $result);
  732. $result = emojify($result, $elem['emojis']);
  733. $result = preg_replace("/#([A-Za-z0-9\/\.]*)/", "<a class='ldr' href=\"./?tag=$1\"><b>#$1</b></a>", $result);
  734. return $result;
  735. }
  736. /* function used in the process of uploading a file */
  737. function get_mime($filename) {
  738. $result = new finfo();
  739. if (is_resource($result) === true) {
  740. return $result->file($filename, FILEINFO_MIME_TYPE);
  741. }
  742. return false;
  743. }
  744. function sanitize($text){
  745. return preg_replace("/[^a-zA-Z0-9]+/", "", $text);
  746. }
  747. function themes($mode,$name = false){
  748. global $user_settings;
  749. switch ($mode){
  750. case "list":
  751. $themes = scandir("themes/");
  752. $themelist = array();
  753. foreach ($themes as $elem){
  754. if ($elem != ".." && $elem != "." && $elem != "custom"){
  755. $themelist[] = $elem;
  756. }
  757. }
  758. return $themelist;
  759. case "file":
  760. $theme = sanitize($user_settings['theme']);
  761. if (file_exists("themes/$theme/$name")){
  762. return "themes/$theme/$name";
  763. } else {
  764. return "$name";
  765. }
  766. case "get":
  767. $theme = sanitize($user_settings['theme']);
  768. if (file_exists("themes/$theme/$name")){
  769. return file_get_contents("themes/$theme/$name");
  770. } else {
  771. return file_get_contents("$name");
  772. }
  773. }
  774. }