mirror of
https://github.com/barelyprofessional/KfChatDotNet.git
synced 2026-05-02 04:22:04 -04:00
Added support for selectively overriding capture settings on a per-stream basis
This commit is contained in:
@@ -33,12 +33,35 @@ public enum StreamService
|
|||||||
KiwiPeerTube
|
KiwiPeerTube
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KickStreamMetaModel
|
public class BaseMetaModel
|
||||||
|
{
|
||||||
|
public CaptureOverridesModel? CaptureOverrides { get; set; } = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CaptureOverridesModel
|
||||||
|
{
|
||||||
|
// Options applicable to YtDlp will not work with Streamlink and vice versa
|
||||||
|
// That being said, some options are shared while still being explicitly marked as YtDlp
|
||||||
|
// This applies to CaptureYtDlpWorkingDirectory, CaptureYtDlpParentTerminal, and CaptureYtDlpScriptPath
|
||||||
|
public string? CaptureYtDlpBinaryPath { get; set; } = null;
|
||||||
|
public string? CaptureYtDlpWorkingDirectory { get; set; } = null;
|
||||||
|
public string? CaptureYtDlpCookiesFromBrowser { get; set; } = null;
|
||||||
|
public string? CaptureYtDlpOutputFormat { get; set; } = null;
|
||||||
|
public string? CaptureYtDlpParentTerminal { get; set; } = null;
|
||||||
|
public string? CaptureYtDlpScriptPath { get; set; } = null;
|
||||||
|
public string? CaptureYtDlpUserAgent { get; set; } = null;
|
||||||
|
public string? CaptureStreamlinkBinaryPath { get; set; } = null;
|
||||||
|
public string? CaptureStreamlinkOutputFormat { get; set; } = null;
|
||||||
|
public string? CaptureStreamlinkRemuxScript { get; set; } = null;
|
||||||
|
public string? CaptureStreamlinkTwitchOptions { get; set; } = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class KickStreamMetaModel : BaseMetaModel
|
||||||
{
|
{
|
||||||
public required int ChannelId { get; set; }
|
public required int ChannelId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PeerTubeMetaModel
|
public class PeerTubeMetaModel : BaseMetaModel
|
||||||
{
|
{
|
||||||
public required string AccountName { get; set; }
|
public required string AccountName { get; set; }
|
||||||
}
|
}
|
||||||
@@ -920,7 +920,7 @@ public class BotServices
|
|||||||
{
|
{
|
||||||
_logger.Info($"BossmanJack stream event came in. isLive => {isLive}");
|
_logger.Info($"BossmanJack stream event came in. isLive => {isLive}");
|
||||||
var settings = SettingsProvider.GetMultipleValuesAsync([
|
var settings = SettingsProvider.GetMultipleValuesAsync([
|
||||||
BuiltIn.Keys.TwitchBossmanJackUsername, BuiltIn.Keys.CaptureEnabled, BuiltIn.Keys.TwitchIcon
|
BuiltIn.Keys.TwitchBossmanJackUsername, BuiltIn.Keys.CaptureEnabled, BuiltIn.Keys.TwitchIcon, BuiltIn.Keys.CaptureStreamlinkBmjWorkingDirectory
|
||||||
]).Result;
|
]).Result;
|
||||||
var bmjUsername = settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value;
|
var bmjUsername = settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value;
|
||||||
|
|
||||||
@@ -930,7 +930,12 @@ public class BotServices
|
|||||||
if (settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
if (settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
||||||
{
|
{
|
||||||
_logger.Info("Capturing Bossman's stream");
|
_logger.Info("Capturing Bossman's stream");
|
||||||
_ = new StreamCapture($"https://www.twitch.tv/{settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value}", StreamCaptureMethods.Streamlink, _cancellationToken).CaptureAsync();
|
_ = new StreamCapture($"https://www.twitch.tv/{settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value}",
|
||||||
|
StreamCaptureMethods.Streamlink,
|
||||||
|
new CaptureOverridesModel
|
||||||
|
{
|
||||||
|
CaptureYtDlpWorkingDirectory = settings[BuiltIn.Keys.CaptureStreamlinkBmjWorkingDirectory].Value
|
||||||
|
}, _cancellationToken).CaptureAsync();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1025,6 +1030,7 @@ public class BotServices
|
|||||||
using var db = new ApplicationDbContext();
|
using var db = new ApplicationDbContext();
|
||||||
var channels = db.Streams.Where(s => s.Service == StreamService.Kick).Include(s => s.User);
|
var channels = db.Streams.Where(s => s.Service == StreamService.Kick).Include(s => s.User);
|
||||||
StreamDbModel? channel = null;
|
StreamDbModel? channel = null;
|
||||||
|
KickStreamMetaModel? meta = null;
|
||||||
foreach (var ch in channels)
|
foreach (var ch in channels)
|
||||||
{
|
{
|
||||||
if (ch.Metadata == null)
|
if (ch.Metadata == null)
|
||||||
@@ -1033,7 +1039,6 @@ public class BotServices
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
KickStreamMetaModel meta;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
meta = JsonSerializer.Deserialize<KickStreamMetaModel>(ch.Metadata) ??
|
meta = JsonSerializer.Deserialize<KickStreamMetaModel>(ch.Metadata) ??
|
||||||
@@ -1071,7 +1076,7 @@ public class BotServices
|
|||||||
if (channel.AutoCapture && settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
if (channel.AutoCapture && settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
||||||
{
|
{
|
||||||
_logger.Info($"{channel.StreamUrl} is configured to auto capture");
|
_logger.Info($"{channel.StreamUrl} is configured to auto capture");
|
||||||
_ = new StreamCapture(channel.StreamUrl, StreamCaptureMethods.YtDlp, _cancellationToken).CaptureAsync();
|
_ = new StreamCapture(channel.StreamUrl, StreamCaptureMethods.YtDlp, meta?.CaptureOverrides, _cancellationToken).CaptureAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,11 +1104,25 @@ public class BotServices
|
|||||||
identity = "@" + channel.User.KfUsername;
|
identity = "@" + channel.User.KfUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BaseMetaModel? meta = null;
|
||||||
|
if (channel.Metadata != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
meta = JsonSerializer.Deserialize<BaseMetaModel>(channel.Metadata);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error($"Failed to deserialize metadata for Parti stream: {channel.StreamUrl}");
|
||||||
|
_logger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_chatBot.SendChatMessage($"{identity} is live! {data.EventTitle} {url}", true);
|
_chatBot.SendChatMessage($"{identity} is live! {data.EventTitle} {url}", true);
|
||||||
if (channel.AutoCapture && settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
if (channel.AutoCapture && settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
||||||
{
|
{
|
||||||
_logger.Info($"{channel.StreamUrl} is configured to auto capture");
|
_logger.Info($"{channel.StreamUrl} is configured to auto capture");
|
||||||
_ = new StreamCapture(url, StreamCaptureMethods.YtDlp, _cancellationToken).CaptureAsync();
|
_ = new StreamCapture(url, StreamCaptureMethods.YtDlp, meta?.CaptureOverrides, _cancellationToken).CaptureAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1158,7 +1177,6 @@ public class BotServices
|
|||||||
$"{identity} is no longer live! :lossmanjack:", true);
|
$"{identity} is no longer live! :lossmanjack:", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Fix this so it aligns with the new Persisted Live setting instead of tracking separately
|
|
||||||
public async Task<bool> CheckBmjIsLive()
|
public async Task<bool> CheckBmjIsLive()
|
||||||
{
|
{
|
||||||
var isLive =
|
var isLive =
|
||||||
|
|||||||
@@ -72,10 +72,24 @@ public class DLive(ChatBot kfChatBot) : IDisposable
|
|||||||
|
|
||||||
await kfChatBot.SendChatMessageAsync($"{identity} is live! {status.Title} {stream.StreamUrl}", true);
|
await kfChatBot.SendChatMessageAsync($"{identity} is live! {status.Title} {stream.StreamUrl}", true);
|
||||||
|
|
||||||
|
BaseMetaModel? meta = null;
|
||||||
|
if (stream.Metadata != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
meta = JsonSerializer.Deserialize<BaseMetaModel>(stream.Metadata);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error($"Caught an exception when attempting to deserialize metadata for DLive stream {stream.StreamUrl}");
|
||||||
|
_logger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stream.AutoCapture && settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
if (stream.AutoCapture && settings[BuiltIn.Keys.CaptureEnabled].ToBoolean())
|
||||||
{
|
{
|
||||||
_logger.Info($"{stream.StreamUrl} is live and set to auto capture");
|
_logger.Info($"{stream.StreamUrl} is live and set to auto capture");
|
||||||
_ = new StreamCapture(stream.StreamUrl, StreamCaptureMethods.Streamlink, ct).CaptureAsync();
|
_ = new StreamCapture(stream.StreamUrl, StreamCaptureMethods.Streamlink, meta?.CaptureOverrides, ct).CaptureAsync();
|
||||||
}
|
}
|
||||||
currentlyLive.Add(username);
|
currentlyLive.Add(username);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class Owncast(ChatBot kfChatBot) : IDisposable
|
|||||||
if (!status.Online) continue;
|
if (!status.Online) continue;
|
||||||
await kfChatBot.SendChatMessageAsync("https://bossmanjack.tv restream is live!", true);
|
await kfChatBot.SendChatMessageAsync("https://bossmanjack.tv restream is live!", true);
|
||||||
if (!(await SettingsProvider.GetValueAsync(BuiltIn.Keys.CaptureEnabled)).ToBoolean()) continue;
|
if (!(await SettingsProvider.GetValueAsync(BuiltIn.Keys.CaptureEnabled)).ToBoolean()) continue;
|
||||||
_ = new StreamCapture("https://bossmanjack.tv", StreamCaptureMethods.YtDlp, ct).CaptureAsync();
|
_ = new StreamCapture("https://bossmanjack.tv", StreamCaptureMethods.YtDlp, null, ct).CaptureAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public class PeerTube(ChatBot kfChatBot) : IDisposable
|
|||||||
{
|
{
|
||||||
if (persistedLive.Contains(stream.Uuid)) continue;
|
if (persistedLive.Contains(stream.Uuid)) continue;
|
||||||
StreamDbModel? dbEntry = null;
|
StreamDbModel? dbEntry = null;
|
||||||
|
PeerTubeMetaModel? meta = null;
|
||||||
foreach (var row in streams)
|
foreach (var row in streams)
|
||||||
{
|
{
|
||||||
if (row.Metadata == null)
|
if (row.Metadata == null)
|
||||||
@@ -64,13 +65,16 @@ public class PeerTube(ChatBot kfChatBot) : IDisposable
|
|||||||
_logger.Error($"Stream ID {row.Id} has null metadata");
|
_logger.Error($"Stream ID {row.Id} has null metadata");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var meta = JsonSerializer.Deserialize<PeerTubeMetaModel>(row.Metadata);
|
meta = JsonSerializer.Deserialize<PeerTubeMetaModel>(row.Metadata);
|
||||||
if (meta == null)
|
if (meta == null)
|
||||||
{
|
{
|
||||||
_logger.Error($"Caught a null when deserializing the metadata for {row.Id}");
|
_logger.Error($"Caught a null when deserializing the metadata for {row.Id}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (meta.AccountName == stream.Account.Name) dbEntry = row;
|
|
||||||
|
if (meta.AccountName != stream.Account.Name) continue;
|
||||||
|
dbEntry = row;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (settings[BuiltIn.Keys.KiwiPeerTubeEnforceWhitelist].ToBoolean() && dbEntry == null)
|
if (settings[BuiltIn.Keys.KiwiPeerTubeEnforceWhitelist].ToBoolean() && dbEntry == null)
|
||||||
{
|
{
|
||||||
@@ -89,7 +93,7 @@ public class PeerTube(ChatBot kfChatBot) : IDisposable
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_logger.Info($"{stream.Url} is live and set to auto capture (if configured)");
|
_logger.Info($"{stream.Url} is live and set to auto capture (if configured)");
|
||||||
_ = new StreamCapture(stream.Url, StreamCaptureMethods.YtDlp, ct).CaptureAsync();
|
_ = new StreamCapture(stream.Url, StreamCaptureMethods.YtDlp, meta?.CaptureOverrides, ct).CaptureAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using KfChatDotNetBot.Models.DbModels;
|
||||||
using KfChatDotNetBot.Settings;
|
using KfChatDotNetBot.Settings;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ namespace KfChatDotNetBot.Services;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="streamUrl">Streamer URL</param>
|
/// <param name="streamUrl">Streamer URL</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod, CancellationToken ct = default)
|
public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod, CaptureOverridesModel? captureOverrides = null, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, Setting> _settings = SettingsProvider
|
private readonly Dictionary<string, Setting> _settings = SettingsProvider
|
||||||
.GetMultipleValuesAsync([BuiltIn.Keys.CaptureYtDlpBinaryPath, BuiltIn.Keys.CaptureYtDlpWorkingDirectory,
|
.GetMultipleValuesAsync([BuiltIn.Keys.CaptureYtDlpBinaryPath, BuiltIn.Keys.CaptureYtDlpWorkingDirectory,
|
||||||
@@ -38,7 +39,7 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
|
||||||
{
|
{
|
||||||
pStartInfoFileName = _settings[BuiltIn.Keys.CaptureYtDlpParentTerminal].Value!;
|
pStartInfoFileName = captureOverrides?.CaptureYtDlpParentTerminal ?? _settings[BuiltIn.Keys.CaptureYtDlpParentTerminal].Value!;
|
||||||
pStartInfoExecuteArgument = "-x";
|
pStartInfoExecuteArgument = "-x";
|
||||||
pStartInfoExecuteScript = scriptPath;
|
pStartInfoExecuteScript = scriptPath;
|
||||||
}
|
}
|
||||||
@@ -51,7 +52,7 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
{
|
{
|
||||||
FileName = pStartInfoFileName,
|
FileName = pStartInfoFileName,
|
||||||
ArgumentList = { pStartInfoExecuteArgument, pStartInfoExecuteScript },
|
ArgumentList = { pStartInfoExecuteArgument, pStartInfoExecuteScript },
|
||||||
WorkingDirectory = _settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value
|
WorkingDirectory = captureOverrides?.CaptureYtDlpWorkingDirectory ?? _settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process == null)
|
if (process == null)
|
||||||
@@ -94,7 +95,7 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
private async Task<string> CreateScriptAsync()
|
private async Task<string> CreateScriptAsync()
|
||||||
{
|
{
|
||||||
var random = Convert.ToHexString(Guid.NewGuid().ToByteArray()[..4]);
|
var random = Convert.ToHexString(Guid.NewGuid().ToByteArray()[..4]);
|
||||||
var scriptPath = Path.Join(_settings[BuiltIn.Keys.CaptureYtDlpScriptPath].Value,
|
var scriptPath = Path.Join(_settings[captureOverrides?.CaptureYtDlpScriptPath ?? BuiltIn.Keys.CaptureYtDlpScriptPath].Value,
|
||||||
$"bot_ytdlp_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}_{random}.sh");
|
$"bot_ytdlp_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}_{random}.sh");
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
@@ -105,9 +106,10 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
string captureLine;
|
string captureLine;
|
||||||
if (captureMethod == StreamCaptureMethods.YtDlp)
|
if (captureMethod == StreamCaptureMethods.YtDlp)
|
||||||
{
|
{
|
||||||
captureLine = $"{_settings[BuiltIn.Keys.CaptureYtDlpBinaryPath].Value} -o \"{_settings[BuiltIn.Keys.CaptureYtDlpOutputFormat].Value}\" " +
|
captureLine = $"{captureOverrides?.CaptureYtDlpBinaryPath ?? _settings[BuiltIn.Keys.CaptureYtDlpBinaryPath].Value} " +
|
||||||
$"--user-agent \"{_settings[BuiltIn.Keys.CaptureYtDlpUserAgent].Value}\" " +
|
$"-o \"{captureOverrides?.CaptureYtDlpOutputFormat ?? _settings[BuiltIn.Keys.CaptureYtDlpOutputFormat].Value}\" " +
|
||||||
$"--cookies-from-browser {_settings[BuiltIn.Keys.CaptureYtDlpCookiesFromBrowser].Value} " +
|
$"--user-agent \"{captureOverrides?.CaptureYtDlpUserAgent ?? _settings[BuiltIn.Keys.CaptureYtDlpUserAgent].Value}\" " +
|
||||||
|
$"--cookies-from-browser {captureOverrides?.CaptureYtDlpCookiesFromBrowser ?? _settings[BuiltIn.Keys.CaptureYtDlpCookiesFromBrowser].Value} " +
|
||||||
$"--write-info-json --wait-for-video 15 --merge-output-format mp4 --verbose {streamUrl}";
|
$"--write-info-json --wait-for-video 15 --merge-output-format mp4 --verbose {streamUrl}";
|
||||||
}
|
}
|
||||||
else if (captureMethod == StreamCaptureMethods.Streamlink)
|
else if (captureMethod == StreamCaptureMethods.Streamlink)
|
||||||
@@ -115,9 +117,10 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
var twitchOpts = string.Empty;
|
var twitchOpts = string.Empty;
|
||||||
if (streamUrl.Contains("twitch.tv"))
|
if (streamUrl.Contains("twitch.tv"))
|
||||||
{
|
{
|
||||||
twitchOpts = _settings[BuiltIn.Keys.CaptureStreamlinkTwitchOptions].Value;
|
twitchOpts = captureOverrides?.CaptureStreamlinkTwitchOptions ?? _settings[BuiltIn.Keys.CaptureStreamlinkTwitchOptions].Value;
|
||||||
}
|
}
|
||||||
captureLine = $"{_settings[BuiltIn.Keys.CaptureStreamlinkBinaryPath].Value} {twitchOpts} --output \"{_settings[BuiltIn.Keys.CaptureStreamlinkOutputFormat].Value}\" " +
|
captureLine = $"{captureOverrides?.CaptureStreamlinkBinaryPath ?? _settings[BuiltIn.Keys.CaptureStreamlinkBinaryPath].Value} {twitchOpts} " +
|
||||||
|
$"--output \"{captureOverrides?.CaptureStreamlinkOutputFormat ?? _settings[BuiltIn.Keys.CaptureStreamlinkOutputFormat].Value}\" " +
|
||||||
$"--retry-streams 15 --retry-max 10 {streamUrl} best";
|
$"--retry-streams 15 --retry-max 10 {streamUrl} best";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -129,7 +132,7 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
var remuxLine = string.Empty;
|
var remuxLine = string.Empty;
|
||||||
if (captureMethod == StreamCaptureMethods.Streamlink)
|
if (captureMethod == StreamCaptureMethods.Streamlink)
|
||||||
{
|
{
|
||||||
remuxLine = _settings[BuiltIn.Keys.CaptureStreamlinkRemuxScript].Value;
|
remuxLine = captureOverrides?.CaptureStreamlinkRemuxScript ?? _settings[BuiltIn.Keys.CaptureStreamlinkRemuxScript].Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
string scriptContent;
|
string scriptContent;
|
||||||
@@ -138,8 +141,8 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
{
|
{
|
||||||
// GetPathRoot on Windows returns the top level directory, e.g. "C:\". Assuming the working directory is on another drive such as D:
|
// GetPathRoot on Windows returns the top level directory, e.g. "C:\". Assuming the working directory is on another drive such as D:
|
||||||
// we'll need to swap to that drive letter, so this just trims off the \ to transform it to D: or whatever. UNC paths not supported
|
// we'll need to swap to that drive letter, so this just trims off the \ to transform it to D: or whatever. UNC paths not supported
|
||||||
scriptContent = $"{Path.GetPathRoot(_settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value)?.TrimEnd('\\')}{Environment.NewLine}" +
|
scriptContent = $"{Path.GetPathRoot(captureOverrides?.CaptureYtDlpWorkingDirectory ?? _settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value)?.TrimEnd('\\')}{Environment.NewLine}" +
|
||||||
$"CD {_settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value}{Environment.NewLine}" +
|
$"CD {captureOverrides?.CaptureYtDlpWorkingDirectory ?? _settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value}{Environment.NewLine}" +
|
||||||
$"{captureLine}{Environment.NewLine}" +
|
$"{captureLine}{Environment.NewLine}" +
|
||||||
$"{remuxLine}{Environment.NewLine}" +
|
$"{remuxLine}{Environment.NewLine}" +
|
||||||
$"PAUSE";
|
$"PAUSE";
|
||||||
@@ -147,7 +150,7 @@ public class StreamCapture(string streamUrl, StreamCaptureMethods captureMethod,
|
|||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
|
||||||
{
|
{
|
||||||
scriptContent = $"#!/bin/bash{Environment.NewLine}" +
|
scriptContent = $"#!/bin/bash{Environment.NewLine}" +
|
||||||
$"cd {_settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value}{Environment.NewLine}" +
|
$"cd {captureOverrides?.CaptureYtDlpWorkingDirectory ?? _settings[BuiltIn.Keys.CaptureYtDlpWorkingDirectory].Value}{Environment.NewLine}" +
|
||||||
$"{captureLine}{Environment.NewLine}" +
|
$"{captureLine}{Environment.NewLine}" +
|
||||||
$"{remuxLine}{Environment.NewLine}" +
|
$"{remuxLine}{Environment.NewLine}" +
|
||||||
$"read -p \"Press enter to exit\"";
|
$"read -p \"Press enter to exit\"";
|
||||||
|
|||||||
@@ -1061,6 +1061,13 @@ public static class BuiltIn
|
|||||||
Default = "300",
|
Default = "300",
|
||||||
ValueType = SettingValueType.Text,
|
ValueType = SettingValueType.Text,
|
||||||
Regex = WholeNumberRegex
|
Regex = WholeNumberRegex
|
||||||
|
},
|
||||||
|
new BuiltInSettingsModel
|
||||||
|
{
|
||||||
|
Key = Keys.CaptureStreamlinkBmjWorkingDirectory,
|
||||||
|
Description = "Working directory for BMJ's Twitch streams captured with streamlink",
|
||||||
|
Default = "/root/twitch/",
|
||||||
|
ValueType = SettingValueType.Text
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -1183,5 +1190,6 @@ public static class BuiltIn
|
|||||||
public static string BotImageChinkSelfDestructDelay = "Bot.Image.ChinkSelfDestructDelay";
|
public static string BotImageChinkSelfDestructDelay = "Bot.Image.ChinkSelfDestructDelay";
|
||||||
public static string BotRateLimitCooldownAutoDeleteDelay = "Bot.RateLimit.CooldownAutoDeleteDelay";
|
public static string BotRateLimitCooldownAutoDeleteDelay = "Bot.RateLimit.CooldownAutoDeleteDelay";
|
||||||
public static string BotRateLimitExpiredEntryCleanupInterval = "Bot.RateLimit.ExpiredEntryCleanupInterval";
|
public static string BotRateLimitExpiredEntryCleanupInterval = "Bot.RateLimit.ExpiredEntryCleanupInterval";
|
||||||
|
public static string CaptureStreamlinkBmjWorkingDirectory = "Bot.Streamlink.BmjWorkingDirectory";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user