diff --git a/src/AppViewLite.Web/ApiCompat/AppBskyActor.cs b/src/AppViewLite.Web/ApiCompat/AppBskyActor.cs index afcde9b3..a0328f99 100644 --- a/src/AppViewLite.Web/ApiCompat/AppBskyActor.cs +++ b/src/AppViewLite.Web/ApiCompat/AppBskyActor.cs @@ -27,6 +27,13 @@ public async Task GetProfile(string actor) return profile.ToApiCompatProfileDetailed().ToJsonResponse(); } + [HttpGet("app.bsky.actor.getProfiles")] + public async Task GetProfiles([FromQuery]string[] actors) + { + var profiles = await Task.WhenAll(actors.Select(did => apis.GetFullProfileAsync(did, ctx, 0))); + return new GetProfilesOutput(profiles.Select(p => p.ToApiCompatProfileDetailed()).ToList()).ToJsonResponse(); + } + [HttpGet("app.bsky.actor.searchActorsTypeahead")] public Task SearchActorsTypeahead(string q, int limit) { diff --git a/src/AppViewLite.Web/ApiCompat/AppBskyFeed.cs b/src/AppViewLite.Web/ApiCompat/AppBskyFeed.cs index c623eb71..fab4b594 100644 --- a/src/AppViewLite.Web/ApiCompat/AppBskyFeed.cs +++ b/src/AppViewLite.Web/ApiCompat/AppBskyFeed.cs @@ -99,6 +99,32 @@ public async Task GetFeedGenerator(string feed) }.ToJsonResponse(); } + [HttpGet("app.bsky.feed.getFeedGenerators")] + public async Task GetFeedGenerators([FromQuery]string[] feeds) + { + var feedGenerators = await Task.WhenAll(feeds.Select(async feed => { + var uri = await apis.ResolveUriAsync(feed, ctx); + var feedDid = uri.Did!.Handler!; + var feedRKey = uri.Rkey; + try + { + var generator = await apis.GetFeedGeneratorAsync(feedDid, feedRKey, ctx); + var creator = await apis.GetProfileAsync(feedDid, ctx); + return generator.ToApiCompatGeneratorView(creator); + } + catch (Exception ex) + { + Console.Error.WriteLine("Could not check with PDS if account is actually still deactivated", ex); + return null; + } + })); + + return new GetFeedGeneratorsOutput + { + Feeds = feedGenerators.Where(f => f != null).ToList(), + }.ToJsonResponse(); + } + [HttpGet("app.bsky.feed.getFeed")] public async Task GetFeed(string feed, int limit, string? cursor) { diff --git a/src/AppViewLite.Web/ApiCompat/AppBskyGraph.cs b/src/AppViewLite.Web/ApiCompat/AppBskyGraph.cs index 29196f27..c58f7db9 100644 --- a/src/AppViewLite.Web/ApiCompat/AppBskyGraph.cs +++ b/src/AppViewLite.Web/ApiCompat/AppBskyGraph.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using AppViewLite; #pragma warning disable CS1998 @@ -54,6 +55,16 @@ public async Task GetActorStarterPacks(string actor, string? cursor, in StarterPacks = [] }.ToJsonResponse(); } + [HttpGet("app.bsky.graph.getList")] + public async Task GetActorStarterPacks(string list, string? cursor, int? limit) + { + // stub empty for now + return new FishyFlip.Lexicon.App.Bsky.Graph.GetListOutput + { + List = ApiCompatUtils.ToApiCompatListView(), + Items = [ApiCompatUtils.ToApiCompatListItemView()], + }.ToJsonResponse(); + } } } diff --git a/src/AppViewLite.Web/Program.cs b/src/AppViewLite.Web/Program.cs index 99c62f7a..1f480662 100644 --- a/src/AppViewLite.Web/Program.cs +++ b/src/AppViewLite.Web/Program.cs @@ -387,7 +387,7 @@ await PluggableProtocol.RetryInfiniteLoopAsync("PlcDirectory", async ct => var handler = new JwtSecurityTokenHandler(); var unverifiedJwtToken = authorization.Substring(7).Trim(); var parsedUnverifiedJwtToken = handler.ReadJwtToken(unverifiedJwtToken); - var unverifiedDid = parsedUnverifiedJwtToken.Subject; + var unverifiedDid = parsedUnverifiedJwtToken.Issuer; return unverifiedJwtToken + "=" + unverifiedDid; } return null; diff --git a/src/AppViewLite/ApiCompatUtils.cs b/src/AppViewLite/ApiCompatUtils.cs index d9d3b4b2..c33bed0c 100644 --- a/src/AppViewLite/ApiCompatUtils.cs +++ b/src/AppViewLite/ApiCompatUtils.cs @@ -1,6 +1,7 @@ using AppViewLite.Models; using FishyFlip.Lexicon; using FishyFlip.Lexicon.App.Bsky.Actor; +using FishyFlip.Lexicon.App.Bsky.Graph; using FishyFlip.Lexicon.App.Bsky.Embed; using FishyFlip.Lexicon.App.Bsky.Feed; using FishyFlip.Lexicon.App.Bsky.Richtext; @@ -306,6 +307,55 @@ public static GeneratorView ToApiCompatGeneratorView(this BlueskyFeedGenerator f }; } + public static ListView ToApiCompatListView() + { + return new ListView + { + Cid = GetSyntheticCid(new FishyFlip.Models.ATUri("at://did:web:bad-example.com/com.example.bad/33333")), + Creator = new ProfileView + { + DisplayName = "[stub]", + Labels = [], + CreatedAt = DummyDate, + Avatar = "https://bad-example.com/stub", + Did = new FishyFlip.Models.ATDid("did:plc:hdhoaan3xa3jiuq4fg4mefid"), + Handle = new FishyFlip.Models.ATHandle("stub.bad-example.com"), + Viewer = new FishyFlip.Lexicon.App.Bsky.Actor.ViewerState + { + Muted = false, + BlockedBy = false, + }, + }, + ListItemCount = 0, + Name = "[stub]", + Purpose = "app.bsky.graph.defs#curatelist", + Uri = new FishyFlip.Models.ATUri("at://did:web:bad-example.com/com.example.bad/33333"), + IndexedAt = DummyDate, + }; + } + + public static ListItemView ToApiCompatListItemView() + { + return new FishyFlip.Lexicon.App.Bsky.Graph.ListItemView + { + Subject = new FishyFlip.Lexicon.App.Bsky.Actor.ProfileView + { + DisplayName = "[stub]", + Labels = [], + CreatedAt = DummyDate, + Avatar = "https://bad-example.com/stub", + Did = new FishyFlip.Models.ATDid("did:plc:hdhoaan3xa3jiuq4fg4mefid"), + Handle = new FishyFlip.Models.ATHandle("stub.bad-example.com"), + Viewer = new FishyFlip.Lexicon.App.Bsky.Actor.ViewerState + { + Muted = false, + BlockedBy = false, + }, + }, + Uri = new FishyFlip.Models.ATUri("at://did:web:bad-example.com/com.example.bad/33333"), + }; + } + } }