Compare commits
1 Commits
fb04f4003f
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| aa89578297 |
@@ -229,6 +229,7 @@ namespace TwitchChatTTS.Chat.Commands.Limits
|
||||
var temp = usage.Uses.Skip(sizeDiff);
|
||||
var tempSize = usage.Uses.Length - sizeDiff;
|
||||
usage.Uses = temp.Union(new DateTime[Math.Max(0, Limit.Count - tempSize)]).ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
@@ -256,7 +257,7 @@ namespace TwitchChatTTS.Chat.Commands.Limits
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
_rwls.ExitUpgradeableReadLock();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using HermesSocketLibrary.Requests.Messages;
|
||||
using Serilog;
|
||||
|
||||
@@ -9,109 +7,199 @@ namespace TwitchChatTTS.Chat.Groups
|
||||
{
|
||||
private readonly IDictionary<string, Group> _groups;
|
||||
private readonly IDictionary<long, ICollection<string>> _chatters;
|
||||
private readonly ReaderWriterLockSlim _rwls;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
|
||||
public ChatterGroupManager(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_groups = new ConcurrentDictionary<string, Group>();
|
||||
_chatters = new ConcurrentDictionary<long, ICollection<string>>();
|
||||
_groups = new Dictionary<string, Group>();
|
||||
_chatters = new Dictionary<long, ICollection<string>>();
|
||||
_rwls = new ReaderWriterLockSlim();
|
||||
}
|
||||
|
||||
public void Add(Group group)
|
||||
{
|
||||
_groups.Add(group.Id, group);
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_groups.Add(group.Id, group);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(long chatterId, string groupId)
|
||||
{
|
||||
if (_chatters.TryGetValue(chatterId, out var list))
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
if (!list.Contains(groupId))
|
||||
list.Add(groupId);
|
||||
if (_chatters.TryGetValue(chatterId, out var list))
|
||||
{
|
||||
if (!list.Contains(groupId))
|
||||
list.Add(groupId);
|
||||
}
|
||||
else
|
||||
_chatters.Add(chatterId, new List<string>() { groupId });
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
else
|
||||
_chatters.Add(chatterId, new List<string>() { groupId });
|
||||
}
|
||||
|
||||
public void Add(long chatter, ICollection<string> groupIds)
|
||||
{
|
||||
if (_chatters.TryGetValue(chatter, out var list))
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
foreach (var groupId in groupIds)
|
||||
if (!list.Contains(groupId))
|
||||
list.Add(groupId);
|
||||
if (_chatters.TryGetValue(chatter, out var list))
|
||||
{
|
||||
foreach (var groupId in groupIds)
|
||||
if (!list.Contains(groupId))
|
||||
list.Add(groupId);
|
||||
}
|
||||
else
|
||||
_chatters.Add(chatter, groupIds);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
else
|
||||
_chatters.Add(chatter, groupIds);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_groups.Clear();
|
||||
_chatters.Clear();
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_groups.Clear();
|
||||
_chatters.Clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public Group? Get(string groupId)
|
||||
{
|
||||
if (_groups.TryGetValue(groupId, out var group))
|
||||
return group;
|
||||
return null;
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (_groups.TryGetValue(groupId, out var group))
|
||||
return group;
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetGroupNamesFor(long chatter)
|
||||
{
|
||||
if (_chatters.TryGetValue(chatter, out var groups))
|
||||
return groups.Select(g => _groups.TryGetValue(g, out var group) ? group.Name : null)
|
||||
.Where(g => g != null)
|
||||
.Cast<string>();
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (_chatters.TryGetValue(chatter, out var groups))
|
||||
return groups.Select(g => _groups.TryGetValue(g, out var group) ? group.Name : null)
|
||||
.Where(g => g != null)
|
||||
.Cast<string>();
|
||||
|
||||
return Array.Empty<string>();
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPriorityFor(long chatter)
|
||||
{
|
||||
if (!_chatters.TryGetValue(chatter, out var groups))
|
||||
return 0;
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (!_chatters.TryGetValue(chatter, out var groups))
|
||||
return 0;
|
||||
|
||||
return GetPriorityFor(groups);
|
||||
return GetPriorityFor(groups);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPriorityFor(IEnumerable<string> groupIds)
|
||||
{
|
||||
var values = groupIds.Select(g => _groups.TryGetValue(g, out var group) ? group : null).Where(g => g != null);
|
||||
if (values.Any())
|
||||
return values.Max(g => g!.Priority);
|
||||
return 0;
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
var values = groupIds.Select(g => _groups.TryGetValue(g, out var group) ? group : null).Where(g => g != null);
|
||||
if (values.Any())
|
||||
return values.Max(g => g!.Priority);
|
||||
return 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public void Modify(Group group)
|
||||
{
|
||||
_groups[group.Id] = group;
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_groups[group.Id] = group;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(string groupId)
|
||||
{
|
||||
if (_groups.Remove(groupId))
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
foreach (var entry in _chatters)
|
||||
entry.Value.Remove(groupId);
|
||||
return true;
|
||||
if (_groups.Remove(groupId))
|
||||
{
|
||||
foreach (var entry in _chatters)
|
||||
entry.Value.Remove(groupId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Remove(long chatterId, string groupId)
|
||||
{
|
||||
if (_chatters.TryGetValue(chatterId, out var groups))
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
groups.Remove(groupId);
|
||||
_logger.Debug($"Removed chatter from group [chatter id: {chatterId}][group name: {_groups[groupId].Name}][group id: {groupId}]");
|
||||
return true;
|
||||
if (_chatters.TryGetValue(chatterId, out var groups))
|
||||
{
|
||||
groups.Remove(groupId);
|
||||
_logger.Debug($"Removed chatter from group [chatter id: {chatterId}][group name: {_groups[groupId].Name}][group id: {groupId}]");
|
||||
return true;
|
||||
}
|
||||
_logger.Debug($"Failed to remove chatter from group [chatter id: {chatterId}][group name: {_groups[groupId].Name}][group id: {groupId}]");
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
_logger.Debug($"Failed to remove chatter from group [chatter id: {chatterId}][group name: {_groups[groupId].Name}][group id: {groupId}]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,33 +5,51 @@ namespace TwitchChatTTS.Chat.Groups.Permissions
|
||||
{
|
||||
public class GroupPermissionManager : IGroupPermissionManager
|
||||
{
|
||||
private PermissionNode _root;
|
||||
private ILogger _logger;
|
||||
private readonly PermissionNode _root;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ReaderWriterLockSlim _rwls;
|
||||
|
||||
|
||||
public GroupPermissionManager(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_root = new PermissionNode(string.Empty, null, null);
|
||||
_rwls = new ReaderWriterLockSlim();
|
||||
}
|
||||
|
||||
|
||||
public bool? CheckIfAllowed(string path)
|
||||
{
|
||||
var res = Get(path)!.Allow;
|
||||
_logger.Debug($"Permission Node GET {path} = {res?.ToString() ?? "null"}");
|
||||
return res;
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
var res = Get(path)!.Allow;
|
||||
_logger.Debug($"Permission Node GET {path} = {res?.ToString() ?? "null"}");
|
||||
return res;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public bool? CheckIfDirectAllowed(string path)
|
||||
{
|
||||
var node = Get(path, nullIfMissing: true);
|
||||
if (node == null)
|
||||
return null;
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
var node = Get(path, nullIfMissing: true);
|
||||
if (node == null)
|
||||
return null;
|
||||
|
||||
var res = node.DirectAllow;
|
||||
_logger.Debug($"Permission Node GET {path} = {res?.ToString() ?? "null"} [direct]");
|
||||
return res;
|
||||
var res = node.DirectAllow;
|
||||
_logger.Debug($"Permission Node GET {path} = {res?.ToString() ?? "null"} [direct]");
|
||||
return res;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public bool? CheckIfAllowed(IEnumerable<string> groups, string path)
|
||||
@@ -64,31 +82,63 @@ namespace TwitchChatTTS.Chat.Groups.Permissions
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_root.Clear();
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_root.Clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(string path)
|
||||
{
|
||||
var node = Get(path);
|
||||
if (node == null || node.Parent == null)
|
||||
return false;
|
||||
|
||||
var parts = path.Split('.');
|
||||
var last = parts.Last();
|
||||
if (parts.Length > 1 && parts[parts.Length - 1] == node.Parent.Name || parts.Length == 1 && node.Parent.Name == null)
|
||||
_rwls.EnterUpgradeableReadLock();
|
||||
try
|
||||
{
|
||||
node.Parent.Remove(last);
|
||||
_logger.Debug($"Permission Node REMOVE priv {path}");
|
||||
return true;
|
||||
var node = Get(path);
|
||||
if (node == null || node.Parent == null)
|
||||
return false;
|
||||
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
var parts = path.Split('.');
|
||||
var last = parts.Last();
|
||||
if (parts.Length > 1 && parts[parts.Length - 1] == node.Parent.Name || parts.Length == 1 && node.Parent.Name == null)
|
||||
{
|
||||
node.Parent.Remove(last);
|
||||
_logger.Debug($"Permission Node REMOVE priv {path}");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitUpgradeableReadLock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Set(string path, bool? allow)
|
||||
{
|
||||
var node = Get(path, true);
|
||||
node!.Allow = allow;
|
||||
_logger.Debug($"Permission Node ADD {path} = {allow?.ToString() ?? "null"}");
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
var node = Get(path, true);
|
||||
node!.Allow = allow;
|
||||
_logger.Debug($"Permission Node ADD {path} = {allow?.ToString() ?? "null"}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
private PermissionNode? Get(string path, bool edit = false, bool nullIfMissing = false)
|
||||
|
||||
@@ -62,15 +62,15 @@ namespace TwitchChatTTS.Chat.Messaging
|
||||
|
||||
var emoteUsage = GetEmoteUsage(fragments);
|
||||
var tasks = new List<Task>();
|
||||
if (_obs.Streaming && !_user.Slave)
|
||||
if ((!_obs.Connected || _obs.Streaming) && !_user.Slave)
|
||||
{
|
||||
if (emoteUsage.NewEmotes.Any())
|
||||
tasks.Add(_hermes.SendEmoteDetails(emoteUsage.NewEmotes));
|
||||
if (emoteUsage.EmotesUsed.Any() && messageId != null && chatterId != null)
|
||||
tasks.Add(_hermes.SendEmoteUsage(messageId, chatterId.Value, emoteUsage.EmotesUsed));
|
||||
if (!string.IsNullOrEmpty(chatterLogin) && chatterId != null && !_user.Chatters.Contains(chatterId.Value))
|
||||
if (chatterId.HasValue && !_user.Chatters.Contains(chatterId.Value))
|
||||
{
|
||||
tasks.Add(_hermes.SendChatterDetails(chatterId.Value, chatterLogin));
|
||||
tasks.Add(_hermes.SendChatterDetails(chatterId.Value, chatterLogin!));
|
||||
_user.Chatters.Add(chatterId.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers
|
||||
|
||||
if (message.AnotherClient)
|
||||
{
|
||||
if (client.LoggedIn)
|
||||
_logger.Warning($"Another client has connected to the same account via {(message.WebLogin ? "web login" : "application")}.");
|
||||
_logger.Warning($"Another client has connected to the same account via {(message.WebLogin ? "web login" : "application")}.");
|
||||
return;
|
||||
}
|
||||
if (client.LoggedIn)
|
||||
@@ -51,6 +50,7 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers
|
||||
_user.TwitchUsername = message.UserName;
|
||||
_user.TwitchUserId = long.Parse(message.ProviderAccountId);
|
||||
_user.OwnerId = message.OwnerId;
|
||||
_user.StreamElementsOverlayKey = message.StreamElementsOverlayKey;
|
||||
_user.DefaultTTSVoice = message.DefaultTTSVoice;
|
||||
_user.VoicesAvailable = new ConcurrentDictionary<string, string>(message.TTSVoicesAvailable);
|
||||
_user.VoicesEnabled = new HashSet<string>(message.EnabledTTSVoices);
|
||||
@@ -58,7 +58,7 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers
|
||||
_user.NightbotConnection = message.Connections.FirstOrDefault(c => c.Default && c.Type == "nightbot") ?? message.Connections.FirstOrDefault(c => c.Type == "nightbot");
|
||||
if (_user.TwitchConnection != null)
|
||||
{
|
||||
_logger.Information("Twitch connection: " + _user.TwitchConnection.Name + " / " + _user.TwitchConnection.AccessToken);
|
||||
_logger.Debug("Twitch connection: " + _user.TwitchConnection.Name + " / " + _user.TwitchConnection.AccessToken);
|
||||
}
|
||||
|
||||
var filters = message.WordFilters.Where(f => f.Search != null && f.Replace != null).ToList();
|
||||
@@ -101,8 +101,9 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers
|
||||
}
|
||||
|
||||
_logger.Information("TTS is now ready.");
|
||||
_bus.Send(this, "tts_connected", _user);
|
||||
client.Ready = true;
|
||||
|
||||
_bus.Send(this, "tts_connected", _user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,35 +82,36 @@ namespace TwitchChatTTS.Hermes.Socket
|
||||
|
||||
public override async Task Connect()
|
||||
{
|
||||
_rwls.EnterWriteLock();
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (Connected)
|
||||
return;
|
||||
|
||||
_logger.Debug($"Attempting to connect to {URL}");
|
||||
await ConnectAsync(URL);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
|
||||
_logger.Debug($"Attempting to connect to {URL}");
|
||||
await ConnectAsync(URL);
|
||||
|
||||
}
|
||||
|
||||
private async Task Disconnect()
|
||||
{
|
||||
_rwls.EnterWriteLock();
|
||||
_rwls.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (!Connected)
|
||||
return;
|
||||
|
||||
await DisconnectAsync(new SocketDisconnectionEventArgs("Normal disconnection", "Disconnection was executed"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
|
||||
await DisconnectAsync(new SocketDisconnectionEventArgs("Normal disconnection", "Disconnection was executed"));
|
||||
}
|
||||
|
||||
public async Task CreateTTSVoice(string voiceName)
|
||||
@@ -437,13 +438,13 @@ namespace TwitchChatTTS.Hermes.Socket
|
||||
_logger.Warning("Tom to Speech websocket client is not connected. Not sending a message.");
|
||||
return;
|
||||
}
|
||||
|
||||
await base.Send(opcode, message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitReadLock();
|
||||
}
|
||||
|
||||
await base.Send(opcode, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Text.Json;
|
||||
using Serilog;
|
||||
using TwitchChatTTS.Chat.Groups;
|
||||
|
||||
@@ -8,13 +7,11 @@ namespace TwitchChatTTS.Hermes.Socket.Requests
|
||||
{
|
||||
public string Name => "delete_group";
|
||||
private readonly IChatterGroupManager _groups;
|
||||
private readonly JsonSerializerOptions _options;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DeleteGroupAck(IChatterGroupManager groups, JsonSerializerOptions options, ILogger logger)
|
||||
public DeleteGroupAck(IChatterGroupManager groups, ILogger logger)
|
||||
{
|
||||
_groups = groups;
|
||||
_options = options;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,13 @@ public class SevenApiClient
|
||||
{
|
||||
_logger.Debug($"Fetching 7tv information using Twitch Id [twitch id: {twitchId}]");
|
||||
var details = await _web.GetJson<UserDetails>($"{API_URL}/users/twitch/" + twitchId);
|
||||
return details?.EmoteSet;
|
||||
_logger.Information($"Fetched 7tv emotes [count: {details?.EmoteSet.EmoteCount ?? -1}]");
|
||||
if (details?.EmoteSet == null)
|
||||
{
|
||||
_logger.Warning("Could not find 7tv emotes linked to your Twitch account.");
|
||||
return null;
|
||||
}
|
||||
return details.EmoteSet;
|
||||
}
|
||||
catch (JsonException e)
|
||||
{
|
||||
|
||||
10
TTS.cs
10
TTS.cs
@@ -22,8 +22,8 @@ namespace TwitchChatTTS
|
||||
public class TTS : IHostedService
|
||||
{
|
||||
public const int MAJOR_VERSION = 4;
|
||||
public const int MINOR_VERSION = 8;
|
||||
public const int PATCH_VERSION = 2;
|
||||
public const int MINOR_VERSION = 9;
|
||||
public const int PATCH_VERSION = 3;
|
||||
|
||||
private readonly User _user;
|
||||
private readonly HermesApiClient _hermesApiClient;
|
||||
@@ -84,7 +84,7 @@ namespace TwitchChatTTS
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_configuration.Hermes?.Token))
|
||||
{
|
||||
_logger.Error("Tom to Speech API token not set in the yml file.");
|
||||
_logger.Error("Tom to Speech API token not set in the configuration file.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace TwitchChatTTS
|
||||
_logger.Error("Failed to fetch latest TTS version. Something went wrong.");
|
||||
return;
|
||||
}
|
||||
if (hermesVersion.MajorVersion > TTS.MAJOR_VERSION || hermesVersion.MajorVersion == TTS.MAJOR_VERSION && (hermesVersion.MinorVersion > TTS.MINOR_VERSION || hermesVersion.MinorVersion == TTS.MINOR_VERSION && (hermesVersion.PatchVersion == null || hermesVersion.PatchVersion > TTS.PATCH_VERSION)))
|
||||
if (hermesVersion.MajorVersion > MAJOR_VERSION || hermesVersion.MajorVersion == MAJOR_VERSION && (hermesVersion.MinorVersion > MINOR_VERSION || hermesVersion.MinorVersion == MINOR_VERSION && (hermesVersion.PatchVersion == null || hermesVersion.PatchVersion > PATCH_VERSION)))
|
||||
{
|
||||
_logger.Information($"A new update for TTS is avaiable! Version {hermesVersion.MajorVersion}.{hermesVersion.MinorVersion}.{hermesVersion.PatchVersion} is available at {hermesVersion.Download}");
|
||||
var changes = hermesVersion.Changelog.Split("\n");
|
||||
@@ -111,9 +111,9 @@ namespace TwitchChatTTS
|
||||
}
|
||||
|
||||
var disposables = new List<IDisposable>();
|
||||
var connected = _bus.GetTopic("tts_connected");
|
||||
|
||||
// 7tv
|
||||
var connected = _bus.GetTopic("tts_connected");
|
||||
disposables.Add(connected.FirstAsync().Subscribe(async (data) =>
|
||||
{
|
||||
if (data.Value is not User user)
|
||||
|
||||
@@ -11,19 +11,23 @@ namespace TwitchChatTTS
|
||||
{
|
||||
public class TTSListening : IHostedService
|
||||
{
|
||||
private const string TTS_API_URL = "https://api.streamelements.com/kappa/v2/speech";
|
||||
|
||||
private readonly AudioPlaybackEngine _playback;
|
||||
private readonly TTSPlayer _player;
|
||||
private readonly TTSConsumer _consumer;
|
||||
private readonly IDisposable _subscription;
|
||||
private readonly User _user;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
|
||||
public TTSListening(AudioPlaybackEngine playback, TTSPlayer player, TTSPublisher publisher, TTSConsumer consumer, ILogger logger)
|
||||
public TTSListening(AudioPlaybackEngine playback, TTSPlayer player, TTSPublisher publisher, TTSConsumer consumer, User user, ILogger logger)
|
||||
{
|
||||
_playback = playback;
|
||||
_player = player;
|
||||
_consumer = consumer;
|
||||
_subscription = publisher.Subscribe(consumer);
|
||||
_user = user;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -115,7 +119,7 @@ namespace TwitchChatTTS
|
||||
|
||||
try
|
||||
{
|
||||
string url = $"https://api.streamelements.com/kappa/v2/speech?voice={message.Voice}&text={HttpUtility.UrlEncode(message.Message.Trim())}";
|
||||
string url = $"{TTS_API_URL}?key={_user.StreamElementsOverlayKey}&voice={message.Voice}&text={HttpUtility.UrlEncode(message.Message.Trim())}";
|
||||
var nws = new NetworkWavSound(url);
|
||||
var provider = new CachedWavProvider(nws);
|
||||
var data = _playback.ConvertSound(provider);
|
||||
|
||||
@@ -110,37 +110,29 @@ namespace TwitchChatTTS.Twitch.Redemptions
|
||||
|
||||
private void Add(string twitchRedemptionId, string redemptionId)
|
||||
{
|
||||
_rwls.EnterWriteLock();
|
||||
try
|
||||
if (!_redeems.TryGetValue(twitchRedemptionId, out var redeems))
|
||||
_redeems.Add(twitchRedemptionId, redeems = new List<string>());
|
||||
|
||||
var item = _redemptions.TryGetValue(redemptionId, out var r) ? r : null;
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
var redemptions = redeems.Select(r => _redemptions.TryGetValue(r, out var rr) ? rr : null);
|
||||
bool added = false;
|
||||
for (int i = 0; i < redeems.Count; i++)
|
||||
{
|
||||
if (!_redeems.TryGetValue(twitchRedemptionId, out var redeems))
|
||||
_redeems.Add(twitchRedemptionId, redeems = new List<string>());
|
||||
|
||||
var item = _redemptions.TryGetValue(redemptionId, out var r) ? r : null;
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
var redemptions = redeems.Select(r => _redemptions.TryGetValue(r, out var rr) ? rr : null);
|
||||
bool added = false;
|
||||
for (int i = 0; i < redeems.Count; i++)
|
||||
if (redeems[i] != null && _redemptions.TryGetValue(redeems[i], out var rr))
|
||||
{
|
||||
if (redeems[i] != null && _redemptions.TryGetValue(redeems[i], out var rr))
|
||||
if (item.Order > rr.Order)
|
||||
{
|
||||
if (item.Order > rr.Order)
|
||||
{
|
||||
redeems.Insert(i, redemptionId);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
redeems.Insert(i, redemptionId);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added)
|
||||
redeems.Add(redemptionId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rwls.ExitWriteLock();
|
||||
}
|
||||
if (!added)
|
||||
redeems.Add(redemptionId);
|
||||
_logger.Debug($"Added redemption action [redemption id: {redemptionId}][twitch redemption id: {twitchRedemptionId}]");
|
||||
}
|
||||
|
||||
|
||||
@@ -120,8 +120,7 @@ namespace TwitchChatTTS.Twitch.Socket.Handlers
|
||||
private int GetTotalBits(TwitchChatFragment[] fragments)
|
||||
{
|
||||
return fragments.Where(f => f.Type == "cheermote" && f.Cheermote != null)
|
||||
.Select(f => f.Cheermote!.Bits)
|
||||
.Sum();
|
||||
.Sum(f => f.Cheermote!.Bits);
|
||||
}
|
||||
|
||||
private string GetPermissionPath(string? customRewardId, int bits)
|
||||
|
||||
@@ -142,14 +142,14 @@ namespace TwitchChatTTS.Twitch.Socket
|
||||
_logger.Warning($"Twitch client has been identified, but isn't main or backup [client: {client.UID}][main: {_identified.UID}][backup: {_backup?.UID}]");
|
||||
clientDisconnect = true;
|
||||
}
|
||||
|
||||
if (clientDisconnect)
|
||||
client.DisconnectAsync(new SocketDisconnectionEventArgs("Closed", "No need for a tertiary client.")).Wait();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_mutex.ReleaseMutex();
|
||||
}
|
||||
|
||||
if (clientDisconnect)
|
||||
await client.DisconnectAsync(new SocketDisconnectionEventArgs("Closed", "No need for a tertiary client."));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ namespace TwitchChatTTS.Twitch.Socket
|
||||
while (current < total)
|
||||
{
|
||||
var size = Encoding.UTF8.GetBytes(content.Substring(current), array);
|
||||
await _socket!.SendAsync(array, WebSocketMessageType.Text, current + size >= total, _cts!.Token);
|
||||
await _socket!.SendAsync(array, WebSocketMessageType.Text, current + size >= total, CancellationToken.None);
|
||||
current += size;
|
||||
}
|
||||
_logger.Debug("Twitch TX #" + type + ": " + content);
|
||||
|
||||
1
User.cs
1
User.cs
@@ -15,6 +15,7 @@ namespace TwitchChatTTS
|
||||
public required string TwitchUsername { get; set; }
|
||||
public required string SevenEmoteSetId { get; set; }
|
||||
public long? OwnerId { get; set; }
|
||||
public required string StreamElementsOverlayKey { get; set; }
|
||||
|
||||
public Connection? TwitchConnection { get; set; }
|
||||
public Connection? NightbotConnection { get; set; }
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace TwitchChatTTS.Veadotube
|
||||
while (current < total)
|
||||
{
|
||||
var size = Encoding.UTF8.GetBytes(content.Substring(current), array);
|
||||
await _socket.SendAsync(array, WebSocketMessageType.Text, current + size >= total, _cts!.Token);
|
||||
await _socket.SendAsync(array, WebSocketMessageType.Text, current + size >= total, CancellationToken.None);
|
||||
current += size;
|
||||
}
|
||||
_logger.Debug($"Veado TX [message type: {typeof(T).Name}]: " + content);
|
||||
|
||||
Reference in New Issue
Block a user