at main 6.8 kB view raw
1using AltBot.Core.Models; 2using AltBot.Data; 3using AltBot.ServiceDefaults; 4using Duende.IdentityModel.OidcClient; 5using idunno.AtProto; 6using idunno.Bluesky; 7using idunno.Bluesky.Actor; 8using idunno.Bluesky.Feed; 9using idunno.Bluesky.Graph; 10using idunno.Bluesky.Record; 11using Microsoft.EntityFrameworkCore; 12using Cid = AltBot.Core.Models.Cid; 13using Did = AltBot.Core.Models.Did; 14using Like = idunno.Bluesky.Record.Like; 15 16namespace AltBot.Api; 17 18public static class StartupExtensions 19{ 20 // DTOs 21 record SubscriberCreate(Did Did, string? Handle); 22 record SubscriberUpdate(string? Handle, bool Active, string Rkey); 23 record PostCreate(Did Did, Cid Cid, string Rkey); 24 25 public static void MapApplicationEndpoints(this WebApplication app) 26 { 27 // Subscribers endpoints 28 app.MapGet("/subscribers", async (DataContext db) => 29 { 30 var agent = new BlueskyAgent(); 31 32 33 var likesResult = await agent.GetLikes( 34 new AtUri("at://did:plc:yb2gz6yxpebbzlundrrfkv4d/app.bsky.labeler.service/self")); 35 36 37 if (!likesResult.Succeeded || likesResult.Result.Count == 0) 38 { 39 return Results.NotFound(); 40 } 41 42 var list = new List<ProfileView>(); 43 list.AddRange(likesResult.Result.Select(x => x.Actor)); 44 45 while (!string.IsNullOrEmpty(likesResult.Result.Cursor)) 46 { 47 likesResult = await agent.GetLikes( 48 new AtUri("at://did:plc:yb2gz6yxpebbzlundrrfkv4d/app.bsky.labeler.service/self"), 49 cursor: likesResult.Result.Cursor); 50 51 list.AddRange(likesResult.Result.Select(x => x.Actor)); 52 } 53 54 var x = list.Select(x => $"{x.Handle.Value} - {x.Did}"); 55 56 return Results.Ok(x); 57 58 59 60 //var followersResult = await agent.GetFollowers(AtIdentifier.Create("did:plc:yb2gz6yxpebbzlundrrfkv4d")); 61 62 //var list = new List<Followers>(); 63 64 //if (followersResult.Succeeded && followersResult.Result.Count > 0) 65 //{ 66 67 //} 68 69 //var sfsda = new List<Followers>(); 70 71 //do 72 //{ 73 // var results = followers.Result.Select(follow => $"{follow.Handle.Value} - {follow.Did}"); 74 //} 75 //while (!string.IsNullOrEmpty(followers.Result.Cursor)) 76 77 78 79 //return Results.Ok(results); 80 81 82 83 var subscribers = await db.Subscribers 84 .Select(s => new 85 { 86 s.Did, 87 s.Handle, 88 s.Active, 89 s.SeenAt, 90 s.Label 91 }) 92 .ToListAsync(); 93 return Results.Ok(subscribers); 94 }) 95 .WithName("GetSubscribers") 96 .WithOpenApi(); 97 98 app.MapGet("/subscribers/{did}", async (Did did, DataContext db) => 99 { 100 var subscriber = await db.Subscribers.FirstOrDefaultAsync(s => s.Did == did); 101 return subscriber == null ? Results.NotFound() : Results.Ok(subscriber); 102 }) 103 .WithName("GetSubscriber") 104 .WithOpenApi(); 105 106 app.MapGet("subscribers/{did}/posts", async (Did did, DataContext db) => 107 { 108 var posts = await db.Posts 109 .Where(x => x.Did == did) 110 .Select(p => new 111 { 112 p.Cid, 113 p.Rkey, 114 p.SeenAt 115 }) 116 .ToListAsync(); 117 return Results.Ok(posts); 118 }) 119 .WithName("GetPosts") 120 .WithOpenApi(); 121 122 app.MapPost("/subscribers", async (SubscriberCreate request, DataContext db) => 123 { 124 if (await db.Subscribers.AnyAsync(s => s.Did == request.Did)) 125 { 126 return Results.Conflict("Subscriber already exists"); 127 } 128 129 var subscriber = new Subscriber 130 { 131 Did = request.Did, 132 Handle = request.Handle, 133 Active = true, 134 SeenAt = DateTime.UtcNow 135 }; 136 137 db.Subscribers.Add(subscriber); 138 await db.SaveChangesAsync(); 139 140 return Results.Created($"/subscribers/{subscriber.Did}", subscriber); 141 }) 142 .WithName("CreateSubscriber") 143 .WithOpenApi(); 144 145 app.MapPut("/subscribers/{did}", async (Did did, SubscriberUpdate request, DataContext db) => 146 { 147 var subscriber = await db.Subscribers.FindAsync(did); 148 if (subscriber == null) 149 { 150 return Results.NotFound(); 151 } 152 153 subscriber.Handle = request.Handle ?? subscriber.Handle; 154 subscriber.Active = request.Active; 155 subscriber.Rkey = request.Rkey; 156 157 await db.SaveChangesAsync(); 158 return Results.Ok(subscriber); 159 }) 160 .WithName("UpdateSubscriber") 161 .WithOpenApi(); 162 163 app.MapDelete("/subscribers/{did}", async (Did did, DataContext db) => 164 { 165 var subscriber = await db.Subscribers.FindAsync(did); 166 if (subscriber == null) 167 { 168 return Results.NotFound(); 169 } 170 171 db.Subscribers.Remove(subscriber); 172 await db.SaveChangesAsync(); 173 174 return Results.NoContent(); 175 }) 176 .WithName("DeleteSubscriber") 177 .WithOpenApi(); 178 179 180 // Posts endpoints 181 app.MapPost("/posts", async (PostCreate request, DataContext db) => 182 { 183 if (!await db.Subscribers.AnyAsync(s => s.Did == request.Did)) 184 { 185 return Results.NotFound("Subscriber not found"); 186 } 187 188 var post = new ImagePost 189 { 190 Did = request.Did, 191 Cid = request.Cid, 192 Rkey = request.Rkey, 193 SeenAt = DateTime.UtcNow 194 }; 195 196 db.Posts.Add(post); 197 await db.SaveChangesAsync(); 198 199 return Results.Created($"/subscribers/{post.Did}/posts/{post.Cid}", post); 200 }) 201 .WithName("CreatePost") 202 .WithOpenApi(); 203 204 app.MapDelete("/posts/{did}/{cid}/{rKey}", async (Did did, Cid cid, string rKey, DataContext db) => 205 { 206 var post = await db.Posts.FindAsync(did, cid); 207 if (post == null) 208 { 209 return Results.NotFound(); 210 } 211 212 db.Posts.Remove(post); 213 await db.SaveChangesAsync(); 214 215 return Results.NoContent(); 216 }) 217 .WithName("DeletePost") 218 .WithOpenApi(); 219 220 app.MapDefaultEndpoints(); 221 222 app.Run(); 223 } 224}