friendship ended with social-app. php is my new best friend
1<?php 2error_reporting(E_ALL); 3ini_set('display_errors', 'On'); 4ini_set('log_errors_max_len', '0'); 5 6require_once('vendor/autoload.php'); 7require_once('config.php'); 8require_once('lib/bskyToucher.php'); 9 10use flight\Engine; 11use League\CommonMark\CommonMarkConverter; 12use React\Promise\Deferred; 13use React\EventLoop\Loop; 14use React\Promise\Promise; 15use Tracy\Debugger; 16use Tracy\OutputDebugger; 17use Matrix\Async; 18 19$bskyToucher = new BskyToucher(); 20 21$favoriteFeeds = array_map(function ($feed) use ($bskyToucher) { 22 return $bskyToucher->getFeedInfo($feed); 23}, FAVORITE_FEEDS); 24 25function getPostOgImage(object $post): ?string { 26 if (!property_exists($post, 'embedType') || !$post->embedType) return null; 27 28 if ($post->embedType === 'app.bsky.embed.images') { 29 return $post->embeds[0]->imgUrl; 30 } else if ($post->embedType === 'app.bsky.embed.external' || $post->embedType === 'app.bsky.embed.video') { 31 return $post->embeds[0]->thumb; 32 } else if ($post->embedType === 'app.bsky.embed.record') { 33 return getPostOgImage($post->embeds[0]->post); 34 } 35 return null; 36} 37 38/*Debugger::enable(); 39// This where errors and exceptions will be logged. Make sure this directory exists and is writable. 40Debugger::$logDirectory = __DIR__ . '/../log/'; 41//Debugger::$strictMode = true; // display all errors 42// Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // all errors except deprecated notices 43if (Debugger::$showBar) { 44 // This is specific to the Tracy Extension for Flight if you've included that 45 // otherwise comment this out. 46 //new TracyExtensionLoader($app); 47}*/ 48 49Flight::set('frontpageFeed', FRONTPAGE_FEED); 50Flight::set('slingshotInstance', SLINGSHOT_INSTANCE); 51Flight::set('constellationInstance', CONSTELLATION_INSTANCE); 52Flight::set('plcDirectory', PLC_DIRECTORY); 53Flight::set('defaultPds', DEFAULT_PDS); 54Flight::set('publicApi', PUBLIC_API); 55Flight::set('frontpageFeed', FRONTPAGE_FEED); 56Flight::set('defaultRelay', DEFAULT_RELAY); 57Flight::set('userAuth', null); 58Flight::set('flight.log_errors', false); 59Flight::set('flight.handle_errors', false); 60Flight::set('flight.content_length', false); 61 62Flight::set('standardParams', [ 63 'siteTitle' => SITE_TITLE, 64 'themes' => THEMES, 65 'fonts' => FONTS, 66 'setTheme' => array_key_exists('sbs_theme', $_COOKIE) ? $_COOKIE['sbs_theme'] : DEFAULT_THEME, 67 'setFont' => array_key_exists('sbs_font', $_COOKIE) ? $_COOKIE['sbs_font'] : DEFAULT_FONT, 68 'userAuth' => Flight::get('userAuth'), 69 'favFeeds' => $favoriteFeeds, 70 'pages' => PAGES, 71 'links' => LINKS, 72 'ogdomain' => SITE_DOMAIN 73]); 74 75Flight::route('/', function () { 76 $bskyToucher = new BskyToucher(); 77 $posts = $bskyToucher->getFeed(Flight::get('frontpageFeed')); 78 $feedInfo = $bskyToucher->getFeedInfo(Flight::get('frontpageFeed')); 79 $latte = new Latte\Engine; 80 $latte->render('./templates/home.latte', array_merge(Flight::get('standardParams'), [ 81 'mainClass' => 'home feed', 82 'feedInfo' => $feedInfo, 83 'posts' => array_map(function ($p) { return $p->post; }, $posts->feed), 84 'cursor' => $posts->cursor, 85 'feedAtUri' => FRONTPAGE_FEED, 86 'ogtitle' => SITE_TITLE, 87 'ogdesc' => SITE_DESC, 88 'ogimage' => '', 89 'ogurl' => SITE_DOMAIN.'/' 90 ])); 91}); 92 93Flight::route('/u/@handle:[a-z0-9\.]+/@rkey:[a-z0-9]+', function (string $handle, string $rkey): void { 94 $bskyToucher = new BskyToucher(); 95 $did = $bskyToucher->resolveHandle($handle); 96 $userInfo = $bskyToucher->getUserInfo($handle); 97 $atUri = 'at://'.$did.'/app.bsky.feed.post/'.$rkey; 98 $latte = new Latte\Engine; 99 $latte->render('./templates/single.latte', array_merge(Flight::get('standardParams'), [ 100 'mainClass' => 'post', 101 'post' => $atUri, 102 'displayName' => $userInfo->displayName, 103 'handle' => $handle, 104 'ogtitle' => SITE_TITLE." | ".$userInfo->displayName." (@".$handle.")", 105 'ogdesc' => '', //$post->content, 106 'ogimage' => '', //getPostOgImage($post), 107 'ogurl' => SITE_DOMAIN.'/u/'.$handle.'/'.$rkey 108 ])); 109}); 110 111Flight::route('/u/@handle:[a-z0-9\.]+(/@tab:[a-z]+)', function (string $handle, ?string $tab): void { 112 $bskyToucher = new BskyToucher(); 113 $user = $bskyToucher->getUserInfo($handle, 'handle'); 114 $posts = $bskyToucher->getUserPosts($user->did); 115 $latte = new Latte\Engine; 116 $latte->render('./templates/profile.latte', array_merge(Flight::get('standardParams'), [ 117 'mainClass' => 'profile', 118 'handle' => $handle, 119 'posts' => array_map(function ($p) { return $p->uri; }, $posts->records), 120 'cursor' => $posts->cursor, 121 'user' => $user, 122 'ogtitle' => SITE_TITLE." | ".$user->displayName." (@".$user->handle.")", 123 'ogdesc' => $user->description, 124 'ogimage' => $user->avatar, 125 'ogurl' => SITE_DOMAIN.'/u/'.$user->handle.'/' 126 ])); 127}); 128 129Flight::route('/f/@did:did:plc:[0-9a-z]+/@name:[a-z0-9\-\_]+', function (string $did, string $name): void { 130 $bskyToucher = new BskyToucher(); 131 $feedUrl = "at://".$did."/app.bsky.feed.generator/".$name; 132 $feedInfo = $bskyToucher->getFeedInfo($feedUrl); 133 $creatorInfo = $bskyToucher->getUserInfo($feedInfo->creatorDid, 'did'); 134 $posts = $bskyToucher->getFeed($feedUrl); 135 $latte = new Latte\Engine; 136 $latte->render('./templates/feed.latte', array_merge(Flight::get('standardParams'), [ 137 'mainClass' => 'feed', 138 'posts' => array_map(function ($p) { return $p->post; }, $posts->feed), 139 'cursor' => '', 140 'feedName' => $feedInfo->title, 141 'feedAvatar' => $feedInfo->avatar, 142 'feedDescription' => $feedInfo->description, 143 'feedAtUri' => $feedUrl, 144 'feedAuthorName' => $creatorInfo->displayName, 145 'feedAuthorHandle' => $creatorInfo->handle, 146 'feedAuthorDid' => $creatorInfo->did, 147 'feedAuthorPds' => $creatorInfo->pds, 148 'ogtitle' => SITE_TITLE." | ".$feedInfo->title, 149 'ogdesc' => $feedInfo->description, 150 'ogimage' => $feedInfo->avatar, 151 'ogurl' => SITE_DOMAIN.'/f/'.$did.'/'.$name 152 ])); 153}); 154 155Flight::route('/s', function (): void { 156 $latte = new Latte\Engine; 157 $latte->render('./templates/search.latte', array_merge(Flight::get('standardParams'), [ 158 'mainClass' => 'search', 159 'params' => $_GET, 160 'ogtitle' => SITE_TITLE." | search".(array_key_exists('s', $_GET) ? ': '.$_GET['s'] : ''), 161 'ogdesc' => SITE_DESC, 162 'ogimage' => '', 163 'ogurl' => SITE_DOMAIN.'/u/'.$handle.'/'.$rkey 164 ])); 165}); 166 167Flight::route('GET /login', function(): void { 168 $latte = new Latte\Engine; 169 $latte->render('./templates/login.latte', array_merge(Flight::get('standardParams'), [ 170 'mainClass' => 'form', 171 'ogtitle' => SITE_TITLE." | login", 172 'ogdesc' => SITE_DESC, 173 'ogimage' => '', 174 'ogurl' => SITE_DOMAIN.'/login' 175 ])); 176}); 177 178Flight::route('POST /login', function(): void { 179 // whatever stupid token exchange dance needs to happen to direct them to oauth 180}); 181 182Flight::route('/createaccount', function(): void { 183 $latte = new Latte\Engine; 184 $latte->render('./templates/create.latte', array_merge(Flight::get('standardParams'), [ 185 'mainClass' => 'form', 186 'ogtitle' => SITE_TITLE." | create account", 187 'ogdesc' => SITE_DESC, 188 'ogimage' => '', 189 'ogurl' => SITE_DOMAIN.'/createaccount' 190 ])); 191}); 192 193Flight::route('/api/post/@did/@rkey', function (string $did, string $rkey): void { 194 $bskyToucher = new BskyToucher(); 195 $ret = $bskyToucher->getPost($did, $rkey, true); 196 if ($ret) { 197 $latte = new Latte\Engine; 198 $latte->render('./templates/_partials/post.latte', array_merge(Flight::get('standardParams'), [ 199 'post' => $ret 200 ])); 201 die(1); 202 } 203 Flight::json(['error' => 'malformed response or bad vibes']); 204}); 205 206Flight::route('/api/likes/@did/@rkey', function (string $did, string $rkey): void { 207 $bskyToucher = new BskyToucher(); 208 $ret = $bskyToucher->getLikes('at://'.$did.'/app.bsky.feed.post/'.$rkey); 209 if ($ret) { 210 $latte = new Latte\Engine; 211 $output = $latte->renderToString('./templates/_partials/interaction_list.latte', array_merge(Flight::get('standardParams'), [ 212 'interactions' => $ret->records 213 ])); 214 $ret->rendered = $output; 215 Flight::json($ret); 216 } 217}); 218 219Flight::route('/api/reposts/@did/@rkey', function (string $did, string $rkey): void { 220 $bskyToucher = new BskyToucher(); 221 $ret = $bskyToucher->getReposts('at://'.$did.'/app.bsky.feed.post/'.$rkey); 222 if ($ret) { 223 $latte = new Latte\Engine; 224 $output = $latte->renderToString('./templates/_partials/interaction_list.latte', array_merge(Flight::get('standardParams'), [ 225 'interactions' => $ret->records 226 ])); 227 $ret->rendered = $output; 228 Flight::json($ret); 229 } 230}); 231 232Flight::route('/api/replies/@did/@rkey', function (string $did, string $rkey): void { 233 $bskyToucher = new BskyToucher(); 234 $ret = $bskyToucher->getReplies('at://'.$did.'/app.bsky.feed.post/'.$rkey); 235 if ($ret) { 236 $latte = new Latte\Engine; 237 $output = $latte->renderToString('./templates/_partials/feedPosts.latte', array_merge(Flight::get('standardParams'), [ 238 'total' => $ret->total, 239 'cursor' => $ret->cursor, 240 'posts' => array_map(function($p) { return $p->uri; }, $ret->records) 241 ])); 242 $ret->rendered = $output; 243 Flight::json($ret); 244 } 245}); 246 247Flight::route('/api/quotes/@did/@rkey', function (string $did, string $rkey): void { 248 $bskyToucher = new BskyToucher(); 249 $ret = $bskyToucher->getLikes('at://'.$did.'/app.bsky.feed.post/'.$rkey); 250 if ($ret) { 251 $latte = new Latte\Engine; 252 $output = $latte->renderToString('./templates/_partials/interaction_list.latte', array_merge(Flight::get('standardParams'), [ 253 'interactions' => $ret->records 254 ])); 255 $ret->rendered = $output; 256 Flight::json($ret); 257 } 258}); 259 260Flight::route('/api/user/@handle', function (string $handle): void { 261 $bskyToucher = new BskyToucher(); 262 $ret = $bskyToucher->getUserInfo($handle); 263 if ($ret) { 264 Flight::json($ret); 265 die(1); 266 } 267 Flight::json(['error' => 'malformed response or bad vibes']); 268}); 269 270Flight::route('/api/feed/@did/@rkey', function (string $did, string $rkey): void { 271 $bskyToucher = new BskyToucher(); 272}); 273 274Flight::route('/@page', function (string $page): void { 275 $latte = new Latte\Engine; 276 $converter = new CommonMarkConverter(); 277 $md = $converter->convert(file_get_contents('./pages/'.$page.'.md')); 278 $latte->render('./templates/page.latte', array_merge(Flight::get('standardParams'), [ 279 'mainClass' => 'page', 280 'content' => $md, 281 'ogtitle' => SITE_TITLE." | ".$page, 282 'ogdesc' => SITE_DESC, 283 'ogimage' => '', 284 'ogurl' => SITE_DOMAIN.'/'.$page 285 ])); 286}); 287 288Flight::start(); 289 290?>