Initial commit
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user