Skip to content

Commit 7c62519

Browse files
committed
Update conversation and message classes to match lexicon update.
Add support for AddReaction and RemoveReaction for messages. More json pre-compilation fixes.
1 parent 2d0dc52 commit 7c62519

44 files changed

Lines changed: 1303 additions & 250 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/docs/endpointStatus.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
| | [chat.bsky.convo.sendMessageBatch](https://docs.bsky.app/docs/api/chat-bsky-convo-send-message-batch) | `BlueskyAgent.SendMessageBatch()` ||
6262
| | [chat.bsky.convo.sendMessage](https://docs.bsky.app/docs/api/chat-bsky-convo-send-message) | `BlueskyAgent.SendMessage()` ||
6363
| | [chat.bsky.convo.unmuteConvos](https://docs.bsky.app/docs/api/chat-bsky-convo-unmute-convo) | `BlueskyAgent.UnmuteConversation()` ||
64+
| | [chat.bsky.convo.updateAllRead](https://docs.bsky.app/docs/api/chat-bsky-convo-update-all-read) | `BlueskyAgent.UpdateRead()` ||
6465
| | [chat.bsky.convo.updateRead](https://docs.bsky.app/docs/api/chat-bsky-convo-update-read) | `BlueskyAgent.UpdateRead()` ||
6566

6667
## AT Protocol Endpoints

samples/Samples.DirectMessages/Program.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static async Task PerformOperations(string? handle, string? password, string? au
3636
ArgumentException.ThrowIfNullOrEmpty(password);
3737

3838
// Uncomment the next line to route all requests through Fiddler Everywhere
39-
// proxyUri = new Uri("http://localhost:8866");
39+
proxyUri = new Uri("http://localhost:8866");
4040

4141
// Uncomment the next line to route all requests through Fiddler Classic
4242
// proxyUri = new Uri("http://localhost:8888");
@@ -123,9 +123,9 @@ static async Task PerformOperations(string? handle, string? password, string? au
123123
}
124124
conversationMembers.Length -= 3;
125125

126-
if (!conversation.Opened)
126+
if (conversation.Status == ConversationStatus.Requested)
127127
{
128-
Console.Write("\u001b[1mUnopened ");
128+
Console.Write("\u001b[1mRequested ");
129129
}
130130

131131
Console.Write($"Conversation #{conversation.Id} between {conversationMembers}");
@@ -135,7 +135,7 @@ static async Task PerformOperations(string? handle, string? password, string? au
135135
Console.Write($" {conversation.UnreadCount} unread");
136136
}
137137

138-
if (!conversation.Opened)
138+
if (conversation.Status == ConversationStatus.Requested)
139139
{
140140
Console.Write("\u001b[22m");
141141
}

samples/Samples.Posting/Program.cs

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,21 +276,80 @@ static async Task PerformOperations(string? handle, string? password, string? au
276276

277277
var replyWithImageResult = await agent.ReplyTo(createPostResult.Result.StrongReference, "Reply with an image.", imageUploadResult.Result!, cancellationToken: cancellationToken);
278278

279-
using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Samples.Posting.BlueskyLogoRotated90.jpg")!)
279+
if (!replyWithImageResult.Succeeded)
280+
{
281+
Console.ForegroundColor = ConsoleColor.Red;
282+
Console.WriteLine($"{createPostResult.StatusCode} occurred when creating the post.");
283+
return;
284+
}
285+
286+
using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Samples.Posting.BlueskyLogo.jpg")!)
280287
using (MemoryStream memoryStream = new())
281288
{
282289
resourceStream.CopyTo(memoryStream);
283290
imageAsBytes = memoryStream.ToArray();
284291
}
285292

286293
imageUploadResult = await agent.UploadImage(
294+
imageAsBytes,
295+
"image/jpg",
296+
"The Bluesky Logo",
297+
new AspectRatio(1000, 1000),
298+
cancellationToken: cancellationToken);
299+
300+
using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Samples.Posting.BlueskyLogoRotated90.jpg")!)
301+
using (MemoryStream memoryStream = new())
302+
{
303+
resourceStream.CopyTo(memoryStream);
304+
imageAsBytes = memoryStream.ToArray();
305+
}
306+
var rotated90UploadResult= await agent.UploadImage(
287307
imageAsBytes,
288308
"image/jpg",
289309
"The Bluesky Logo, rotated 90°",
290310
new AspectRatio(1000, 1000),
291311
cancellationToken: cancellationToken);
292312

293-
if (!replyWithImageResult.Succeeded)
313+
using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Samples.Posting.BlueskyLogoRotated180.jpg")!)
314+
using (MemoryStream memoryStream = new())
315+
{
316+
resourceStream.CopyTo(memoryStream);
317+
imageAsBytes = memoryStream.ToArray();
318+
}
319+
var rotated180UploadResult = await agent.UploadImage(
320+
imageAsBytes,
321+
"image/jpg",
322+
"The Bluesky Logo, rotated 180°",
323+
new AspectRatio(1000, 1000),
324+
cancellationToken: cancellationToken);
325+
326+
using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Samples.Posting.BlueskyLogoRotated270.jpg")!)
327+
using (MemoryStream memoryStream = new())
328+
{
329+
resourceStream.CopyTo(memoryStream);
330+
imageAsBytes = memoryStream.ToArray();
331+
}
332+
var rotated270UploadResult = await agent.UploadImage(
333+
imageAsBytes,
334+
"image/jpg",
335+
"The Bluesky Logo, rotated 270°",
336+
new AspectRatio(1000, 1000),
337+
cancellationToken: cancellationToken);
338+
339+
340+
AtProtoHttpResult<CreateRecordResponse> multipleImagePostResult = await agent.Post(
341+
"Hello world with multiple images",
342+
[
343+
imageUploadResult.Result!,
344+
rotated90UploadResult.Result!,
345+
rotated180UploadResult.Result!,
346+
rotated270UploadResult.Result!,
347+
],
348+
cancellationToken: cancellationToken);
349+
350+
Debugger.Break();
351+
352+
if (!multipleImagePostResult.Succeeded)
294353
{
295354
Console.ForegroundColor = ConsoleColor.Red;
296355
Console.WriteLine($"{createPostResult.StatusCode} occurred when creating the post.");
@@ -299,9 +358,11 @@ static async Task PerformOperations(string? handle, string? password, string? au
299358

300359
Debugger.Break();
301360

302-
// Delete the post we just made, the image will eventually get cleaned up by the backend.
361+
// Delete the post we just made, the images will eventually get cleaned up by the backend.
303362
await agent.DeletePost(createPostResult.Result.StrongReference, cancellationToken: cancellationToken);
304363
await agent.DeletePost(replyWithImageResult.Result.StrongReference, cancellationToken: cancellationToken);
364+
await agent.DeletePost(multipleImagePostResult.Result.StrongReference, cancellationToken: cancellationToken);
365+
305366
}
306367

307368
{
@@ -367,7 +428,7 @@ static async Task PerformOperations(string? handle, string? password, string? au
367428
}
368429

369430
{
370-
// quote
431+
// Quote
371432
AtProtoHttpResult<CreateRecordResponse> createPostResult = await agent.Post("Another test post, for quoting.", cancellationToken: cancellationToken);
372433
if (createPostResult.Succeeded)
373434
{
@@ -446,7 +507,6 @@ static async Task PerformOperations(string? handle, string? password, string? au
446507
var hashTag = new HashTag("beans");
447508
postBuilder.Append(hashTag);
448509

449-
450510
byte[] imageAsBytes;
451511
using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Samples.Posting.bean.png")!)
452512
using (MemoryStream memoryStream = new())

src/idunno.AtProto/AtProtoHttpClient.cs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public AtProtoHttpClient(string? serviceProxy, ILoggerFactory? loggerFactory = n
8484
_supressProxyHeaderCheck = true;
8585
}
8686

87-
loggerFactory ??= NullLoggerFactory.Instance;
87+
loggerFactory ??= NullLoggerFactory.Instance;
8888
_logger = loggerFactory.CreateLogger<AtProtoHttpClient<TResult>>();
8989
}
9090

@@ -1015,17 +1015,10 @@ record is not EmptyRequestBody &&
10151015
{
10161016
string responseContent = await httpResponseMessage.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
10171017

1018-
try
1019-
{
1020-
result.Result = JsonSerializer.Deserialize(
1021-
responseContent,
1022-
typeof(TResult),
1023-
jsonSerializerOptions) as TResult;
1024-
}
1025-
catch (JsonException)
1026-
{
1027-
result.Result = null;
1028-
}
1018+
result.Result = JsonSerializer.Deserialize(
1019+
responseContent,
1020+
typeof(TResult),
1021+
jsonSerializerOptions) as TResult;
10291022
}
10301023
else
10311024
{

src/idunno.AtProto/Authentication/AtProtoAgent.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ public async Task Logout(CancellationToken cancellationToken = default)
633633
service: authorizationService,
634634
endpoint: revocationEndpoint.AbsolutePath,
635635
record: formData,
636-
jsonSerializerOptions: AtProtoServer.SelfContainedJsonSerializerOptions,
636+
jsonSerializerOptions: AtProtoServer.AtProtoJsonSerializerOptions,
637637
credentials: Credentials,
638638
httpClient: HttpClient,
639639
cancellationToken: cancellationToken).ConfigureAwait(false);
@@ -660,7 +660,7 @@ public async Task Logout(CancellationToken cancellationToken = default)
660660
service: authorizationService,
661661
endpoint: revocationEndpoint.AbsolutePath,
662662
record: formData,
663-
jsonSerializerOptions: AtProtoServer.SelfContainedJsonSerializerOptions,
663+
jsonSerializerOptions: AtProtoServer.AtProtoJsonSerializerOptions,
664664
credentials: Credentials,
665665
httpClient: HttpClient,
666666
cancellationToken: cancellationToken).ConfigureAwait(false);

src/idunno.AtProto/Authentication/AtProtoServer.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public static async Task<AtProtoHttpResult<CreateSessionResponse>> CreateSession
7070
CreateSessionEndpoint,
7171
loginRequestRecord,
7272
httpClient: httpClient,
73-
jsonSerializerOptions: SelfContainedJsonSerializerOptions,
73+
jsonSerializerOptions: AtProtoJsonSerializerOptions,
7474
cancellationToken: cancellationToken).ConfigureAwait(false);
7575

7676
return result;
@@ -109,7 +109,7 @@ public static async Task<AtProtoHttpResult<EmptyResponse>> DeleteSession(
109109
endpoint: DeleteSessionEndpoint,
110110
credentials: refreshCredential,
111111
httpClient: httpClient,
112-
jsonSerializerOptions: SelfContainedJsonSerializerOptions,
112+
jsonSerializerOptions: AtProtoJsonSerializerOptions,
113113
cancellationToken: cancellationToken).ConfigureAwait(false);
114114

115115
return result;
@@ -150,7 +150,7 @@ public static async Task<AtProtoHttpResult<RefreshSessionResponse>> RefreshSessi
150150
credentials: refreshCredential,
151151
httpClient: httpClient,
152152
onCredentialsUpdated: credentialsUpdated,
153-
jsonSerializerOptions: SelfContainedJsonSerializerOptions,
153+
jsonSerializerOptions: AtProtoJsonSerializerOptions,
154154
cancellationToken: cancellationToken).ConfigureAwait(false);
155155

156156
return result;
@@ -189,7 +189,7 @@ public static async Task<AtProtoHttpResult<GetSessionResponse>> GetSession(
189189
accessCredentials,
190190
httpClient: httpClient,
191191
onCredentialsUpdated: credentialsUpdated,
192-
jsonSerializerOptions: SelfContainedJsonSerializerOptions,
192+
jsonSerializerOptions: AtProtoJsonSerializerOptions,
193193
cancellationToken: cancellationToken).ConfigureAwait(false);
194194
}
195195

@@ -259,7 +259,7 @@ public static async Task<AtProtoHttpResult<ServiceCredential>> GetServiceAuth(
259259
accessCredentials,
260260
httpClient: httpClient,
261261
onCredentialsUpdated: accessCredentialsUpdated,
262-
jsonSerializerOptions: SelfContainedJsonSerializerOptions,
262+
jsonSerializerOptions: AtProtoJsonSerializerOptions,
263263
cancellationToken: cancellationToken).ConfigureAwait(false);
264264

265265
if (result.Succeeded)

src/idunno.AtProto/JsonSerializerOptions.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@ namespace idunno.AtProto
1010
public partial class AtProtoServer
1111
{
1212
/// <summary>
13-
/// Gets a <see cref="JsonSerializerOptions"/> configured to use Json source generation for AtProto classes without
14-
/// any chaining to external resolvers.
13+
/// Gets a <see cref="JsonSerializerOptions"/> configured to use Json source generation for AtProto classes
1514
/// </summary>
16-
internal static JsonSerializerOptions SelfContainedJsonSerializerOptions => new(JsonSerializerDefaults.Web)
15+
internal static JsonSerializerOptions AtProtoJsonSerializerOptions => new(JsonSerializerDefaults.Web)
1716
{
1817
AllowOutOfOrderMetadataProperties = true,
1918
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
2019
IgnoreReadOnlyProperties = false,
2120
TypeInfoResolver = SourceGenerationContext.Default,
22-
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip
21+
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
2322
};
2423

2524
/// <summary>
@@ -55,7 +54,7 @@ public static JsonSerializerOptions BuildChainedTypeInfoResolverJsonSerializerOp
5554
{
5655
ArgumentNullException.ThrowIfNull(jsonTypeInfoResolver);
5756

58-
JsonSerializerOptions options = SelfContainedJsonSerializerOptions;
57+
JsonSerializerOptions options = AtProtoJsonSerializerOptions;
5958

6059
options.TypeInfoResolverChain.Insert(0, jsonTypeInfoResolver);
6160

src/idunno.AtProto/Labels/AtProtoServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public static async Task<AtProtoHttpResult<PagedReadOnlyCollection<Label>>> Quer
9393
accessCredentials,
9494
httpClient,
9595
onCredentialsUpdated: onCredentialsUpdated,
96-
jsonSerializerOptions: SelfContainedJsonSerializerOptions,
96+
jsonSerializerOptions: AtProtoJsonSerializerOptions,
9797
cancellationToken: cancellationToken).ConfigureAwait(false);
9898

9999
if (response.Succeeded)

src/idunno.AtProto/Labels/SelfLabel.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ public record SelfLabel
1414
/// Creates a new instance of <see cref="SelfLabel"/>
1515
/// </summary>
1616
/// <param name="value">The short string name of the value or type of this label.</param>
17-
/// <exception cref="ArgumentNullException">Thrown when <paramref name="value"/> is null or whitespace.</exception>
17+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="value"/> is null.</exception>
18+
/// <exception cref="ArgumentException">Thrown when <paramref name="value"/> is whitespace.</exception>
1819
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="value"/> is longer than 128 characters.</exception>
1920
public SelfLabel(string value)
2021
{
21-
ArgumentNullException.ThrowIfNullOrWhiteSpace(value);
22+
ArgumentException.ThrowIfNullOrWhiteSpace(value);
2223
ArgumentOutOfRangeException.ThrowIfGreaterThan(value.Length, 128);
2324

2425
Value = value;

src/idunno.AtProto/Labels/SelfLabels.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Barry Dorrans. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using System.Collections.ObjectModel;
54
using System.Diagnostics;
65
using System.Diagnostics.CodeAnalysis;
76
using System.Text.Json.Serialization;
@@ -21,26 +20,25 @@ public sealed class SelfLabels
2120
/// </summary>
2221
public SelfLabels()
2322
{
24-
Values = ReadOnlyCollection<SelfLabel>.Empty;
23+
Values = [];
2524
}
2625

2726
/// <summary>
2827
/// Creates a new instance of <see cref="SelfLabels"/>.
2928
/// </summary>
3029
/// <param name="values">The collection of labels applied to the record.</param>
3130
[JsonConstructor]
32-
public SelfLabels(ReadOnlyCollection<SelfLabel> values)
31+
public SelfLabels(IReadOnlyList<SelfLabel> values)
3332
{
3433
ArgumentNullException.ThrowIfNull(values);
3534
ArgumentOutOfRangeException.ThrowIfGreaterThan(values.Count, 10);
3635

37-
Values = values;
36+
Values = new List<SelfLabel>(values).AsReadOnly();
3837
}
3938

4039
/// <summary>
4140
/// The type discriminator for the class.
4241
/// </summary>
43-
[JsonInclude]
4442
[JsonPropertyName("$type")]
4543
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Needs to an instance property for json serialization.")]
4644
public string Type => "com.atproto.label.defs#selfLabels";
@@ -50,7 +48,7 @@ public SelfLabels(ReadOnlyCollection<SelfLabel> values)
5048
/// </summary>
5149
[JsonInclude]
5250
[JsonRequired]
53-
public ReadOnlyCollection<SelfLabel> Values { get; internal set; }
51+
public IReadOnlyList<SelfLabel> Values { get; internal set; }
5452

5553
/// <summary>
5654
/// Returns a flag indicating whether the specified <paramref name="label"/> is present.

0 commit comments

Comments
 (0)