228 lines
7.8 KiB
C#
228 lines
7.8 KiB
C#
using System.Globalization;
|
|
using log4net;
|
|
using SQLiteEF;
|
|
using SteamApiWrapper.ReturnTypes;
|
|
using SteamGame = SteamApiWrapper.ReturnTypes.Game;
|
|
using Player = SQLiteEF.Player;
|
|
using SteamPlayer = SteamApiWrapper.ReturnTypes.Player;
|
|
using Steam = SteamApiWrapper.SteamApiWrapper;
|
|
|
|
namespace API;
|
|
|
|
public class Tracker : IDisposable
|
|
{
|
|
private readonly Thread _trackerThread;
|
|
private bool _running = true;
|
|
private ILog Log { get; } = LogManager.GetLogger(typeof(Tracker));
|
|
private TimeSpan Interval { get; init; }
|
|
|
|
public Tracker(IServiceProvider serviceProvider, IConfiguration configuration)
|
|
{
|
|
Interval = TimeSpan.Parse(configuration.GetValue<string>("UpdateInterval")!, CultureInfo.InvariantCulture);
|
|
_trackerThread = new (TrackerLoop);
|
|
_trackerThread.Start(serviceProvider);
|
|
}
|
|
|
|
internal void UpdatePlayers(Context context)
|
|
{
|
|
Log.Info("Updating Players");
|
|
Player[] dbPlayers = context.Players.ToArray();
|
|
SteamPlayer[] summaries = Steam.GetPlayerSummaries(dbPlayers.Select(p => p.SteamId).ToArray());
|
|
foreach (Player dbPlayer in dbPlayers)
|
|
{
|
|
if(summaries.All(summaryPlayer => summaryPlayer.steamid != dbPlayer.SteamId))
|
|
continue;
|
|
SteamPlayer summaryPlayer = summaries.First(summaryPlayer => summaryPlayer.steamid == dbPlayer.SteamId);
|
|
|
|
try
|
|
{
|
|
dbPlayer.Name = summaryPlayer.personaname;
|
|
dbPlayer.AvatarUrl = summaryPlayer.avatar;
|
|
dbPlayer.ProfileUrl = summaryPlayer.profileurl;
|
|
dbPlayer.UpdatedAt = DateTime.UtcNow;
|
|
context.SaveChanges();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void UpdatePlayer(Context context, Player player)
|
|
{
|
|
SteamPlayer[] summaries = Steam.GetPlayerSummaries([player.SteamId]);
|
|
if(summaries.All(summaryPlayer => summaryPlayer.steamid != player.SteamId))
|
|
return;
|
|
SteamPlayer summaryPlayer = summaries.First(summaryPlayer => summaryPlayer.steamid == player.SteamId);
|
|
|
|
try
|
|
{
|
|
player.Name = summaryPlayer.personaname;
|
|
player.AvatarUrl = summaryPlayer.avatar;
|
|
player.ProfileUrl = summaryPlayer.profileurl;
|
|
player.UpdatedAt = DateTime.UtcNow;
|
|
context.SaveChanges();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
}
|
|
}
|
|
|
|
internal void UpdateOwnedGames(Context context)
|
|
{
|
|
Log.Info("Updating Owned Games");
|
|
Player[] players = context.Players.ToArray();
|
|
foreach (Player player in players)
|
|
{
|
|
UpdateOwnedGamesPlayer(context, player);
|
|
}
|
|
}
|
|
|
|
internal void UpdateOwnedGamesPlayer(Context context, Player player)
|
|
{
|
|
Log.Debug($"Updating owned games for player {player}");
|
|
SteamGame[] ownedGames = Steam.GetOwnedGames(player.SteamId);
|
|
foreach (SteamGame ownedGame in ownedGames)
|
|
{
|
|
string? iconUrlStr = ownedGame.img_icon_url is not null
|
|
? $"http://media.steampowered.com/steamcommunity/public/images/apps/{ownedGame.appid}/{ownedGame.img_icon_url}.jpg"
|
|
: null;
|
|
string? logoUrlStr = ownedGame.img_logo_url is not null
|
|
? $"http://media.steampowered.com/steamcommunity/public/images/apps/{ownedGame.appid}/{ownedGame.img_logo_url}.jpg"
|
|
: null;
|
|
if (context.Games.Find(ownedGame.appid) is not { } game)
|
|
{
|
|
game = new(ownedGame.appid, ownedGame.name, iconUrlStr, logoUrlStr);
|
|
context.Games.Add(game);
|
|
}
|
|
else
|
|
{
|
|
game.Name = ownedGame.name;
|
|
game.IconUrl = iconUrlStr;
|
|
game.LogoUrl = logoUrlStr;
|
|
}
|
|
|
|
if (!player.Games.Contains(game))
|
|
{
|
|
context.Entry(player).Collection(p => p.Games).Load();
|
|
player.Games.Add(game);
|
|
context.Entry(game).Collection(g => g.PlayedBy).Load();
|
|
game.PlayedBy.Add(player);
|
|
context.Entry(player).Collection(p => p.TrackedTimes).Load();
|
|
player.TrackedTimes.Add(new (game, player, ownedGame.playtime_forever));
|
|
}
|
|
|
|
try
|
|
{
|
|
context.SaveChanges();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void UpdateGameTimes(Context context)
|
|
{
|
|
Log.Info("Updating Game Times");
|
|
Player[] players = context.Players.ToArray();
|
|
foreach (Player player in players)
|
|
{
|
|
UpdateGameTimesPlayer(context, player);
|
|
}
|
|
}
|
|
|
|
internal void UpdateGameTimesPlayer(Context context, Player player)
|
|
{
|
|
Log.Debug($"Updating game times for player {player}");
|
|
GetRecentlyPlayedGames recentlyPlayed = Steam.GetRecentlyPlayedGames(player.SteamId);
|
|
if (recentlyPlayed.total_count < 1)
|
|
return;
|
|
foreach (SteamGame recentlyPlayedGame in recentlyPlayed.games)
|
|
{
|
|
string? iconUrlStr = recentlyPlayedGame.img_icon_url is not null
|
|
? $"http://media.steampowered.com/steamcommunity/public/images/apps/{recentlyPlayedGame.appid}/{recentlyPlayedGame.img_icon_url}.jpg"
|
|
: null;
|
|
string? logoUrlStr = recentlyPlayedGame.img_logo_url is not null
|
|
? $"http://media.steampowered.com/steamcommunity/public/images/apps/{recentlyPlayedGame.appid}/{recentlyPlayedGame.img_logo_url}.jpg"
|
|
: null;
|
|
if (context.Games.Find(recentlyPlayedGame.appid) is not { } game)
|
|
{
|
|
game = new(recentlyPlayedGame.appid, recentlyPlayedGame.name, iconUrlStr, logoUrlStr);
|
|
context.Games.Add(game);
|
|
}
|
|
else
|
|
{
|
|
game.Name = recentlyPlayedGame.name;
|
|
game.IconUrl = iconUrlStr;
|
|
game.LogoUrl = logoUrlStr;
|
|
}
|
|
|
|
if (!player.Games.Contains(game))
|
|
{
|
|
context.Entry(player).Collection(p => p.Games).Load();
|
|
player.Games.Add(game);
|
|
context.Entry(game).Collection(g => g.PlayedBy).Load();
|
|
game.PlayedBy.Add(player);
|
|
}
|
|
|
|
context.Entry(player).Collection(p => p.TrackedTimes).Load();
|
|
player.TrackedTimes.Add(new (game, player, recentlyPlayedGame.playtime_forever));
|
|
|
|
try
|
|
{
|
|
context.SaveChanges();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void TrackerLoop(object? obj)
|
|
{
|
|
if (obj is not IServiceProvider serviceProvider)
|
|
{
|
|
Log.Fatal("Tracker loop wasn't started.");
|
|
return;
|
|
}
|
|
|
|
while (_running)
|
|
{
|
|
IServiceScope scope = serviceProvider.CreateScope();
|
|
Context context = scope.ServiceProvider.GetRequiredService<Context>();
|
|
UpdatePlayers(context);
|
|
UpdateOwnedGames(context);
|
|
UpdateGameTimes(context);
|
|
scope.Dispose();
|
|
try
|
|
{
|
|
Thread.Sleep(Interval);
|
|
}
|
|
catch (ThreadInterruptedException)
|
|
{
|
|
Log.Debug("Thread interrupted");
|
|
}
|
|
catch (ThreadAbortException)
|
|
{
|
|
_running = false;
|
|
}
|
|
}
|
|
Log.Info("Thread exited");
|
|
}
|
|
|
|
public void ForceLoop()
|
|
{
|
|
_trackerThread.Interrupt();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_running = false;
|
|
_trackerThread.Interrupt();
|
|
}
|
|
} |