-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathBlueskyApiClient.Search.cs
120 lines (94 loc) · 3.5 KB
/
BlueskyApiClient.Search.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using Bluesky.NET.Constants;
using Bluesky.NET.Models;
using FluentResults;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace Bluesky.NET.ApiClients;
partial class BlueskyApiClient
{
/// <inheritdoc/>
public async Task<Result<FeedResponse>> SearchFeedsAsync(
string accessToken,
string query,
CancellationToken ct,
string? cursor = null)
{
var url = $"{_baseUrl}/{UrlConstants.SearchFeedsPath}?query={HttpUtility.UrlEncode(query)}";
if (cursor is not null)
{
url += $"&cursor={cursor}";
}
HttpRequestMessage message = new(HttpMethod.Get, url);
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return await SendMessageAsync(
message,
ModelSerializerContext.CaseInsensitive.FeedResponse,
ct);
}
/// <inheritdoc/>
public async Task<Result<FeedResponse>> SearchActorsAsync(
string accessToken,
string query,
CancellationToken ct,
string? cursor = null)
{
// Ref: https://docs.bsky.app/docs/api/app-bsky-actor-search-actors
var url = $"{_baseUrl}/{UrlConstants.SearchActorsPath}?q={HttpUtility.UrlEncode(query)}";
if (cursor is not null)
{
url += $"&cursor={cursor}";
}
HttpRequestMessage message = new(HttpMethod.Get, url);
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return await SendMessageAsync(
message,
ModelSerializerContext.CaseInsensitive.FeedResponse,
ct);
}
public async Task<Result<(IReadOnlyList<FeedPost> Posts, string? Cursor)>> SearchPostsAsync(
string accessToken,
string query,
CancellationToken ct,
string? cursor = null,
SearchOptions? options = null)
{
// Ref: https://docs.bsky.app/docs/api/app-bsky-feed-search-posts
options ??= new();
var url = $"{_baseUrl}/{UrlConstants.SearchPostsPath}?q={HttpUtility.UrlEncode(query)}";
if (cursor is not null)
{
url += $"&cursor={cursor}";
}
url += $"&{OptionsToQueryString(options)}";
HttpRequestMessage message = new(HttpMethod.Get, url);
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
Result<FeedResponse> response = await SendMessageAsync(
message,
ModelSerializerContext.CaseInsensitive.FeedResponse,
ct);
return response.IsSuccess && response.Value.Posts is IReadOnlyList<FeedPost> posts
? Result.Ok((posts, response.Value.Cursor))
: Result.Fail<(IReadOnlyList<FeedPost> Posts, string? Cursor)>(response.Errors);
}
private static string OptionsToQueryString(SearchOptions options)
{
List<string> queryParamPairs = [$"sort={options.Sort}"];
// TODO implement the other filters
return string.Join("&", queryParamPairs);
}
}
public class SearchOptions
{
public string Sort { get; init; } = SearchConstants.SortTop;
public DateTime? Since { get; init; }
public DateTime? Until { get; init; }
public string? IdentifierMentioned { get; init; }
public string? Language { get; init; }
public string? Domain { get; init; }
public string? Url { get; init; }
}