Added Owncast support

This commit is contained in:
barelyprofessional
2025-08-24 03:02:34 -05:00
parent bbfdf1e9f4
commit 2b07a07ac5
3 changed files with 122 additions and 2 deletions

View File

@@ -37,6 +37,7 @@ public class BotServices
private Parti? _parti;
private DLive? _dliveStatusCheck;
private PeerTube? _peerTubeStatusCheck;
private Owncast? _owncastStatusCheck;
private Task? _websocketWatchdog;
private Task? _howlggGetUserTimer;
@@ -84,7 +85,8 @@ public class BotServices
BuildRainbet(),
BuildParti(),
BuildDLiveStatusCheck(),
BuildPeerTubeLiveStatusCheck()
BuildPeerTubeLiveStatusCheck(),
BuildOwncastLiveStatusCheck()
];
try
{
@@ -334,6 +336,14 @@ public class BotServices
return Task.CompletedTask;
}
private Task BuildOwncastLiveStatusCheck()
{
_owncastStatusCheck = new Owncast(_chatBot);
_owncastStatusCheck.StartLiveStatusCheck();
_logger.Info("Built the Owncast livestream status check task");
return Task.CompletedTask;
}
private async Task BuildParti()
{
var settings = await SettingsProvider.GetMultipleValuesAsync([BuiltIn.Keys.Proxy, BuiltIn.Keys.PartiEnabled]);

View File

@@ -0,0 +1,92 @@
using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using KfChatDotNetBot.Settings;
using NLog;
namespace KfChatDotNetBot.Services;
public class Owncast(ChatBot kfChatBot) : IDisposable
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private Task? _liveStatusCheckTask;
private CancellationTokenSource _liveStatusCheckTaskCts = new();
public void StartLiveStatusCheck()
{
_liveStatusCheckTaskCts = new CancellationTokenSource();
_liveStatusCheckTask = Task.Run(LiveStatusCheckTask, _liveStatusCheckTaskCts.Token);
}
private async Task LiveStatusCheckTask()
{
var interval = (await SettingsProvider.GetValueAsync(BuiltIn.Keys.OwncastCheckInterval)).ToType<int>();
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(interval));
while (await timer.WaitForNextTickAsync(_liveStatusCheckTaskCts.Token))
{
var ct = _liveStatusCheckTaskCts.Token;
_logger.Debug("Going to check if anyone is live on Owncast now");
var persistedLive = (await SettingsProvider.GetValueAsync(BuiltIn.Keys.OwncastPersistedCurrentlyLive))
.ToBoolean();
OwncastStatusModel status;
try
{
status = await GetLiveStatus(ct);
}
catch (Exception e)
{
_logger.Error("Caught an error while trying to get the currently live streams from Owncast");
_logger.Error(e);
continue;
}
if (status.Online == persistedLive) continue;
await SettingsProvider.SetValueAsBooleanAsync(BuiltIn.Keys.OwncastPersistedCurrentlyLive,
status.Online);
if (!status.Online) continue;
await kfChatBot.SendChatMessageAsync("https://bossmanjack.tv restream is live!", true);
if (!(await SettingsProvider.GetValueAsync(BuiltIn.Keys.CaptureEnabled)).ToBoolean()) continue;
_ = new StreamCapture("https://bossmanjack.tv", StreamCaptureMethods.YtDlp, ct);
}
}
public static async Task<OwncastStatusModel> GetLiveStatus(CancellationToken ct = default)
{
var logger = LogManager.GetCurrentClassLogger();
var proxy = await SettingsProvider.GetValueAsync(BuiltIn.Keys.Proxy);
var handler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.All,
};
if (proxy.Value != null)
{
handler.Proxy = new WebProxy(proxy.Value);
handler.UseProxy = true;
logger.Debug($"Set proxy for the Owncast API request to {proxy.Value}");
}
using var client = new HttpClient(handler);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://bossmanjack.tv/api/status", ct);
var content = await response.Content.ReadFromJsonAsync<JsonElement>(cancellationToken: ct);
logger.Debug("Owncast endpoint returned the following JSON");
logger.Debug(content.GetRawText);
return content.GetProperty("data").Deserialize<OwncastStatusModel>() ?? throw new InvalidOperationException();
}
public void Dispose()
{
_liveStatusCheckTaskCts.Cancel();
_liveStatusCheckTask?.Dispose();
GC.SuppressFinalize(this);
}
}
public class OwncastStatusModel
{
[JsonPropertyName("online")]
public required bool Online { get; set; }
}

View File

@@ -976,7 +976,23 @@ public static class BuiltIn
Description = "Special options for Twitch streams captured with Streamlink",
Default = "--twitch-disable-ad --twitch-proxy-playlist=https://eu.luminous.dev,https://eu2.luminous.dev,https://as.luminous.dev,https://cdn.perfprod.com",
ValueType = SettingValueType.Text
}
},
new BuiltInSettingsModel
{
Key = Keys.OwncastCheckInterval,
Description = "Interval in seconds to check if someone is live on Owncast",
Default = "5",
ValueType = SettingValueType.Text,
Regex = WholeNumberRegex
},
new BuiltInSettingsModel
{
Key = Keys.OwncastPersistedCurrentlyLive,
Description = "Whether someone is live on Owncast",
Default = "false",
ValueType = SettingValueType.Boolean,
Regex = BooleanRegex
},
];
public static class Keys
@@ -1087,5 +1103,7 @@ public static class BuiltIn
public static string MoneyInitialBalance = "Money.InitialBalance";
public static string TwitchGraphQlCheckInterval = "TwitchGraphQl.CheckInterval";
public static string TwitchGraphQlPersistedCurrentlyLive = "TwitchGraphQl.PersistedCurrentlyLive";
public static string OwncastCheckInterval = "Owncast.CheckInterval";
public static string OwncastPersistedCurrentlyLive = "Owncast.PersistedCurrentlyLive";
}
}