188 lines
6.5 KiB
C#
188 lines
6.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using BetterRaid.Attributes;
|
|
using BetterRaid.Extensions;
|
|
using BetterRaid.Models;
|
|
using TwitchLib.PubSub;
|
|
using TwitchLib.PubSub.Events;
|
|
|
|
namespace BetterRaid.Services.Implementations;
|
|
|
|
public class TwitchPubSubService : ITwitchPubSubService
|
|
{
|
|
private readonly Dictionary<PubSubType, List<PubSubListener>> _targets = new();
|
|
private readonly TwitchPubSub _sub;
|
|
|
|
public TwitchPubSubService()
|
|
{
|
|
_sub = new TwitchPubSub();
|
|
|
|
_sub.OnPubSubServiceConnected += OnSubOnOnPubSubServiceConnected;
|
|
_sub.OnPubSubServiceError += OnSubOnOnPubSubServiceError;
|
|
_sub.OnPubSubServiceClosed += OnSubOnOnPubSubServiceClosed;
|
|
_sub.OnListenResponse += OnSubOnOnListenResponse;
|
|
_sub.OnViewCount += OnSubOnOnViewCount;
|
|
|
|
_sub.Connect();
|
|
}
|
|
|
|
private void OnSubOnOnViewCount(object? sender, OnViewCountArgs args)
|
|
{
|
|
var listeners = _targets
|
|
.Where(x => x.Key == PubSubType.VideoPlayback)
|
|
.SelectMany(x => x.Value)
|
|
.Where(x => x.ChannelId == args.ChannelId)
|
|
.ToList();
|
|
|
|
foreach (var listener in listeners)
|
|
{
|
|
if (listener.Listener == null || listener.Instance == null)
|
|
continue;
|
|
|
|
try
|
|
{
|
|
if (listener.Listener.SetValue(listener.Instance, args.Viewers) == false)
|
|
{
|
|
Console.WriteLine($"[ERROR][{nameof(TwitchPubSubService)}] Failed to set {listener.Instance.GetType().Name}.{listener.Listener.Name} to {args.Viewers}");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"[DEBUG][{nameof(TwitchPubSubService)}] Setting {listener.Instance.GetType().Name}.{listener.Listener.Name} to {args.Viewers}");
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine($"[ERROR][{nameof(TwitchPubSubService)}] Exception while setting {listener.Instance?.GetType().Name}.{listener.Listener?.Name}: {e.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnSubOnOnListenResponse(object? sender, OnListenResponseArgs args)
|
|
{
|
|
Console.WriteLine($"Listen Response: {args.Topic}");
|
|
}
|
|
|
|
private void OnSubOnOnPubSubServiceClosed(object? sender, EventArgs args)
|
|
{
|
|
Console.WriteLine("PubSub Closed");
|
|
}
|
|
|
|
private void OnSubOnOnPubSubServiceError(object? sender, OnPubSubServiceErrorArgs args)
|
|
{
|
|
Console.WriteLine($"PubSub Error: {args.Exception.Message}");
|
|
}
|
|
|
|
private void OnSubOnOnPubSubServiceConnected(object? sender, EventArgs args)
|
|
{
|
|
Console.WriteLine("Connected to PubSub");
|
|
}
|
|
|
|
public void RegisterReceiver<T>(T receiver) where T : class
|
|
{
|
|
ArgumentNullException.ThrowIfNull(receiver, nameof(receiver));
|
|
|
|
Console.WriteLine($"[DEBUG][{nameof(TwitchPubSubService)}] Registering {receiver.GetType().Name}");
|
|
|
|
var type = typeof(T);
|
|
var publicTargets = type
|
|
.GetProperties()
|
|
.Concat(
|
|
type.GetFields() as MemberInfo[]
|
|
);
|
|
|
|
foreach (var target in publicTargets)
|
|
{
|
|
if (target.GetCustomAttribute<PubSubAttribute>() is not { } attr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var channelId =
|
|
type.GetProperty(attr.ChannelIdField)?.GetValue(receiver)?.ToString() ??
|
|
type.GetField(attr.ChannelIdField)?.GetValue(receiver)?.ToString();
|
|
|
|
if (string.IsNullOrEmpty(channelId))
|
|
{
|
|
Console.WriteLine($"[ERROR][{nameof(TwitchPubSubService)}] {target.Name} is missing ChannelIdField named {attr.ChannelIdField}");
|
|
continue;
|
|
}
|
|
|
|
switch (attr.Type)
|
|
{
|
|
case PubSubType.Bits:
|
|
break;
|
|
case PubSubType.ChannelPoints:
|
|
break;
|
|
case PubSubType.Follows:
|
|
break;
|
|
case PubSubType.Raids:
|
|
break;
|
|
case PubSubType.Subscriptions:
|
|
break;
|
|
case PubSubType.VideoPlayback:
|
|
Console.WriteLine($"[DEBUG][{nameof(TwitchPubSubService)}] Registering {target.Name} for {attr.Type}");
|
|
if (_targets.TryGetValue(PubSubType.VideoPlayback, out var value))
|
|
{
|
|
value.Add(new PubSubListener
|
|
{
|
|
ChannelId = channelId,
|
|
Instance = receiver,
|
|
Listener = target
|
|
});
|
|
}
|
|
else
|
|
{
|
|
_targets.Add(PubSubType.VideoPlayback, [
|
|
new PubSubListener
|
|
{
|
|
ChannelId = channelId,
|
|
Instance = receiver,
|
|
Listener = target
|
|
}
|
|
]);
|
|
}
|
|
|
|
_sub.ListenToVideoPlayback(channelId);
|
|
_sub.SendTopics(App.TwitchOAuthAccessToken);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UnregisterReceiver<T>(T receiver) where T : class
|
|
{
|
|
ArgumentNullException.ThrowIfNull(receiver, nameof(receiver));
|
|
|
|
foreach (var target in _targets)
|
|
{
|
|
var topic = target.Key;
|
|
var listener = target.Value.Where(x => x.Instance == receiver).ToList();
|
|
|
|
foreach (var l in listener)
|
|
{
|
|
switch (topic)
|
|
{
|
|
case PubSubType.Bits:
|
|
break;
|
|
case PubSubType.ChannelPoints:
|
|
break;
|
|
case PubSubType.Follows:
|
|
break;
|
|
case PubSubType.Raids:
|
|
break;
|
|
case PubSubType.Subscriptions:
|
|
break;
|
|
case PubSubType.VideoPlayback:
|
|
_sub.ListenToVideoPlayback(l.ChannelId);
|
|
_sub.SendTopics(App.TwitchOAuthAccessToken, true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
_targets[topic].RemoveAll(x => x.Instance == receiver);
|
|
}
|
|
}
|
|
} |