mirror of
https://github.com/barelyprofessional/KfChatDotNet.git
synced 2026-05-02 04:22:04 -04:00
Added Owncast support
This commit is contained in:
@@ -37,6 +37,7 @@ public class BotServices
|
|||||||
private Parti? _parti;
|
private Parti? _parti;
|
||||||
private DLive? _dliveStatusCheck;
|
private DLive? _dliveStatusCheck;
|
||||||
private PeerTube? _peerTubeStatusCheck;
|
private PeerTube? _peerTubeStatusCheck;
|
||||||
|
private Owncast? _owncastStatusCheck;
|
||||||
|
|
||||||
private Task? _websocketWatchdog;
|
private Task? _websocketWatchdog;
|
||||||
private Task? _howlggGetUserTimer;
|
private Task? _howlggGetUserTimer;
|
||||||
@@ -84,7 +85,8 @@ public class BotServices
|
|||||||
BuildRainbet(),
|
BuildRainbet(),
|
||||||
BuildParti(),
|
BuildParti(),
|
||||||
BuildDLiveStatusCheck(),
|
BuildDLiveStatusCheck(),
|
||||||
BuildPeerTubeLiveStatusCheck()
|
BuildPeerTubeLiveStatusCheck(),
|
||||||
|
BuildOwncastLiveStatusCheck()
|
||||||
];
|
];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -334,6 +336,14 @@ public class BotServices
|
|||||||
return Task.CompletedTask;
|
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()
|
private async Task BuildParti()
|
||||||
{
|
{
|
||||||
var settings = await SettingsProvider.GetMultipleValuesAsync([BuiltIn.Keys.Proxy, BuiltIn.Keys.PartiEnabled]);
|
var settings = await SettingsProvider.GetMultipleValuesAsync([BuiltIn.Keys.Proxy, BuiltIn.Keys.PartiEnabled]);
|
||||||
|
|||||||
92
KfChatDotNetBot/Services/Owncast.cs
Normal file
92
KfChatDotNetBot/Services/Owncast.cs
Normal 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; }
|
||||||
|
}
|
||||||
@@ -976,7 +976,23 @@ public static class BuiltIn
|
|||||||
Description = "Special options for Twitch streams captured with Streamlink",
|
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",
|
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
|
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
|
public static class Keys
|
||||||
@@ -1087,5 +1103,7 @@ public static class BuiltIn
|
|||||||
public static string MoneyInitialBalance = "Money.InitialBalance";
|
public static string MoneyInitialBalance = "Money.InitialBalance";
|
||||||
public static string TwitchGraphQlCheckInterval = "TwitchGraphQl.CheckInterval";
|
public static string TwitchGraphQlCheckInterval = "TwitchGraphQl.CheckInterval";
|
||||||
public static string TwitchGraphQlPersistedCurrentlyLive = "TwitchGraphQl.PersistedCurrentlyLive";
|
public static string TwitchGraphQlPersistedCurrentlyLive = "TwitchGraphQl.PersistedCurrentlyLive";
|
||||||
|
public static string OwncastCheckInterval = "Owncast.CheckInterval";
|
||||||
|
public static string OwncastPersistedCurrentlyLive = "Owncast.PersistedCurrentlyLive";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user