Skip to content

Commit a86180b

Browse files
committed
Add support for verification, VerificationView is added to ProfileViewBasic, ProfileView and ProfileViewDetailed.
Document verification on profiles
1 parent 11c54a8 commit a86180b

File tree

19 files changed

+465
-21
lines changed

19 files changed

+465
-21
lines changed

docs/docs/labels.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ the agent has authenticated.
1414
using Bluesky.Agent;
1515

1616
Preferences userPreferences;
17-
AtProtoHttpResult<Preferences> userPreferencesResult = await agent.GetPreferences();
17+
var userPreferencesResult = await agent.GetPreferences();
1818
if (userPreferencesResult.Succeeded)
1919
{
2020
userPreferences = userPreferencesResult.Result;
@@ -53,6 +53,9 @@ foreach (Notification notification in notificationsList.Result)
5353
}
5454
```
5555

56+
Many APIs will take a `subscribedLabelers` parameters, including `GetProfile`, `GetSuggestions`, `SearchActors`, `GetFeed`, `GetTimeline` and so on.
57+
It is recommended you cache the user's subscribed labelers and provide them to any API that accepts them.
58+
5659
By default idunno.Bluesky will return the Bluesky moderation labeler as part of a user's labeler subscriptions. This can be controlled
5760
with the `includeBlueskyModerationLabeler` parameter on the `GetPreferences` method.
5861

docs/docs/profiles.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# <a name="profileViewing">Viewing a user's profile</a>
2+
3+
## <a name="gettingAProfile">Getting a profile</a>
4+
5+
To retrieve a user's profile use `agent.GetProfile()`, with either a `Handle` or `Did`.
6+
7+
```c#
8+
var profileViewResult = await agent.GetProfile(new Handle("blowdart.me"), cancellationToken: cancellationToken);
9+
```
10+
11+
A user's `ProfileView` includes their `Did`, `Handle`, display name, description, avatar etc. It also includes their follower, following and posts count, information
12+
on the number of lists, starter packs and feed generators they have created, as well who they will accept direct messages from.
13+
14+
The profile view also includes a `Viewer` property which describes the relationship between the user that requested the profile and the user the profile refers to,
15+
including properties such as `Muted`, when the user requesting the profile has muted the user the profile refers to, as well as `BlockedBy`, `Following`, `FollowedBy`
16+
and other properties that will effect how you should render the profile, or the item in a view that also contains the author profile, to the requesting user.
17+
18+
Feeds, timelines etc. will also contain a `ProfileViewBasic`, `ProfileView` or `ProfileViewDetailed`, depending on the view or API definition.
19+
20+
## <a name="profileVerification">Profile labels</a>
21+
22+
Profile views can include labels from labelers. Please see [Labels](labels.md) for more information.
23+
24+
## <a name="profileVerification">Profile verification</a>
25+
26+
Bluesky supports a composible verification system where various organications will verify accounts, for example the New York Times may verify their reporters. The
27+
`Verification` property holds the verification status for a user, and a list of the verifiers who have verified it. The `VerifiedStatus` can be valid, invalid, none or unknown,
28+
you can use this to decide if you want to display an indicator of the status to your users.
29+

docs/docs/sourceGeneration.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,23 @@ and passing in the `JsonSerializerOptions.Default` from your code where you have
5555

5656
### Annotating your own classes for json source generation
5757

58-
The reference `AtProto` implementation is quite laissez faire about where the `$type` property appears in serialized JSON. Make sure that the `AllowOutOfOrderMetadataProperties` is set
59-
to `true`` in your `JsonSourceGenerationOptions` on your `SourceGenerationContext` class. For example,
58+
The reference `AtProto` implementation is quite laissez faire about where the `$type` property appears in serialized JSON. Make sure that the
59+
`AllowOutOfOrderMetadataProperties` is set to `true`` in your `JsonSourceGenerationOptions` on your `SourceGenerationContext` class. For example,
6060

6161
```c#
6262
[JsonSourceGenerationOptions(
6363
AllowOutOfOrderMetadataProperties = true,
6464
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
6565
IgnoreReadOnlyProperties = false,
66-
GenerationMode = JsonSourceGenerationMode.Metadata,
6766
NumberHandling = JsonNumberHandling.AllowReadingFromString,
6867
PropertyNameCaseInsensitive = true,
6968
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
7069
WriteIndented = false,
7170
UseStringEnumConverter = true)]
7271
```
7372

74-
You must also ensure both your record classes (those deriving from `AtProtoRecord`) and your record value classes (those deriving from `AtProtoRecordValue`) are marked as `JsonSerializable` in your
75-
`JsonSerializerContext`. Additionally you must also add the `AtProtoRecord<YourRecordValue>` class to the context.
73+
You must also ensure both your record classes (those deriving from `AtProtoRecord`) and your record value classes (those deriving from `AtProtoRecordValue`) are marked
74+
as `JsonSerializable` in your `JsonSerializerContext`. Additionally you must also add the `AtProtoRecord<YourRecordValue>` class to the context.
7675

7776
For example, if you have a custom `AtProtoRecordValue` and corresponding `AtProtoRecord<TRecordValue>` it should look something like the following.
7877

@@ -93,7 +92,6 @@ For example, if you have a custom `AtProtoRecordValue` and corresponding `AtProt
9392
AllowOutOfOrderMetadataProperties = true,
9493
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
9594
IgnoreReadOnlyProperties = false,
96-
GenerationMode = JsonSourceGenerationMode.Metadata,
9795
NumberHandling = JsonNumberHandling.AllowReadingFromString,
9896
PropertyNameCaseInsensitive = true,
9997
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
@@ -119,3 +117,6 @@ Native AOT has benefits:
119117
* Reduced memory usage: Native AOT apps can show reduced memory demands, depending on the work it does.
120118

121119
If you wish to use AOT with your own classes you must enable JSON Source Generation for your `AtProtoRecordValue` and `AtProtoRecord` records and follow the guidance above.
120+
121+
> [!WARNING]
122+
> Trimming is not currently supported due to a bug in the [linker](https://github.com/dotnet/runtime/issues/114307).

docs/docs/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ items:
2626

2727
- name: Users
2828
items:
29+
- name: Viewing user profiles
30+
href: profiles.md
2931
- name: User Preferences
3032
href: userPreferences.md
3133
- name: Conversations & Messages

history.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Version History
22

3+
## 0.6.0
4+
5+
### Features
6+
7+
#### idunno.Bluesky
8+
9+
* Add support for verification, `VerificationView` is added to `ProfileViewBasic`, `ProfileView` and `ProfileViewDetailed`.
10+
311
## 0.5.0
412

513
### Bug Fixes

idunno.Bluesky.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{E2B63F0A-9
137137
docs\docs\notifications.md = docs\docs\notifications.md
138138
docs\docs\posting.md = docs\docs\posting.md
139139
docs\docs\profileEditing.md = docs\docs\profileEditing.md
140+
docs\docs\profiles.md = docs\docs\profiles.md
140141
docs\docs\savingAndRestoringAuthentication.md = docs\docs\savingAndRestoringAuthentication.md
141142
docs\docs\sourceGeneration.md = docs\docs\sourceGeneration.md
142143
docs\docs\threadGatesAndPostGates.md = docs\docs\threadGatesAndPostGates.md

samples/Samples.ConsoleShell/Program.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77

88
using Microsoft.Extensions.Logging;
99

10-
using idunno.Bluesky;
11-
1210
using Samples.Common;
11+
1312
using idunno.AtProto;
14-
using idunno.AtProto.Repo;
15-
using idunno.Bluesky.Moderation;
13+
using idunno.Bluesky;
1614

1715
namespace Samples.ConsoleShell
1816
{
@@ -35,7 +33,7 @@ static async Task PerformOperations(string? handle, string? password, string? au
3533
ArgumentException.ThrowIfNullOrEmpty(password);
3634

3735
// Uncomment the next line to route all requests through Fiddler Everywhere
38-
proxyUri = new Uri("http://localhost:8866");
36+
// proxyUri = new Uri("http://localhost:8866");
3937

4038
// Uncomment the next line to route all requests through Fiddler Classic
4139
// proxyUri = new Uri("http://localhost:8888");

src/idunno.Bluesky/Actor/ProfileView.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public record ProfileView : ProfileViewBasic
2626
/// <param name="createdAt">The date and time the actor was created.</param>
2727
/// <param name="viewer">Metadata about the current user's relationship to the actor.</param>
2828
/// <param name="labels">Labels applied to the actor.</param>
29+
/// <param name="verification">The <see cref="VerificationState"/> of the actor, if any.</param>
2930
/// <exception cref="ArgumentNullException">Thrown when <paramref name="did"/> or <paramref name="handle"/> are null.</exception>
3031
/// <exception cref="ArgumentOutOfRangeException">
3132
/// Thrown when <paramref name="displayName"/> is not null and has a character length greater than 640 or a grapheme length greater than 64.
@@ -41,7 +42,9 @@ public ProfileView(
4142
ActorViewerState? viewer,
4243
IReadOnlyCollection<Label>? labels,
4344
DateTimeOffset? indexedAt,
44-
DateTimeOffset? createdAt) : base(did, handle, displayName, avatar, associated, viewer, labels, createdAt)
45+
DateTimeOffset? createdAt,
46+
VerificationState? verification
47+
) : base(did, handle, displayName, avatar, associated, viewer, labels, createdAt, verification)
4548
{
4649
Description = description;
4750
IndexedAt = indexedAt;

src/idunno.Bluesky/Actor/ProfileViewBasic.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public record ProfileViewBasic : View
3030
/// <param name="viewer">Metadata about the current user's relationship to the actor.</param>
3131
/// <param name="labels">Labels applied to the actor.</param>
3232
/// <param name="createdAt">The date and time the actor was created.</param>
33+
/// <param name="verification">The <see cref="VerificationState"/> of the actor, if any.</param>
3334
/// <exception cref="ArgumentNullException">Thrown when <paramref name="did"/> or <paramref name="handle"/> are null.</exception>
3435
/// <exception cref="ArgumentOutOfRangeException">
3536
/// Thrown when <paramref name="displayName"/> is not null and has a character length greater than 640 or a grapheme length greater than 64.
@@ -43,7 +44,8 @@ public ProfileViewBasic(
4344
ProfileAssociated? associated,
4445
ActorViewerState? viewer,
4546
IReadOnlyCollection<Label>? labels,
46-
DateTimeOffset? createdAt)
47+
DateTimeOffset? createdAt,
48+
VerificationState? verification)
4749
{
4850
ArgumentNullException.ThrowIfNull(did);
4951
ArgumentNullException.ThrowIfNull(handle);
@@ -61,6 +63,7 @@ public ProfileViewBasic(
6163
Associated = associated;
6264
Viewer = viewer;
6365
CreatedAt = createdAt;
66+
Verification = verification;
6467

6568
if (labels is null)
6669
{
@@ -107,21 +110,26 @@ public ProfileViewBasic(
107110
public ActorViewerState? Viewer { get; init; }
108111

109112
/// <summary>
110-
/// Any labels applied to the actor.
113+
/// Gets any labels applied to the actor.
111114
/// </summary>
112115
/// <remarks>
113116
///<para>
114-
///Labels will only be populated if a list of subscribed labelers from a user's <see cref="Preferences"/>
115-
///is passed into an API which returns this class.
117+
/// Labels will only be populated if a list of subscribed labelers from a user's <see cref="Preferences"/>
118+
/// is passed into an API which returns this class.
116119
///</para>
117120
/// </remarks>
118121
public IReadOnlyCollection<Label> Labels { get; init; }
119122

120123
/// <summary>
121-
/// The date and time the actor was created at.
124+
/// Gets the date and time the actor was created at.
122125
/// </summary>
123126
public DateTimeOffset? CreatedAt { get; init; }
124127

128+
/// <summary>
129+
/// Gets the <see cref="VerificationState"/> of the actor, if any.
130+
/// </summary>
131+
public VerificationState? Verification { get; init; }
132+
125133
/// <summary>
126134
/// Gets a string representation of the <see cref="ProfileView"/>.
127135
/// This returns the actor's display name, if any, otherwise returns the actor's handle.

src/idunno.Bluesky/Actor/ProfileViewDetailed.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public sealed record ProfileViewDetailed : ProfileView
3232
/// <param name="indexedAt">The date and time the actor was last indexed.</param>
3333
/// <param name="createdAt">The date and time the actor was created.</param>
3434
/// <param name="banner">A <see cref="Uri"/> to the actor's banner image.</param>
35+
/// <param name="verification">The <see cref="VerificationState"/> of the actor, if any.</param>
3536
/// <param name="followersCount">The actor's current follower count.</param>
3637
/// <param name="followsCount">The number of actors the actor follows.</param>
3738
/// <param name="postsCount">The number of posts the actor has made.</param>
@@ -54,12 +55,13 @@ public ProfileViewDetailed(
5455
IReadOnlyCollection<Label>? labels,
5556
DateTimeOffset? indexedAt,
5657
DateTimeOffset? createdAt,
58+
VerificationState? verification,
5759
StarterPackViewBasic? joinedViaStarterPack = null,
5860
StrongReference? pinnedPost = null,
5961
int followersCount = 0,
6062
int followsCount = 0,
6163
int postsCount = 0
62-
) : base(did, handle, displayName, description, avatar, associated, viewer, labels, indexedAt, createdAt)
64+
) : base(did, handle, displayName, description, avatar, associated, viewer, labels, indexedAt, createdAt, verification)
6365
{
6466
Banner = banner;
6567
FollowersCount = followersCount;

0 commit comments

Comments
 (0)