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?>