Bump version to 1.1.2
Cleaner item list display Allow full item list as file Fixed online status message with new handler
This commit is contained in:
parent
a55af9f667
commit
735bc8e8ae
@ -6,7 +6,7 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
<Version>1.1.1</Version>
|
<Version>1.1.2</Version>
|
||||||
<Authors>Michael Chen</Authors>
|
<Authors>Michael Chen</Authors>
|
||||||
<Company>$(Authors)</Company>
|
<Company>$(Authors)</Company>
|
||||||
<RepositoryUrl>https://gitlab.com/chenmichael/mcdiscordbot</RepositoryUrl>
|
<RepositoryUrl>https://gitlab.com/chenmichael/mcdiscordbot</RepositoryUrl>
|
||||||
|
@ -19,4 +19,6 @@ public class Fluid {
|
|||||||
: $"{Amount:n0} mB of {DisplayName}";
|
: $"{Amount:n0} mB of {DisplayName}";
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string CleanDisplayName => DisplayName[1..^1];
|
public string CleanDisplayName => DisplayName[1..^1];
|
||||||
|
[JsonIgnore]
|
||||||
|
public string? TagString => Tags is string[] tags ? string.Join(", ", tags) : null;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MinecraftDiscordBot.Models;
|
namespace MinecraftDiscordBot.Models;
|
||||||
|
|
||||||
@ -10,5 +11,23 @@ public class Item : Fluid {
|
|||||||
public Md5Hash Fingerprint { get; set; } = default!;
|
public Md5Hash Fingerprint { get; set; } = default!;
|
||||||
[JsonProperty("nbt", Required = Required.DisallowNull)]
|
[JsonProperty("nbt", Required = Required.DisallowNull)]
|
||||||
public dynamic? NBT { get; set; }
|
public dynamic? NBT { get; set; }
|
||||||
public override string ToString() => $"{Amount:n0}x {DisplayName}";
|
public override string ToString() => $"{AmountString} {CleanDisplayName}";
|
||||||
|
[JsonIgnore]
|
||||||
|
public string DetailString {
|
||||||
|
get {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendFormat("{0} {1}, fp: {2}", AmountString, CleanDisplayName, Fingerprint);
|
||||||
|
if (TagString is string tags)
|
||||||
|
sb.AppendFormat(", tags: [{0}]", tags);
|
||||||
|
if (NBT is not null)
|
||||||
|
sb.AppendFormat(", NBT: {0}", JsonConvert.SerializeObject(NBT));
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[JsonIgnore]
|
||||||
|
public string AmountString => Amount switch {
|
||||||
|
> 1000000 => $"> {Amount / 1000000:n0}m",
|
||||||
|
> 10000 => $"~ {Amount / 1000.0f:n2}k",
|
||||||
|
_ => Amount.ToString()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -57,10 +57,11 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
_config = config;
|
_config = config;
|
||||||
_computer = new(this);
|
_computer = new(this);
|
||||||
_computer.ChatMessageReceived += MinecraftMessageReceived;
|
_computer.ChatMessageReceived += MinecraftMessageReceived;
|
||||||
|
_computer.SocketChanged += ComputerConnectedChanged;
|
||||||
_administrators = config.Administrators.ToHashSet();
|
_administrators = config.Administrators.ToHashSet();
|
||||||
ClientScript = GetClientScript(config);
|
ClientScript = GetClientScript(config);
|
||||||
_client.Log += LogAsync;
|
_client.Log += LogAsync;
|
||||||
_client.MessageReceived += (msg) => DiscordMessageReceived(msg);
|
_client.MessageReceived += (msg) => DiscordMessageReceived(msg, 20 * 1000);
|
||||||
_client.ReactionAdded += DiscordReactionAdded;
|
_client.ReactionAdded += DiscordReactionAdded;
|
||||||
_wssv = new WebSocketServer($"ws://0.0.0.0:{config.Port}") {
|
_wssv = new WebSocketServer($"ws://0.0.0.0:{config.Port}") {
|
||||||
RestartAfterListenError = true
|
RestartAfterListenError = true
|
||||||
@ -69,6 +70,11 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
_whitelistedChannels = config.Channels.ToHashSet();
|
_whitelistedChannels = config.Channels.ToHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ComputerConnectedChanged(object? sender, IWebSocketConnection? e) {
|
||||||
|
_ = Task.Run(() => Broadcast(i => i.SendMessageAsync(e is not null
|
||||||
|
? "The Minecraft client is now available!"
|
||||||
|
: "The Minecraft client disconnected!")));
|
||||||
|
}
|
||||||
private void MinecraftMessageReceived(object? sender, ChatEvent e)
|
private void MinecraftMessageReceived(object? sender, ChatEvent e)
|
||||||
=> Task.Run(() => WebhookBroadcast(i => i.SendMessageAsync(e.Message, username: e.Username, avatarUrl: $"https://crafatar.com/renders/head/{e.UUID}")));
|
=> Task.Run(() => WebhookBroadcast(i => i.SendMessageAsync(e.Message, username: e.Username, avatarUrl: $"https://crafatar.com/renders/head/{e.UUID}")));
|
||||||
private Task<T[]> WebhookBroadcast<T>(Func<DiscordWebhookClient, Task<T>> apply) => Task.WhenAll(Channels.Select(i => apply(new DiscordWebhookClient(i.Webhook))));
|
private Task<T[]> WebhookBroadcast<T>(Func<DiscordWebhookClient, Task<T>> apply) => Task.WhenAll(Channels.Select(i => apply(new DiscordWebhookClient(i.Webhook))));
|
||||||
@ -211,7 +217,8 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
private Task SendResponse(SocketUserMessage message, ResponseType response) => response switch {
|
private Task SendResponse(SocketUserMessage message, ResponseType response) => response switch {
|
||||||
ResponseType.IChoiceResponse res => HandleChoice(message, res),
|
ResponseType.IChoiceResponse res => HandleChoice(message, res),
|
||||||
ResponseType.StringResponse res => message.ReplyAsync(res.Message),
|
ResponseType.StringResponse res => message.ReplyAsync(res.Message),
|
||||||
_ => message.ReplyAsync($"Whoops, someone forgot to implement '{response.GetType()}' responses?"),
|
ResponseType.FileResponse res => message.Channel.SendFileAsync(res.Path, text: res.Message),
|
||||||
|
_ => message.ReplyAsync($"Whoops, someone forgot to implement '{response.GetType().Name}' responses?"),
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<ulong, ResponseType.IChoiceResponse> _choiceWait = new();
|
private readonly ConcurrentDictionary<ulong, ResponseType.IChoiceResponse> _choiceWait = new();
|
||||||
@ -340,6 +347,8 @@ public abstract class ResponseType {
|
|||||||
private static string DefaultDisplay<T>(T obj) => obj?.ToString() ?? throw new InvalidProgramException("ToString did not yield anything!");
|
private static string DefaultDisplay<T>(T obj) => obj?.ToString() ?? throw new InvalidProgramException("ToString did not yield anything!");
|
||||||
public static ResponseType AsString(string message) => new StringResponse(message);
|
public static ResponseType AsString(string message) => new StringResponse(message);
|
||||||
public static ResponseType FromChoice<T>(string query, IEnumerable<T> choice, Func<T, Task> resultHandler, Func<T, string>? display = null) => new ChoiceResponse<T>(query, choice, resultHandler, display ?? DefaultDisplay);
|
public static ResponseType FromChoice<T>(string query, IEnumerable<T> choice, Func<T, Task> resultHandler, Func<T, string>? display = null) => new ChoiceResponse<T>(query, choice, resultHandler, display ?? DefaultDisplay);
|
||||||
|
internal static ResponseType File(string path, string message) => new FileResponse(path, message);
|
||||||
|
|
||||||
public class StringResponse : ResponseType {
|
public class StringResponse : ResponseType {
|
||||||
public StringResponse(string message) => Message = message;
|
public StringResponse(string message) => Message = message;
|
||||||
public string Message { get; }
|
public string Message { get; }
|
||||||
@ -363,4 +372,14 @@ public abstract class ResponseType {
|
|||||||
_displayer = display;
|
_displayer = display;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FileResponse : ResponseType {
|
||||||
|
public FileResponse(string path, string message) {
|
||||||
|
Path = path;
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path { get; }
|
||||||
|
public string Message { get; }
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using Discord.WebSocket;
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
using MinecraftDiscordBot.Commands;
|
using MinecraftDiscordBot.Commands;
|
||||||
using MinecraftDiscordBot.Models;
|
using MinecraftDiscordBot.Models;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -146,6 +147,7 @@ public class RefinedStorageService : CommandRouter {
|
|||||||
|
|
||||||
[CommandHandler(CmdListItems, HelpText = "Gets a list of items that are currently stored in the RS system.")]
|
[CommandHandler(CmdListItems, HelpText = "Gets a list of items that are currently stored in the RS system.")]
|
||||||
public async Task<ResponseType> HandleItemListing(SocketUserMessage message, string[] parameters, CancellationToken ct) {
|
public async Task<ResponseType> HandleItemListing(SocketUserMessage message, string[] parameters, CancellationToken ct) {
|
||||||
|
if (parameters.Length is 1 && parameters[0] == "full") return await SendFullItemList(message, ct);
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.Append("The Refined Storage system currently stores these items:");
|
sb.Append("The Refined Storage system currently stores these items:");
|
||||||
var items = await RefreshItemList(ct);
|
var items = await RefreshItemList(ct);
|
||||||
@ -153,11 +155,29 @@ public class RefinedStorageService : CommandRouter {
|
|||||||
var taken = 0;
|
var taken = 0;
|
||||||
foreach (var item in items) {
|
foreach (var item in items) {
|
||||||
if (sb.Length > 500) break;
|
if (sb.Length > 500) break;
|
||||||
sb.AppendFormat("\n{0:n0}x {1}", item.Amount, item.DisplayName);
|
sb.Append('\n');
|
||||||
|
sb.Append(item.ToString());
|
||||||
taken++;
|
taken++;
|
||||||
}
|
}
|
||||||
if (items.Count > taken) sb.AppendFormat("\nand {0} more items.", items.Skip(taken).Sum(i => i.Amount));
|
if (items.Count > taken) sb.AppendFormat("\nand {0:n0} more items.", items.Skip(taken).Sum(i => i.Amount));
|
||||||
}
|
}
|
||||||
return ResponseType.AsString(sb.ToString());
|
return ResponseType.AsString(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<ResponseType> SendFullItemList(SocketUserMessage message, CancellationToken ct) {
|
||||||
|
var path = await GetItemListFile(ct);
|
||||||
|
return ResponseType.File(path, $"{message.Author.Mention} Here you go:");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetItemListFile(CancellationToken ct) {
|
||||||
|
var items = await RefreshItemList(ct);
|
||||||
|
var file = Path.Combine(Path.GetTempPath(), "itemlist.txt");
|
||||||
|
var fs = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write);
|
||||||
|
using (var sw = new StreamWriter(fs, Encoding.UTF8)) {
|
||||||
|
await sw.WriteLineAsync("The RS System stores the following items:");
|
||||||
|
foreach (var item in items)
|
||||||
|
await sw.WriteLineAsync(item.DetailString);
|
||||||
|
};
|
||||||
|
return file;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user