+ if (req.method == .GET) {
+ try write_start(&res);
+ try write_header(&res, logged_in);
+
+ const txn = try env.txn();
+ defer txn.abort();
+
+ if (std.mem.startsWith(u8, req.target, "/user/")) {
+ const username = req.target[6..req.target.len];
+
+ const user_ids = try Db.user_ids(txn);
+ if (user_ids.get(try Username.fromSlice(username))) |user_id| {
+ const users = try Db.users(txn);
+ const user = try users.get(user_id);
+
+ const following = try user.following.open(txn);
+ const followers = try user.followers.open(txn);
+
+ try res.write(
+ \\<a href="/user/{s}">{s}</a>
+ , .{
+ user.name.constSlice(), user.display_name.constSlice(),
+ });
+ if (logged_in != null and user_id != logged_in.?.user.id) {
+ if (try followers.has(logged_in.?.user.id)) {
+ try html_form(&res, "/follow", .{}, .{
+ .{ "type=\"hidden\" name=\"user_id\" value=\"{x}\"", .{@intFromEnum(user_id)} },
+ \\type="submit" value="Unfollow"
+ });
+ } else {
+ try html_form(&res, "/follow", .{}, .{
+ .{ "type=\"hidden\" name=\"user_id\" value=\"{x}\"", .{@intFromEnum(user_id)} },
+ \\type="submit" value="Follow"
+ });
+ }
+ }
+ try res.write(
+ \\ <a href="/following/{s}">{} following</a>
+ \\ <a href="/followers/{s}">{} followers</a>
+ , .{
+ user.name.constSlice(), following.len(),
+ user.name.constSlice(), followers.len(),
+ });
+
+ try write_posts(&res, txn, logged_in, user);
+ } else |err| {
+ try res.write(
+ \\<p>User not found [{}]</p>
+ , .{err});
+ }
+ } else if (std.mem.startsWith(u8, req.target, "/following/")) {
+ const username = req.target[11..req.target.len];
+
+ const user_ids = try Db.user_ids(txn);
+ if (user_ids.get(try Username.fromSlice(username))) |user_id| {
+ const users = try Db.users(txn);
+ const user = try users.get(user_id);
+
+ const following = try user.following.open(txn);
+ var it = following.iterator();
+
+ try res.write(
+ \\<h2><a href="/user/{s}">{s}</a> follows:</h2>
+ , .{ user.name.constSlice(), user.display_name.constSlice() });
+
+ while (it.next()) |kv| {
+ const following_user = try users.get(kv.key);
+
+ try res.write(
+ \\<a href="/user/{s}">{s}</a><br />
+ , .{ following_user.name.constSlice(), following_user.display_name.constSlice() });
+ }
+ } else |err| {
+ try res.write(
+ \\<p>User not found [{}]</p>
+ , .{err});
+ }
+ } else if (std.mem.startsWith(u8, req.target, "/followers/")) {
+ const username = req.target[11..req.target.len];
+
+ const user_ids = try Db.user_ids(txn);
+ if (user_ids.get(try Username.fromSlice(username))) |user_id| {
+ const users = try Db.users(txn);
+ const user = try users.get(user_id);
+
+ const followers = try user.followers.open(txn);
+ var it = followers.iterator();
+
+ try res.write(
+ \\<h2><a href="/user/{s}">{s}</a> followers:</h2>
+ , .{ user.name.constSlice(), user.display_name.constSlice() });
+
+ while (it.next()) |kv| {
+ const follower_user = try users.get(kv.key);
+
+ try res.write(
+ \\<a href="/user/{s}">{s}</a><br />
+ , .{ follower_user.name.constSlice(), follower_user.display_name.constSlice() });
+ }
+ } else |err| {
+ try res.write(
+ \\<p>User not found [{}]</p>
+ , .{err});
+ }
+ } else if (std.mem.startsWith(u8, req.target, "/post/")) {
+ const post_id_str = req.target[6..req.target.len];
+ const post_id = try parse_enum(PostId, post_id_str, 16);
+
+ try write_post(&res, txn, logged_in, post_id, .Yes);
+ } else if (std.mem.startsWith(u8, req.target, "/quotes/")) {
+ const post_id_str = req.target[8..req.target.len];
+ const post_id = try parse_enum(PostId, post_id_str, 16);
+
+ const posts = try Db.posts(txn);
+ const post = try posts.get(post_id);
+
+ const quotes_view = try post.quotes.open(txn);
+ var it = quotes_view.iterator();
+ while (it.next()) |kv| {
+ try write_post(&res, txn, logged_in, kv.key, .Once);
+ try res.write("<br />", .{});
+ }
+ } else if (std.mem.eql(u8, req.target, "/post")) {