Files
rudder-csharp-sdk/Services/UgcService.cs
T
2026-08-12 14:04:55 +03:00

156 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using RudderSdk.Core.Models.Ugc;
namespace RudderSdk.Core;
/// <summary>User-generated content: upload, list, download URLs, deletion.</summary>
public sealed class UgcService
{
private readonly RudderClient _client;
internal UgcService(RudderClient client) => _client = client;
/// <summary>
/// Uploads a file in one call: pre-signed URL, PUT of the bytes, submission.
/// Requires an upload transport in <see cref="RudderClientOptions.UploadTransport"/>.
/// </summary>
public async Task<UgcSubmission> UploadAsync(
string name,
byte[] data,
string? description = null,
JToken? metadata = null,
CancellationToken cancellationToken = default)
{
var uploadTransport = _client.Options.UploadTransport
?? throw new InvalidOperationException("UploadTransport is not configured.");
var upload = await GetUploadUrlAsync(name, cancellationToken).ConfigureAwait(false);
await uploadTransport.PutAsync(
upload.UploadUrl,
data ?? Array.Empty<byte>(),
GetContentType(name),
cancellationToken).ConfigureAwait(false);
return await SubmitAsync(
name,
upload.FileKey,
data?.LongLength ?? 0,
description,
metadata,
cancellationToken).ConfigureAwait(false);
}
/// <summary>Fetches one page of the player's submissions.</summary>
public Task<ListUgcResponse> ListAsync(string? status = null, int limit = 20, string? cursor = null, CancellationToken cancellationToken = default)
=> _client.SendAsync<ListUgcResponse>(
"GET",
"/sdk/v1/ugc" + Url.Query(
("status", status),
("limit", limit > 0 ? limit.ToString() : null),
("cursor", cursor)),
cancellationToken);
/// <summary>Iterates over all of the player's submissions, following the cursor pagination.</summary>
public async IAsyncEnumerable<UgcSubmission> ListAllAsync(
string? status = null,
int limit = 20,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
string? cursor = null;
do
{
var page = await ListAsync(status, limit, cursor, cancellationToken).ConfigureAwait(false);
if (page?.Items != null)
{
foreach (var item in page.Items)
yield return item;
}
cursor = page?.NextCursor;
}
while (!string.IsNullOrEmpty(cursor));
}
/// <summary>Returns one submission.</summary>
public Task<UgcSubmission> GetAsync(string id, CancellationToken cancellationToken = default)
=> _client.SendAsync<UgcSubmission>("GET", "/sdk/v1/ugc/" + Url.Encode(id), cancellationToken);
/// <summary>Deletes a submission; returns false when the server refused.</summary>
public async Task<bool> DeleteAsync(string id, CancellationToken cancellationToken = default)
{
var response = await _client.SendAsync<DeleteUgcResponse>(
"DELETE",
"/sdk/v1/ugc/" + Url.Encode(id),
cancellationToken).ConfigureAwait(false);
return response == null || response.Success;
}
/// <summary>Requests a pre-signed upload URL.</summary>
public Task<GetUploadUrlResponse> GetUploadUrlAsync(string filename, CancellationToken cancellationToken = default)
=> _client.SendAsync<GetUploadUrlResponse>(
"GET",
"/sdk/v1/ugc/upload-url" + Url.Query(("filename", filename)),
cancellationToken);
/// <summary>
/// Resolves the download URL of a submission.
/// Throws <see cref="InvalidOperationException"/> when the server returned none.
/// </summary>
public async Task<string> GetDownloadUrlAsync(string id, CancellationToken cancellationToken = default)
{
var response = await _client.SendAsync<GetDownloadUrlResponse>(
"GET",
"/sdk/v1/ugc/" + Url.Encode(id) + "/download",
cancellationToken).ConfigureAwait(false);
if (response == null || string.IsNullOrEmpty(response.DownloadUrl))
throw new InvalidOperationException("The server returned no download URL.");
return response.DownloadUrl;
}
/// <summary>Registers an uploaded file as a submission.</summary>
public Task<UgcSubmission> SubmitAsync(
string name,
string fileKey,
long fileSize,
string? description = null,
JToken? metadata = null,
CancellationToken cancellationToken = default)
{
return _client.SendAsync<SubmitUgcRequest, UgcSubmission>(
"POST",
"/sdk/v1/ugc",
new SubmitUgcRequest
{
Name = name,
FileKey = fileKey,
FileSize = fileSize,
Description = description!,
Metadata = metadata!
},
cancellationToken);
}
private static string GetContentType(string filename)
{
var ext = System.IO.Path.GetExtension(filename)?.ToLowerInvariant();
switch (ext)
{
case ".png": return "image/png";
case ".jpg":
case ".jpeg": return "image/jpeg";
case ".gif": return "image/gif";
case ".webp": return "image/webp";
case ".txt": return "text/plain";
default: return "application/octet-stream";
}
}
}