Track rule reading in database, don't show popup locally (#7278)

This commit is contained in:
DrSmugleaf
2022-03-26 20:16:57 +01:00
committed by GitHub
parent 19d8824951
commit ca0fb3c6a2
13 changed files with 2302 additions and 53 deletions

View File

@@ -2,8 +2,6 @@ using Content.Client.EscapeMenu.UI;
using Robust.Client.ResourceManagement; using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
namespace Content.Client.Info namespace Content.Client.Info
{ {
@@ -62,12 +60,5 @@ namespace Content.Client.Info
info.InfoContainer.AddChild(new InfoSection(title, info.InfoContainer.AddChild(new InfoSection(title,
_resourceManager.ContentFileReadAllText($"/Server Info/{path}"), markup)); _resourceManager.ContentFileReadAllText($"/Server Info/{path}"), markup));
} }
protected override void Opened()
{
base.Opened();
_rulesManager.SaveLastReadTime();
}
} }
} }

View File

@@ -1,5 +1,3 @@
using System;
using System.Globalization;
using Content.Client.Lobby; using Content.Client.Lobby;
using Content.Client.Viewport; using Content.Client.Viewport;
using Content.Shared.CCVar; using Content.Shared.CCVar;
@@ -8,28 +6,33 @@ using Robust.Client.Console;
using Robust.Client.State; using Robust.Client.State;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Utility;
namespace Content.Client.Info; namespace Content.Client.Info;
public sealed class RulesManager : SharedRulesManager public sealed class RulesManager : SharedRulesManager
{ {
[Dependency] private readonly IResourceManager _resource = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!; [Dependency] private readonly IStateManager _stateManager = default!;
[Dependency] private readonly IClientConsoleHost _consoleHost = default!; [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly INetManager _netManager = default!; [Dependency] private readonly INetManager _netManager = default!;
private bool _shouldShowRules;
public void Initialize() public void Initialize()
{ {
_netManager.RegisterNetMessage<ShouldShowRulesPopupMessage>(OnShouldShowRules);
_netManager.RegisterNetMessage<ShowRulesPopupMessage>(OnShowRulesPopupMessage); _netManager.RegisterNetMessage<ShowRulesPopupMessage>(OnShowRulesPopupMessage);
_netManager.RegisterNetMessage<RulesAcceptedMessage>();
_stateManager.OnStateChanged += OnStateChanged; _stateManager.OnStateChanged += OnStateChanged;
} }
private void OnShouldShowRules(ShouldShowRulesPopupMessage message)
{
_shouldShowRules = true;
}
private void OnShowRulesPopupMessage(ShowRulesPopupMessage message) private void OnShowRulesPopupMessage(ShowRulesPopupMessage message)
{ {
ShowRules(message.PopupTime); ShowRules(message.PopupTime);
@@ -39,32 +42,15 @@ public sealed class RulesManager : SharedRulesManager
{ {
if (args.NewState is not (GameScreen or LobbyState)) if (args.NewState is not (GameScreen or LobbyState))
return; return;
_stateManager.OnStateChanged -= OnStateChanged;
var path = new ResourcePath($"/rules_last_seen_{_configManager.GetCVar(CCVars.ServerId)}"); if (!_shouldShowRules)
var showRules = true;
if (_resource.UserData.TryReadAllText(path, out var lastReadTimeText)
&& DateTime.TryParse(lastReadTimeText, null, DateTimeStyles.AssumeUniversal, out var lastReadTime))
showRules = lastReadTime < DateTime.UtcNow - TimeSpan.FromDays(60);
else
SaveLastReadTime();
if (!showRules)
return; return;
_shouldShowRules = false;
ShowRules(_configManager.GetCVar(CCVars.RulesWaitTime)); ShowRules(_configManager.GetCVar(CCVars.RulesWaitTime));
} }
/// <summary>
/// Ran when the user opens ("read") the rules, stores the new ID to disk.
/// </summary>
public void SaveLastReadTime()
{
using var sw = _resource.UserData.OpenWriteText(new ResourcePath($"/rules_last_seen_{_configManager.GetCVar(CCVars.ServerId)}"));
sw.Write(DateTime.UtcNow.ToUniversalTime());
}
private void ShowRules(float time) private void ShowRules(float time)
{ {
var rulesPopup = new RulesPopup var rulesPopup = new RulesPopup
@@ -83,6 +69,7 @@ public sealed class RulesManager : SharedRulesManager
private void OnAcceptPressed() private void OnAcceptPressed()
{ {
SaveLastReadTime(); var message = _netManager.CreateNetMessage<RulesAcceptedMessage>();
_netManager.ClientSendMessage(message);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
#nullable disable
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Content.Server.Database.Migrations.Postgres
{
public partial class PlayerReadRules : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "last_read_rules",
table: "player",
type: "timestamp with time zone",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "last_read_rules",
table: "player");
}
}
}

View File

@@ -387,6 +387,10 @@ namespace Content.Server.Database.Migrations.Postgres
.HasColumnType("timestamp with time zone") .HasColumnType("timestamp with time zone")
.HasColumnName("first_seen_time"); .HasColumnName("first_seen_time");
b.Property<DateTime?>("LastReadRules")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_read_rules");
b.Property<IPAddress>("LastSeenAddress") b.Property<IPAddress>("LastSeenAddress")
.IsRequired() .IsRequired()
.HasColumnType("inet") .HasColumnType("inet")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
#nullable disable
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Content.Server.Database.Migrations.Sqlite
{
public partial class PlayerReadRules : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "last_read_rules",
table: "player",
type: "TEXT",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "last_read_rules",
table: "player");
}
}
}

View File

@@ -355,6 +355,10 @@ namespace Content.Server.Database.Migrations.Sqlite
.HasColumnType("TEXT") .HasColumnType("TEXT")
.HasColumnName("first_seen_time"); .HasColumnName("first_seen_time");
b.Property<DateTime?>("LastReadRules")
.HasColumnType("TEXT")
.HasColumnName("last_read_rules");
b.Property<string>("LastSeenAddress") b.Property<string>("LastSeenAddress")
.IsRequired() .IsRequired()
.HasColumnType("TEXT") .HasColumnType("TEXT")

View File

@@ -249,6 +249,8 @@ namespace Content.Server.Database
// Data that changes with each round // Data that changes with each round
public List<Round> Rounds { get; set; } = null!; public List<Round> Rounds { get; set; } = null!;
public List<AdminLogPlayer> AdminLogs { get; set; } = null!; public List<AdminLogPlayer> AdminLogs { get; set; } = null!;
public DateTime? LastReadRules { get; set; }
} }
[Table("whitelist")] [Table("whitelist")]

View File

@@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@@ -10,13 +8,9 @@ using Content.Server.Administration.Logs;
using Content.Shared.Administration.Logs; using Content.Shared.Administration.Logs;
using Content.Shared.CharacterAppearance; using Content.Shared.CharacterAppearance;
using Content.Shared.Preferences; using Content.Shared.Preferences;
using Content.Shared.Species;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Robust.Shared.Enums; using Robust.Shared.Enums;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Server.Database namespace Content.Server.Database
@@ -774,6 +768,30 @@ namespace Content.Server.Database
await db.DbContext.SaveChangesAsync(); await db.DbContext.SaveChangesAsync();
} }
public async Task<DateTime?> GetLastReadRules(NetUserId player)
{
await using var db = await GetDb();
return await db.DbContext.Player
.Where(dbPlayer => dbPlayer.UserId == player)
.Select(dbPlayer => dbPlayer.LastReadRules)
.SingleOrDefaultAsync();
}
public async Task SetLastReadRules(NetUserId player, DateTime date)
{
await using var db = await GetDb();
var dbPlayer = await db.DbContext.Player.Where(dbPlayer => dbPlayer.UserId == player).SingleOrDefaultAsync();
if (dbPlayer == null)
{
return;
}
dbPlayer.LastReadRules = date;
await db.DbContext.SaveChangesAsync();
}
#endregion #endregion
#region Uploaded Resources Logs #region Uploaded Resources Logs

View File

@@ -1,6 +1,4 @@
using System; using System.Collections.Immutable;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text.Json; using System.Text.Json;
@@ -16,9 +14,6 @@ using Microsoft.Extensions.Logging;
using Npgsql; using Npgsql;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.ContentPack; using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Network; using Robust.Shared.Network;
using LogLevel = Robust.Shared.Log.LogLevel; using LogLevel = Robust.Shared.Log.LogLevel;
using MSLogLevel = Microsoft.Extensions.Logging.LogLevel; using MSLogLevel = Microsoft.Extensions.Logging.LogLevel;
@@ -193,6 +188,13 @@ namespace Content.Server.Database
Task PurgeUploadedResourceLogAsync(int days); Task PurgeUploadedResourceLogAsync(int days);
#endregion #endregion
#region Rules
Task<DateTime?> GetLastReadRules(NetUserId player);
Task SetLastReadRules(NetUserId player, DateTime time);
#endregion
} }
public sealed class ServerDbManager : IServerDbManager public sealed class ServerDbManager : IServerDbManager
@@ -473,6 +475,16 @@ namespace Content.Server.Database
return _db.PurgeUploadedResourceLogAsync(days); return _db.PurgeUploadedResourceLogAsync(days);
} }
public Task<DateTime?> GetLastReadRules(NetUserId player)
{
return _db.GetLastReadRules(player);
}
public Task SetLastReadRules(NetUserId player, DateTime time)
{
return _db.SetLastReadRules(player, time);
}
private DbContextOptions<PostgresServerDbContext> CreatePostgresOptions() private DbContextOptions<PostgresServerDbContext> CreatePostgresOptions()
{ {
var host = _cfg.GetCVar(CCVars.DatabasePgHost); var host = _cfg.GetCVar(CCVars.DatabasePgHost);

View File

@@ -1,15 +1,45 @@
using Content.Shared.Info; using System.Net;
using Robust.Shared.IoC; using Content.Server.Database;
using Content.Shared.Info;
using Robust.Shared.Network; using Robust.Shared.Network;
namespace Content.Server.Info; namespace Content.Server.Info;
public sealed class RulesManager : SharedRulesManager public sealed class RulesManager : SharedRulesManager
{ {
[Dependency] private readonly IServerDbManager _dbManager = default!;
[Dependency] private readonly INetManager _netManager = default!; [Dependency] private readonly INetManager _netManager = default!;
private static DateTime LastValidReadTime => DateTime.UtcNow - TimeSpan.FromDays(60);
public void Initialize() public void Initialize()
{ {
_netManager.RegisterNetMessage<ShouldShowRulesPopupMessage>();
_netManager.RegisterNetMessage<ShowRulesPopupMessage>(); _netManager.RegisterNetMessage<ShowRulesPopupMessage>();
_netManager.RegisterNetMessage<RulesAcceptedMessage>(OnRulesAccepted);
_netManager.Connected += OnConnected;
}
private async void OnConnected(object? sender, NetChannelArgs e)
{
if (IPAddress.IsLoopback(e.Channel.RemoteEndPoint.Address))
{
return;
}
var lastRead = await _dbManager.GetLastReadRules(e.Channel.UserId);
if (lastRead > LastValidReadTime)
{
return;
}
var message = _netManager.CreateNetMessage<ShouldShowRulesPopupMessage>();
_netManager.ServerSendMessage(message, e.Channel);
}
private async void OnRulesAccepted(RulesAcceptedMessage message)
{
var date = DateTime.UtcNow;
await _dbManager.SetLastReadRules(message.MsgChannel.UserId, date);
} }
} }

View File

@@ -1,12 +1,13 @@
using JetBrains.Annotations; using Lidgren.Network;
using Lidgren.Network;
using Robust.Shared.Network; using Robust.Shared.Network;
namespace Content.Shared.Info; namespace Content.Shared.Info;
public abstract class SharedRulesManager public abstract class SharedRulesManager
{ {
[UsedImplicitly] /// <summary>
/// Sent by the server to show the rules to the client instantly.
/// </summary>
public sealed class ShowRulesPopupMessage : NetMessage public sealed class ShowRulesPopupMessage : NetMessage
{ {
public override MsgGroups MsgGroup => MsgGroups.Command; public override MsgGroups MsgGroup => MsgGroups.Command;
@@ -23,4 +24,36 @@ public abstract class SharedRulesManager
buffer.Write(PopupTime); buffer.Write(PopupTime);
} }
} }
/// <summary>
/// Sent by the server when the client needs to display the rules on join.
/// </summary>
public sealed class ShouldShowRulesPopupMessage : NetMessage
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public override void ReadFromBuffer(NetIncomingMessage buffer)
{
}
public override void WriteToBuffer(NetOutgoingMessage buffer)
{
}
}
/// <summary>
/// Sent by the client when it has accepted the rules.
/// </summary>
public sealed class RulesAcceptedMessage : NetMessage
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public override void ReadFromBuffer(NetIncomingMessage buffer)
{
}
public override void WriteToBuffer(NetOutgoingMessage buffer)
{
}
}
} }