diff --git a/Src/Notion.Client/Api/ApiEndpoints.cs b/Src/Notion.Client/Api/ApiEndpoints.cs index 54de4e10..a788b8fc 100644 --- a/Src/Notion.Client/Api/ApiEndpoints.cs +++ b/Src/Notion.Client/Api/ApiEndpoints.cs @@ -145,6 +145,7 @@ public static class FileUploadsApiUrls public static string Create() => "/v1/file_uploads"; public static string Send(string fileUploadId) => $"/v1/file_uploads/{fileUploadId}/send"; public static string Complete(string fileUploadId) => $"/v1/file_uploads/{fileUploadId}/complete"; + public static string List => "/v1/file_uploads"; } } } diff --git a/Src/Notion.Client/Api/FileUploads/IFileUploadsClient.cs b/Src/Notion.Client/Api/FileUploads/IFileUploadsClient.cs index 660665c8..2e63f145 100644 --- a/Src/Notion.Client/Api/FileUploads/IFileUploadsClient.cs +++ b/Src/Notion.Client/Api/FileUploads/IFileUploadsClient.cs @@ -40,5 +40,16 @@ Task CompleteAsync( CompleteFileUploadRequest completeFileUploadRequest, CancellationToken cancellationToken = default ); + + /// + /// List File Uploads for the current bot integration, sorted by most recent first. + /// + /// + /// + /// + Task ListAsync( + ListFileUploadsRequest request, + CancellationToken cancellationToken = default + ); } } \ No newline at end of file diff --git a/Src/Notion.Client/Api/FileUploads/List/FileUploadsClient.cs b/Src/Notion.Client/Api/FileUploads/List/FileUploadsClient.cs new file mode 100644 index 00000000..49443cae --- /dev/null +++ b/Src/Notion.Client/Api/FileUploads/List/FileUploadsClient.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Notion.Client +{ + public sealed partial class FileUploadsClient + { + public async Task ListAsync( + ListFileUploadsRequest request, + System.Threading.CancellationToken cancellationToken = default) + { + IListFileUploadsQueryParameters queryParameters = request; + + var queryParams = new Dictionary + { + { "page_size", queryParameters.PageSize?.ToString() }, + { "start_cursor", queryParameters.StartCursor }, + { "status", queryParameters.Status } + }; + + return await _restClient.GetAsync( + ApiEndpoints.FileUploadsApiUrls.List, + queryParams: queryParams, + cancellationToken: cancellationToken + ); + } + } +} diff --git a/Src/Notion.Client/Api/FileUploads/List/Request/IListFileUploadsQueryParameters.cs b/Src/Notion.Client/Api/FileUploads/List/Request/IListFileUploadsQueryParameters.cs new file mode 100644 index 00000000..feeb0820 --- /dev/null +++ b/Src/Notion.Client/Api/FileUploads/List/Request/IListFileUploadsQueryParameters.cs @@ -0,0 +1,22 @@ +namespace Notion.Client +{ + public interface IListFileUploadsQueryParameters + { + /// + /// Filter file uploads by specifying the status. Supported values are "pending", "uploaded", "expired", "failed". + /// + string Status { get; set; } + + /// + /// If supplied, this endpoint will return a page of results starting after the cursor provided. + /// If not supplied, this endpoint will return the first page of results. + /// + string StartCursor { get; set; } + + /// + /// The number of items from the full list desired in the response. Maximum: 100 + /// Default to 100 + /// + int? PageSize { get; set; } + } +} diff --git a/Src/Notion.Client/Api/FileUploads/List/Request/ListFileUploadsRequest.cs b/Src/Notion.Client/Api/FileUploads/List/Request/ListFileUploadsRequest.cs new file mode 100644 index 00000000..b61c36e0 --- /dev/null +++ b/Src/Notion.Client/Api/FileUploads/List/Request/ListFileUploadsRequest.cs @@ -0,0 +1,9 @@ +namespace Notion.Client +{ + public class ListFileUploadsRequest : IListFileUploadsQueryParameters + { + public string Status { get; set; } + public string StartCursor { get; set; } + public int? PageSize { get; set; } + } +} diff --git a/Src/Notion.Client/Api/FileUploads/List/Response/ListFileUploadsResponse.cs b/Src/Notion.Client/Api/FileUploads/List/Response/ListFileUploadsResponse.cs new file mode 100644 index 00000000..581c80f8 --- /dev/null +++ b/Src/Notion.Client/Api/FileUploads/List/Response/ListFileUploadsResponse.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Notion.Client +{ + public class ListFileUploadsResponse : PaginatedList + { + [JsonProperty("file_uploads")] + public Dictionary FileUploads { get; set; } + } +} diff --git a/Test/Notion.IntegrationTests/FileUploadsClientTests.cs b/Test/Notion.IntegrationTests/FileUploadsClientTests.cs index e0e7776f..f91e9819 100644 --- a/Test/Notion.IntegrationTests/FileUploadsClientTests.cs +++ b/Test/Notion.IntegrationTests/FileUploadsClientTests.cs @@ -121,5 +121,23 @@ public async Task Verify_multi_part_file_upload_flow() Assert.Equal("completed", completeResponse.Status); } } + + [Fact] + public async Task ListAsync() + { + // Arrange + var request = new ListFileUploadsRequest + { + PageSize = 5 + }; + + // Act + var response = await Client.FileUploads.ListAsync(request); + + // Assert + Assert.NotNull(response); + Assert.NotNull(response.Results); + Assert.True(response.Results.Count <= 5); + } } } \ No newline at end of file diff --git a/Test/Notion.UnitTests/FileUploadsClientTests.cs b/Test/Notion.UnitTests/FileUploadsClientTests.cs index d1f0c3a7..3d80d7d6 100644 --- a/Test/Notion.UnitTests/FileUploadsClientTests.cs +++ b/Test/Notion.UnitTests/FileUploadsClientTests.cs @@ -178,4 +178,45 @@ public async Task SendAsync_CallsRestClientPostAsync_WithCorrectParameters() Assert.Equal(expectedResponse.Id, response.Id); _restClientMock.VerifyAll(); } + + #region ListAsync Tests + + [Fact] + public async Task ListAsync_CallsRestClientGetAsync_WithCorrectParameters() + { + // Arrange + var request = new ListFileUploadsRequest + { + PageSize = 10, + StartCursor = "cursor123", + Status = "completed" + }; + + _restClientMock + .Setup(client => client.GetAsync( + It.Is(url => url == ApiEndpoints.FileUploadsApiUrls.List), + It.IsAny>(), + null, + null, + It.IsAny() + )) + .ReturnsAsync(new ListFileUploadsResponse + { + Results = new List + { + new() { Id = "file1", Status = "completed" }, + new() { Id = "file2", Status = "completed" } + } + }); + + // Act + var response = await _fileUploadClient.ListAsync(request); + + // Assert + Assert.NotNull(response); + Assert.Equal(2, response.Results.Count); + _restClientMock.VerifyAll(); + } + + #endregion ListAsync Tests }