Skip to content

Commit 933d5e7

Browse files
committed
Merge branch 'better-chain-events'
2 parents 8341807 + ba43fd9 commit 933d5e7

File tree

16 files changed

+428
-156
lines changed

16 files changed

+428
-156
lines changed

ProjectPlugins/CodexContractsPlugin/ChainMonitor/ChainState.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CodexContractsPlugin.Marketplace;
2+
using GethPlugin;
23
using Logging;
34
using System.Numerics;
45
using Utils;
@@ -11,7 +12,7 @@ public interface IChainStateChangeHandler
1112
void OnRequestFinished(IChainStateRequest request);
1213
void OnRequestFulfilled(IChainStateRequest request);
1314
void OnRequestCancelled(IChainStateRequest request);
14-
void OnSlotFilled(IChainStateRequest request, BigInteger slotIndex);
15+
void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex);
1516
void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex);
1617
}
1718

@@ -116,7 +117,7 @@ private void ApplyEvent(SlotFilledEventDTO request)
116117
if (r == null) return;
117118
r.Hosts.Add(request.Host, (int)request.SlotIndex);
118119
r.Log($"[{request.Block.BlockNumber}] SlotFilled (host:'{request.Host}', slotIndex:{request.SlotIndex})");
119-
handler.OnSlotFilled(r, request.SlotIndex);
120+
handler.OnSlotFilled(r, request.Host, request.SlotIndex);
120121
}
121122

122123
private void ApplyEvent(SlotFreedEventDTO request)

ProjectPlugins/CodexContractsPlugin/ChainMonitor/DoNothingChainEventHandler.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Numerics;
1+
using GethPlugin;
2+
using System.Numerics;
23

34
namespace CodexContractsPlugin.ChainMonitor
45
{
@@ -20,7 +21,7 @@ public void OnRequestFulfilled(IChainStateRequest request)
2021
{
2122
}
2223

23-
public void OnSlotFilled(IChainStateRequest request, BigInteger slotIndex)
24+
public void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex)
2425
{
2526
}
2627

Tools/BiblioTech/CommandHandler.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ namespace BiblioTech
1010
public class CommandHandler
1111
{
1212
private readonly DiscordSocketClient client;
13+
private readonly CustomReplacement replacement;
1314
private readonly BaseCommand[] commands;
1415
private readonly ILog log;
1516

16-
public CommandHandler(ILog log, DiscordSocketClient client, params BaseCommand[] commands)
17+
public CommandHandler(ILog log, DiscordSocketClient client, CustomReplacement replacement, params BaseCommand[] commands)
1718
{
1819
this.client = client;
20+
this.replacement = replacement;
1921
this.commands = commands;
2022
this.log = log;
2123
client.Ready += Client_Ready;
@@ -31,7 +33,7 @@ private async Task Client_Ready()
3133
var adminChannels = guild.TextChannels.Where(Program.AdminChecker.IsAdminChannel).ToArray();
3234
if (adminChannels == null || !adminChannels.Any()) throw new Exception("No admin message channel");
3335
Program.AdminChecker.SetAdminChannel(adminChannels.First());
34-
Program.RoleDriver = new RoleDriver(client, log);
36+
Program.RoleDriver = new RoleDriver(client, log, replacement);
3537

3638
var builders = commands.Select(c =>
3739
{

Tools/BiblioTech/Commands/AdminCommand.cs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BiblioTech.Options;
2+
using BiblioTech.Rewards;
23

34
namespace BiblioTech.Commands
45
{
@@ -10,12 +11,14 @@ public class AdminCommand : BaseCommand
1011
private readonly AddSprCommand addSprCommand;
1112
private readonly ClearSprsCommand clearSprsCommand;
1213
private readonly GetSprCommand getSprCommand;
14+
private readonly LogReplaceCommand logReplaceCommand;
1315

14-
public AdminCommand(SprCommand sprCommand)
16+
public AdminCommand(SprCommand sprCommand, CustomReplacement replacement)
1517
{
1618
addSprCommand = new AddSprCommand(sprCommand);
1719
clearSprsCommand = new ClearSprsCommand(sprCommand);
1820
getSprCommand = new GetSprCommand(sprCommand);
21+
logReplaceCommand = new LogReplaceCommand(replacement);
1922
}
2023

2124
public override string Name => "admin";
@@ -29,7 +32,8 @@ public AdminCommand(SprCommand sprCommand)
2932
whoIsCommand,
3033
addSprCommand,
3134
clearSprsCommand,
32-
getSprCommand
35+
getSprCommand,
36+
logReplaceCommand
3337
};
3438

3539
protected override async Task Invoke(CommandContext context)
@@ -52,6 +56,7 @@ protected override async Task Invoke(CommandContext context)
5256
await addSprCommand.CommandHandler(context);
5357
await clearSprsCommand.CommandHandler(context);
5458
await getSprCommand.CommandHandler(context);
59+
await logReplaceCommand.CommandHandler(context);
5560
}
5661

5762
public class ClearUserAssociationCommand : SubCommandOption
@@ -194,7 +199,7 @@ protected override async Task onSubCommand(CommandContext context)
194199
}
195200
}
196201

197-
public class GetSprCommand: SubCommandOption
202+
public class GetSprCommand : SubCommandOption
198203
{
199204
private readonly SprCommand sprCommand;
200205

@@ -210,5 +215,56 @@ protected override async Task onSubCommand(CommandContext context)
210215
await context.Followup("SPRs: " + string.Join(", ", sprCommand.Get().Select(s => $"'{s}'")));
211216
}
212217
}
218+
219+
public class LogReplaceCommand : SubCommandOption
220+
{
221+
private readonly CustomReplacement replacement;
222+
private readonly StringOption fromOption = new StringOption("from", "string to replace", true);
223+
private readonly StringOption toOption = new StringOption("to", "string to replace with", false);
224+
225+
public LogReplaceCommand(CustomReplacement replacement)
226+
: base(name: "logreplace",
227+
description: "Replaces all occurances of 'from' with 'to' in ChainEvent messages. Leave 'to' empty to remove a replacement.")
228+
{
229+
this.replacement = replacement;
230+
}
231+
232+
public override CommandOption[] Options => new[] { fromOption, toOption };
233+
234+
protected override async Task onSubCommand(CommandContext context)
235+
{
236+
var from = await fromOption.Parse(context);
237+
var to = await toOption.Parse(context);
238+
239+
if (string.IsNullOrEmpty(from))
240+
{
241+
await context.Followup("'from' not received");
242+
return;
243+
}
244+
245+
if (from.Length < 5)
246+
{
247+
await context.Followup("'from' must be length 5 or greater.");
248+
return;
249+
}
250+
251+
if (string.IsNullOrEmpty(to))
252+
{
253+
replacement.Remove(from);
254+
await context.Followup($"Replace for '{from}' removed.");
255+
}
256+
else
257+
{
258+
if (to.Length < 5)
259+
{
260+
await context.Followup("'to' must be length 5 or greater.");
261+
return;
262+
}
263+
264+
replacement.Add(from, to);
265+
await context.Followup($"Replace added '{from}' -->> '{to}'.");
266+
}
267+
}
268+
}
213269
}
214270
}

Tools/BiblioTech/Program.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace BiblioTech
1111
public class Program
1212
{
1313
private DiscordSocketClient client = null!;
14+
private readonly CustomReplacement replacement = new CustomReplacement();
1415

1516
public static Configuration Config { get; private set; } = null!;
1617
public static UserRepo UserRepo { get; } = new UserRepo();
@@ -73,13 +74,13 @@ private async Task StartDiscordBot()
7374
var notifyCommand = new NotifyCommand();
7475
var associateCommand = new UserAssociateCommand(notifyCommand);
7576
var sprCommand = new SprCommand();
76-
var handler = new CommandHandler(Log, client,
77+
var handler = new CommandHandler(Log, client, replacement,
7778
new GetBalanceCommand(associateCommand),
7879
new MintCommand(associateCommand),
7980
sprCommand,
8081
associateCommand,
8182
notifyCommand,
82-
new AdminCommand(sprCommand),
83+
new AdminCommand(sprCommand, replacement),
8384
new MarketCommand()
8485
);
8586

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using Discord.WebSocket;
2+
using Logging;
3+
4+
namespace BiblioTech.Rewards
5+
{
6+
public class ChainEventsSender
7+
{
8+
private readonly ILog log;
9+
private readonly CustomReplacement replacement;
10+
private readonly SocketTextChannel? eventsChannel;
11+
12+
public ChainEventsSender(ILog log, CustomReplacement replacement, SocketTextChannel? eventsChannel)
13+
{
14+
this.log = log;
15+
this.replacement = replacement;
16+
this.eventsChannel = eventsChannel;
17+
}
18+
19+
public async Task ProcessChainEvents(string[] eventsOverview)
20+
{
21+
if (eventsChannel == null || eventsOverview == null || !eventsOverview.Any()) return;
22+
try
23+
{
24+
await Task.Run(async () =>
25+
{
26+
var users = Program.UserRepo.GetAllUserData();
27+
28+
foreach (var e in eventsOverview)
29+
{
30+
if (!string.IsNullOrEmpty(e))
31+
{
32+
var @event = ApplyReplacements(users, e);
33+
await eventsChannel.SendMessageAsync(@event);
34+
await Task.Delay(3000);
35+
}
36+
}
37+
});
38+
}
39+
catch (Exception ex)
40+
{
41+
log.Error("Failed to process chain events: " + ex);
42+
}
43+
}
44+
45+
private string ApplyReplacements(UserData[] users, string msg)
46+
{
47+
var result = ApplyUserAddressReplacements(users, msg);
48+
result = ApplyCustomReplacements(result);
49+
return result;
50+
}
51+
52+
private string ApplyUserAddressReplacements(UserData[] users, string msg)
53+
{
54+
foreach (var user in users)
55+
{
56+
if (user.CurrentAddress != null &&
57+
!string.IsNullOrEmpty(user.CurrentAddress.Address) &&
58+
!string.IsNullOrEmpty(user.Name))
59+
{
60+
msg = msg.Replace(user.CurrentAddress.Address, user.Name);
61+
}
62+
}
63+
64+
return msg;
65+
}
66+
67+
private string ApplyCustomReplacements(string result)
68+
{
69+
return replacement.Apply(result);
70+
}
71+
}
72+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace BiblioTech.Rewards
2+
{
3+
public class CustomReplacement
4+
{
5+
private readonly Dictionary<string, string> replacements = new Dictionary<string, string>();
6+
7+
public void Add(string from, string to)
8+
{
9+
if (replacements.ContainsKey(from))
10+
{
11+
replacements[from] = to;
12+
}
13+
else
14+
{
15+
replacements.Add(from, to);
16+
}
17+
}
18+
19+
public void Remove(string from)
20+
{
21+
replacements.Remove(from);
22+
}
23+
24+
public string Apply(string msg)
25+
{
26+
var result = msg;
27+
foreach (var pair in replacements)
28+
{
29+
result.Replace(pair.Key, pair.Value);
30+
}
31+
return result;
32+
}
33+
}
34+
}

Tools/BiblioTech/Rewards/RoleDriver.cs

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ public class RoleDriver : IDiscordRoleDriver
1111
private readonly DiscordSocketClient client;
1212
private readonly ILog log;
1313
private readonly SocketTextChannel? rewardsChannel;
14-
private readonly SocketTextChannel? eventsChannel;
14+
private readonly ChainEventsSender eventsSender;
1515
private readonly RewardRepo repo = new RewardRepo();
1616

17-
public RoleDriver(DiscordSocketClient client, ILog log)
17+
public RoleDriver(DiscordSocketClient client, ILog log, CustomReplacement replacement)
1818
{
1919
this.client = client;
2020
this.log = log;
2121
rewardsChannel = GetChannel(Program.Config.RewardsChannelId);
22-
eventsChannel = GetChannel(Program.Config.ChainEventsChannelId);
22+
eventsSender = new ChainEventsSender(log, replacement, GetChannel(Program.Config.ChainEventsChannelId));
2323
}
2424

2525
public async Task GiveRewards(GiveRewardsCommand rewards)
@@ -31,7 +31,7 @@ public async Task GiveRewards(GiveRewardsCommand rewards)
3131
await ProcessRewards(rewards);
3232
}
3333

34-
await ProcessChainEvents(rewards.EventsOverview);
34+
await eventsSender.ProcessChainEvents(rewards.EventsOverview);
3535
}
3636

3737
private async Task ProcessRewards(GiveRewardsCommand rewards)
@@ -60,29 +60,6 @@ await LoadAllUsers(guild),
6060
return GetGuild().TextChannels.SingleOrDefault(c => c.Id == id);
6161
}
6262

63-
private async Task ProcessChainEvents(string[] eventsOverview)
64-
{
65-
if (eventsChannel == null || eventsOverview == null || !eventsOverview.Any()) return;
66-
try
67-
{
68-
await Task.Run(async () =>
69-
{
70-
foreach (var e in eventsOverview)
71-
{
72-
if (!string.IsNullOrEmpty(e))
73-
{
74-
await eventsChannel.SendMessageAsync(e);
75-
await Task.Delay(3000);
76-
}
77-
}
78-
});
79-
}
80-
catch (Exception ex)
81-
{
82-
log.Error("Failed to process chain events: " + ex);
83-
}
84-
}
85-
8663
private async Task<Dictionary<ulong, IGuildUser>> LoadAllUsers(SocketGuild guild)
8764
{
8865
log.Log("Loading all users..");

0 commit comments

Comments
 (0)