Private broadcasts end like recordings: Enter keeps, Escape deletes (KeepBroadcastDialog). Privacy read from YouTube; delete = videos.delete (fallback liveBroadcasts.delete on 404). Refs: https://developers.google.com/youtube/v3/docs/videos/delete https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/delete (Unit: private broadcast close-out)
This commit is contained in:
@@ -174,6 +174,66 @@ public class YouTubeStreamService
|
||||
return $"YouTube rejected the end transition ({(int)response.StatusCode})";
|
||||
}
|
||||
|
||||
/// <summary>The broadcast's current <c>status.privacyStatus</c> ("private", "unlisted",
|
||||
/// "public"), read from YouTube rather than trusted from local state — the creator can
|
||||
/// change visibility mid-stream from the broadcast form. Null when signed out or the
|
||||
/// read fails (the caller then does nothing destructive).</summary>
|
||||
public async Task<string?> GetBroadcastPrivacyAsync(string broadcastId)
|
||||
{
|
||||
if (!await EnsureToken()) return null;
|
||||
_http.DefaultRequestHeaders.Authorization = new("Bearer", _auth.CurrentChannel!.AccessToken);
|
||||
try
|
||||
{
|
||||
var response = await _http.GetAsync(
|
||||
$"{ApiBase}/liveBroadcasts?part=status&id={Uri.EscapeDataString(broadcastId)}");
|
||||
if (!response.IsSuccessStatusCode) return null;
|
||||
var json = JsonSerializer.Deserialize<JsonElement>(await response.Content.ReadAsStringAsync());
|
||||
if (!json.TryGetProperty("items", out var items) || items.GetArrayLength() == 0) return null;
|
||||
if (!items[0].TryGetProperty("status", out var status)) return null;
|
||||
return status.TryGetProperty("privacyStatus", out var privacy) ? privacy.GetString() : null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppLog.Write($"Broadcast privacy read failed: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Deletes a finished broadcast's recording from YouTube (the creator pressed
|
||||
/// Escape / Delete on the keep-or-delete prompt). A live broadcast's id IS its video's
|
||||
/// id, so this is <c>videos.delete</c> (Data API, 204 on success); if YouTube hasn't
|
||||
/// created the video yet (404) it falls back to <c>liveBroadcasts.delete</c>. Returns
|
||||
/// null on success, or an error string — never throws.
|
||||
/// Docs: https://developers.google.com/youtube/v3/docs/videos/delete ,
|
||||
/// https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/delete</summary>
|
||||
public async Task<string?> DeleteFinishedBroadcastAsync(string broadcastId)
|
||||
{
|
||||
if (!await EnsureToken()) return "not signed in";
|
||||
_http.DefaultRequestHeaders.Authorization = new("Bearer", _auth.CurrentChannel!.AccessToken);
|
||||
try
|
||||
{
|
||||
var id = Uri.EscapeDataString(broadcastId);
|
||||
var video = await _http.DeleteAsync($"{ApiBase}/videos?id={id}");
|
||||
if (video.IsSuccessStatusCode) return null;
|
||||
if (video.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
var broadcast = await _http.DeleteAsync($"{ApiBase}/liveBroadcasts?id={id}");
|
||||
if (broadcast.IsSuccessStatusCode) return null;
|
||||
var bBody = await broadcast.Content.ReadAsStringAsync();
|
||||
AppLog.Write($"liveBroadcasts.delete failed ({(int)broadcast.StatusCode}): {bBody}");
|
||||
return $"YouTube refused to delete the broadcast ({(int)broadcast.StatusCode})";
|
||||
}
|
||||
var body = await video.Content.ReadAsStringAsync();
|
||||
AppLog.Write($"videos.delete failed ({(int)video.StatusCode}): {body}");
|
||||
return $"YouTube refused to delete the video ({(int)video.StatusCode})";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppLog.Write($"Broadcast delete failed: {ex.Message}");
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>One liveBroadcasts.list (part=status) read of the broadcast's own
|
||||
/// lifeCycleStatus — the only reliable "can we complete?" signal. Null when the
|
||||
/// list fails or the status is missing (caller degrades gracefully).</summary>
|
||||
|
||||
Reference in New Issue
Block a user