From 8529348c96411ed2c4a1f717f4d8d3400feb3deb Mon Sep 17 00:00:00 2001 From: Ole Date: Sun, 31 Dec 2023 19:29:55 +0100 Subject: [PATCH] Allow Async (v2) Uploads to Mastodon for bigger files (Videos); GET Media --- Mastonet/IMastodonClient.cs | 53 ++++++++++++++++++++++----- Mastonet/MastodonClient.cs | 73 +++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/Mastonet/IMastodonClient.cs b/Mastonet/IMastodonClient.cs index ab292fe..3c3ad07 100644 --- a/Mastonet/IMastodonClient.cs +++ b/Mastonet/IMastodonClient.cs @@ -1,8 +1,8 @@ using Mastonet.Entities; + using System; using System.Collections.Generic; using System.IO; -using System.Text; using System.Threading.Tasks; namespace Mastonet; @@ -170,6 +170,42 @@ public interface IMastodonClient /// Returns an Attachment that can be used when creating a status Task UploadMedia(Stream data, string fileName = "file", string? description = null, AttachmentFocusData? focus = null); + /// + /// Wait until an attachment has been uploaded and processed + /// + /// Attachment that has just been created + /// Poll for Status update interval + /// Maximum time to wait before giving opt (timeout) + /// Returns an Attachment that can be used when creating a status after the processing is finished + Task WaitUntilMediaIsUploaded(Attachment attachment, int waitSeconds = 10, int maxWaitSeconds = 300); + + /// + /// Get Information from a single Media item + /// + /// Id from Attachment + /// Returns an Attachment that can be used when creating a status after the processing is finished + Task GetMedia(string mediaId); + + /// + /// Uploading a media attachment async (v2) You will have to wait afterwards until the attachment is processed. This is meant for bigger attachments (videos) + /// + /// Media stream to be uploaded + /// Media file name (must contains extension ex: .png, .jpg, ...) + /// A plain-text description of the media for accessibility (max 420 chars) + /// Two floating points. See focal points + /// Returns an Attachment that can be used when creating a status after the processing is finished + Task UploadMediaAsync(MediaDefinition media, string? description = null, AttachmentFocusData? focus = null); + + /// + /// Uploading a media attachment async (v2) You will have to wait afterwards until the attachment is processed. This is meant for bigger attachments (videos) + /// + /// Media to be uploaded + /// A plain-text description of the media for accessibility (max 420 chars) + /// Two floating points. See focal points + /// Returns an Attachment that can be used when creating a status after the processing is finished + Task UploadMediaAsync(Stream data, string fileName = "file", string? description = null, AttachmentFocusData? focus = null); + + /// /// Uploading a media attachment /// @@ -216,7 +252,6 @@ public interface IMastodonClient /// Task DismissNotification(string notificationId); - /// /// Fetching a user's reports /// @@ -309,7 +344,7 @@ public interface IMastodonClient /// Returns Poll Task Vote(string id, IEnumerable choices); - #endregion + #endregion MastodonClient #region MastodonClient.Account @@ -326,8 +361,6 @@ public interface IMastodonClient /// Returns the user's own Account with Source Task GetCurrentUser(); - - /// /// Update the user's display and preferences. /// @@ -468,7 +501,7 @@ Task UpdateCredentials(bool? discoverable = null, /// Task> GetFeaturedTagsSuggestions(); - #endregion + #endregion MastodonClient.Account #region MastodonClient.AccountActions @@ -619,7 +652,7 @@ Task UpdateCredentials(bool? discoverable = null, /// Task> ViewFollowedTags(ArrayOptions? options = null); - #endregion + #endregion MastodonClient.AccountActions #region MastodonClient.Status @@ -791,7 +824,7 @@ Task UpdateCredentials(bool? discoverable = null, /// Returns the target Status Task Unpin(string statusId); - #endregion + #endregion MastodonClient.Status #region MastodonClient.Timeline @@ -860,5 +893,5 @@ Task UpdateCredentials(bool? discoverable = null, TimelineStreaming GetDirectMessagesStreaming(); - #endregion -} + #endregion MastodonClient.Timeline +} \ No newline at end of file diff --git a/Mastonet/MastodonClient.cs b/Mastonet/MastodonClient.cs index cea31b1..aba5ea1 100644 --- a/Mastonet/MastodonClient.cs +++ b/Mastonet/MastodonClient.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net.Http; using System.Net.Http.Headers; +using System.Threading; using System.Threading.Tasks; namespace Mastonet; @@ -347,6 +348,20 @@ public Task UploadMedia(Stream data, string fileName = "file", strin return UploadMedia(new MediaDefinition(data, fileName), description, focus); } + /// + /// Uploading a media attachment async (v2) You will have to wait afterwards until the attachment is processed. This is meant for bigger attachments (videos) + /// + /// Media stream to be uploaded + /// Media file name (must contains extension ex: .png, .jpg, ...) + /// A plain-text description of the media for accessibility (max 420 chars) + /// Two floating points. See focal points + /// Returns an Attachment that can be used when creating a status after the processing is finished + public Task UploadMediaAsync(Stream data, string fileName = "file", string? description = null, + AttachmentFocusData? focus = null) + { + return UploadMediaAsync(new MediaDefinition(data, fileName), description, focus); + } + /// /// Uploading a media attachment /// @@ -373,6 +388,64 @@ public Task UploadMedia(MediaDefinition media, string? description = return this.Post("/api/v2/media", data, list); } + /// + /// Uploading a media attachment async (v2) You will have to wait afterwards until the attachment is processed. This is meant for bigger attachments (videos) + /// + /// Media to be uploaded + /// A plain-text description of the media for accessibility (max 420 chars) + /// Two floating points. See focal points + /// Returns an Attachment that can be used when creating a status after the processing is finished + public async Task UploadMediaAsync(MediaDefinition media, string? description = null, + AttachmentFocusData? focus = null) + { + media.ParamName = "file"; + var list = new List() { media }; + var data = new Dictionary(); + if (description != null) + { + data.Add("description", description); + } + + if (focus != null) + { + data.Add("focus", $"{focus.X},{focus.Y}"); + } + + return await this.Post("/api/v2/media", data, list); + } + + /// + /// Wait until an attachment has been uploaded and processed + /// + /// Attachment that has just been created + /// Poll for Status update interval + /// Maximum time to wait before giving opt (timeout) + /// Returns an Attachment that can be used when creating a status after the processing is finished + public async Task WaitUntilMediaIsUploaded(Attachment attachment, int waitSeconds = 10, int maxWaitSeconds = 300) + { + int totalTimeWasted = 0; + while (attachment.Id != null && attachment.Url == null && attachment.PreviewUrl != null && totalTimeWasted < maxWaitSeconds) + { + Thread.Sleep(waitSeconds * 1000); + totalTimeWasted += waitSeconds; + attachment = await GetMedia(attachment.Id); + } + return attachment; + } + + /// + /// Get Information from a single Media item + /// + /// Id from Attachment + /// Returns an Attachment that can be used when creating a status after the processing is finished + public async Task GetMedia(string mediaId) + { + var attachment = await this.Get("/api/v1/media/" + mediaId); + var prev = attachment.PreviewUrl; + var url = attachment.Url; + return attachment; + } + /// /// Update a media attachment. Can only be done before the media is attached to a status. ///