Generation of raid tiles with channel names and streaming status
This commit is contained in:
parent
deda300eb2
commit
0aa931275b
19
App.axaml.cs
19
App.axaml.cs
@ -6,6 +6,7 @@ using Avalonia.Data.Core.Plugins;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using BetterRaid.ViewModels;
|
||||
using BetterRaid.Views;
|
||||
using TwitchLib.Api;
|
||||
using TwitchLib.Client;
|
||||
using TwitchLib.Client.Events;
|
||||
using TwitchLib.Client.Models;
|
||||
@ -20,6 +21,8 @@ public partial class App : Application
|
||||
public static string TokenClientId = "";
|
||||
public static string TokenClientSecret = "";
|
||||
public static string TokenClientAccess = "";
|
||||
public static TwitchClient? TwitchClient = null;
|
||||
public static TwitchAPI? TwitchAPI = null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@ -48,14 +51,18 @@ public partial class App : Application
|
||||
};
|
||||
|
||||
var customClient = new WebSocketClient(clientOptions);
|
||||
var client = new TwitchClient(customClient);
|
||||
TwitchClient = new TwitchClient(customClient);
|
||||
|
||||
client.Initialize(creds, TwitchChannelName);
|
||||
client.OnMessageReceived += OnMessageReceived;
|
||||
client.OnConnected += OnConnected;
|
||||
client.OnConnectionError += OnConnectionError;
|
||||
TwitchClient.Initialize(creds, TwitchChannelName);
|
||||
TwitchClient.OnMessageReceived += OnMessageReceived;
|
||||
TwitchClient.OnConnected += OnConnected;
|
||||
TwitchClient.OnConnectionError += OnConnectionError;
|
||||
|
||||
client.Connect();
|
||||
TwitchClient.Connect();
|
||||
|
||||
TwitchAPI = new TwitchAPI();
|
||||
TwitchAPI.Settings.ClientId = TokenClientId;
|
||||
TwitchAPI.Settings.AccessToken = TokenClientAccess;
|
||||
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncImageLoader.Avalonia" Version="3.3.0" />
|
||||
<PackageReference Include="Avalonia" Version="11.1.0" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.1.0" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.0" />
|
||||
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.002.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterRaid", "BetterRaid.csproj", "{25B567E7-5B84-4DF8-BAB4-1B802DC11876}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterRaid", "BetterRaid.csproj", "{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -11,10 +11,10 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{25B567E7-5B84-4DF8-BAB4-1B802DC11876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{25B567E7-5B84-4DF8-BAB4-1B802DC11876}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{25B567E7-5B84-4DF8-BAB4-1B802DC11876}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{25B567E7-5B84-4DF8-BAB4-1B802DC11876}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
14
Models/TwitchChannel.cs
Normal file
14
Models/TwitchChannel.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace BetterRaid.Models;
|
||||
|
||||
public class TwitchChannel
|
||||
{
|
||||
public string? BroadcasterId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool IsLive { get; set; }
|
||||
public int ViewerCount { get; set; }
|
||||
|
||||
public TwitchChannel(string channelName)
|
||||
{
|
||||
Name = channelName;
|
||||
}
|
||||
}
|
@ -2,7 +2,5 @@
|
||||
|
||||
public partial class MainWindowViewModel : ViewModelBase
|
||||
{
|
||||
#pragma warning disable CA1822 // Mark members as static
|
||||
public string Greeting => "Welcome to Avalonia!";
|
||||
#pragma warning restore CA1822 // Mark members as static
|
||||
|
||||
}
|
||||
|
@ -3,18 +3,29 @@
|
||||
xmlns:vm="using:BetterRaid.ViewModels"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="450"
|
||||
Width="600"
|
||||
Height="800"
|
||||
x:Class="BetterRaid.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
Title="BetterRaid">
|
||||
|
||||
<Design.DataContext>
|
||||
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||
<vm:MainWindowViewModel/>
|
||||
</Design.DataContext>
|
||||
|
||||
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<Grid
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
x:Name="raidGrid">
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Window>
|
||||
|
@ -1,11 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AsyncImageLoader;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Threading;
|
||||
using BetterRaid.Models;
|
||||
using BetterRaid.ViewModels;
|
||||
using TwitchLib.Client.Events;
|
||||
|
||||
namespace BetterRaid.Views;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private string[] _channelNames = [
|
||||
"Cedricun", // Ehrenbruder
|
||||
"ZanTal", // Ehrenschwester
|
||||
"PropzMaster",
|
||||
"Artimus83",
|
||||
"HyperonsLive",
|
||||
"theshroomlife",
|
||||
"Robocraft999",
|
||||
"sllikson",
|
||||
"Aron_dc",
|
||||
"AIEsports"
|
||||
];
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
PrepareRaidGrid();
|
||||
ConnectToTwitch();
|
||||
}
|
||||
|
||||
private void PrepareRaidGrid()
|
||||
{
|
||||
var rows = (int)Math.Ceiling(_channelNames.Length / 3.0);
|
||||
|
||||
for (var i = 0; i < rows; i++)
|
||||
{
|
||||
raidGrid.RowDefinitions.Add(new RowDefinition(GridLength.Parse("200")));
|
||||
}
|
||||
|
||||
var colIndex = 0;
|
||||
var rowIndex = 0;
|
||||
foreach (var channel in _channelNames)
|
||||
{
|
||||
var btn = new Button
|
||||
{
|
||||
Content = channel,
|
||||
DataContext = new TwitchChannel(channel),
|
||||
Margin = Thickness.Parse("5"),
|
||||
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Stretch,
|
||||
HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center,
|
||||
VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center
|
||||
};
|
||||
|
||||
Grid.SetColumn(btn, colIndex);
|
||||
Grid.SetRow(btn, rowIndex);
|
||||
|
||||
raidGrid.Children.Add(btn);
|
||||
|
||||
colIndex++;
|
||||
if (colIndex % 3 == 0)
|
||||
{
|
||||
colIndex = 0;
|
||||
rowIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ConnectToTwitch()
|
||||
{
|
||||
if (App.TwitchClient != null && App.TwitchAPI != null)
|
||||
{
|
||||
foreach (var c in raidGrid.Children)
|
||||
{
|
||||
if (c is Button btn)
|
||||
{
|
||||
var channel = (btn.DataContext as TwitchChannel)?.Name;
|
||||
|
||||
if (string.IsNullOrEmpty(channel) == false)
|
||||
{
|
||||
var channels = App.TwitchAPI.Helix.Search.SearchChannelsAsync(channel).Result;
|
||||
var exactChannel = channels.Channels.FirstOrDefault(c => c.BroadcasterLogin.ToLower() == channel.ToLower());
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (exactChannel != null)
|
||||
{
|
||||
if (btn.DataContext is TwitchChannel ctx)
|
||||
{
|
||||
ctx.BroadcasterId = exactChannel.Id;
|
||||
var ib = new ImageBrush();
|
||||
ImageBrushLoader.SetSource(ib, exactChannel.ThumbnailUrl);
|
||||
btn.Background = ib;
|
||||
|
||||
var streamInfo = App.TwitchAPI.Helix.Streams.GetStreamsAsync(userLogins: new List<string>([channel])).Result;
|
||||
var exactStreamInfo = streamInfo.Streams.FirstOrDefault(s => s.UserLogin.ToLower() == channel.ToLower());
|
||||
|
||||
if (exactStreamInfo != null)
|
||||
{
|
||||
if (exactChannel.IsLive)
|
||||
{
|
||||
btn.Foreground = new SolidColorBrush(new Color(byte.MaxValue, 0, byte.MaxValue, 0));
|
||||
btn.Content = $"{exactChannel.DisplayName} ({exactStreamInfo.ViewerCount})";
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.Foreground = new SolidColorBrush(new Color(byte.MaxValue, byte.MaxValue, 0, 0));
|
||||
btn.Content = $"{exactChannel.DisplayName} (Offline)";
|
||||
}
|
||||
|
||||
ctx.ViewerCount = exactStreamInfo.ViewerCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.Foreground = new SolidColorBrush(new Color(byte.MaxValue, byte.MaxValue, 0, 0));
|
||||
btn.Content = $"{exactChannel.DisplayName} (Offline)";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user