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 Avalonia.Markup.Xaml;
|
||||||
using BetterRaid.ViewModels;
|
using BetterRaid.ViewModels;
|
||||||
using BetterRaid.Views;
|
using BetterRaid.Views;
|
||||||
|
using TwitchLib.Api;
|
||||||
using TwitchLib.Client;
|
using TwitchLib.Client;
|
||||||
using TwitchLib.Client.Events;
|
using TwitchLib.Client.Events;
|
||||||
using TwitchLib.Client.Models;
|
using TwitchLib.Client.Models;
|
||||||
@ -20,6 +21,8 @@ public partial class App : Application
|
|||||||
public static string TokenClientId = "";
|
public static string TokenClientId = "";
|
||||||
public static string TokenClientSecret = "";
|
public static string TokenClientSecret = "";
|
||||||
public static string TokenClientAccess = "";
|
public static string TokenClientAccess = "";
|
||||||
|
public static TwitchClient? TwitchClient = null;
|
||||||
|
public static TwitchAPI? TwitchAPI = null;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@ -48,14 +51,18 @@ public partial class App : Application
|
|||||||
};
|
};
|
||||||
|
|
||||||
var customClient = new WebSocketClient(clientOptions);
|
var customClient = new WebSocketClient(clientOptions);
|
||||||
var client = new TwitchClient(customClient);
|
TwitchClient = new TwitchClient(customClient);
|
||||||
|
|
||||||
client.Initialize(creds, TwitchChannelName);
|
TwitchClient.Initialize(creds, TwitchChannelName);
|
||||||
client.OnMessageReceived += OnMessageReceived;
|
TwitchClient.OnMessageReceived += OnMessageReceived;
|
||||||
client.OnConnected += OnConnected;
|
TwitchClient.OnConnected += OnConnected;
|
||||||
client.OnConnectionError += OnConnectionError;
|
TwitchClient.OnConnectionError += OnConnectionError;
|
||||||
|
|
||||||
client.Connect();
|
TwitchClient.Connect();
|
||||||
|
|
||||||
|
TwitchAPI = new TwitchAPI();
|
||||||
|
TwitchAPI.Settings.ClientId = TokenClientId;
|
||||||
|
TwitchAPI.Settings.AccessToken = TokenClientAccess;
|
||||||
|
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AsyncImageLoader.Avalonia" Version="3.3.0" />
|
||||||
<PackageReference Include="Avalonia" Version="11.1.0" />
|
<PackageReference Include="Avalonia" Version="11.1.0" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.1.0" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.1.0" />
|
||||||
<PackageReference Include="Avalonia.Themes.Fluent" 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
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.5.002.0
|
VisualStudioVersion = 17.5.002.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
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
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -11,10 +11,10 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{25B567E7-5B84-4DF8-BAB4-1B802DC11876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{25B567E7-5B84-4DF8-BAB4-1B802DC11876}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{25B567E7-5B84-4DF8-BAB4-1B802DC11876}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{050F930D-FE73-4FA8-A05B-E659A4A0CEEA}.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}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
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
|
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:vm="using:BetterRaid.ViewModels"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
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:Class="BetterRaid.Views.MainWindow"
|
||||||
x:DataType="vm:MainWindowViewModel"
|
x:DataType="vm:MainWindowViewModel"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
Title="BetterRaid">
|
Title="BetterRaid">
|
||||||
|
|
||||||
<Design.DataContext>
|
<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/>
|
<vm:MainWindowViewModel/>
|
||||||
</Design.DataContext>
|
</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>
|
</Window>
|
||||||
|
@ -1,11 +1,134 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using AsyncImageLoader;
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
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;
|
namespace BetterRaid.Views;
|
||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
|
private string[] _channelNames = [
|
||||||
|
"Cedricun", // Ehrenbruder
|
||||||
|
"ZanTal", // Ehrenschwester
|
||||||
|
"PropzMaster",
|
||||||
|
"Artimus83",
|
||||||
|
"HyperonsLive",
|
||||||
|
"theshroomlife",
|
||||||
|
"Robocraft999",
|
||||||
|
"sllikson",
|
||||||
|
"Aron_dc",
|
||||||
|
"AIEsports"
|
||||||
|
];
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
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