diff --git a/fs24bot3/Backend/Basic.cs b/fs24bot3/Backend/Basic.cs index 91c9341..a3c584d 100644 --- a/fs24bot3/Backend/Basic.cs +++ b/fs24bot3/Backend/Basic.cs @@ -1,69 +1,69 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using fs24bot3.Core; -using fs24bot3.Models; -using Serilog; - -namespace fs24bot3.Backend; - -public class Basic : IMessagingClient -{ - public string Name { get; } - public Bot BotContext { get; } - - public Dictionary Fmt { get; } - - public Basic() - { - BotContext = new Bot(this); - Fmt = new Dictionary(); - Name = "fs24bot3"; - } - - public void SetupNick(string nickname) { } - public void JoinChannel(string name) - { - Log.Information("Joining channel: {0}", name); - } - public void PartChannel(string name) - { - Log.Information("Parting channel: {0}", name); - } - - public async Task SendMessage(string channel, string message) - { - await Task.Run(() => - { - Log.Information(message); - }); - } - - public async void Process() - { - var thread = new Thread(() => - { - BotContext.ProccessInfinite(); - }); - thread.Start(); - - while (true) - { - Console.Write("fs24bot3: "); - string value = Console.ReadLine()?.TrimEnd(); - if (!string.IsNullOrWhiteSpace(value)) - { - var msg = new MessageGeneric(value, "testchannel", - new User("test", BotContext.Connection)); - BotContext.MessageTrigger(msg); - await BotContext.ExecuteCommand(msg, ConfigurationProvider.Config.Prefix); - } - } - } - - public Task EnsureAuthorization(User user) - { - return Task.FromResult(true); - } +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using fs24bot3.Core; +using fs24bot3.Models; +using Serilog; + +namespace fs24bot3.Backend; + +public class Basic : IMessagingClient +{ + public string Name { get; } + public Bot BotContext { get; } + + public Dictionary Fmt { get; } + + public Basic() + { + BotContext = new Bot(this); + Fmt = new Dictionary(); + Name = "fs24bot3"; + } + + public void SetupNick(string nickname) { } + public void JoinChannel(string name) + { + Log.Information("Joining channel: {0}", name); + } + public void PartChannel(string name) + { + Log.Information("Parting channel: {0}", name); + } + + public async Task SendMessage(string channel, string message) + { + await Task.Run(() => + { + Log.Information(message); + }); + } + + public async void Process() + { + var thread = new Thread(() => + { + BotContext.ProccessInfinite(); + }); + thread.Start(); + + while (true) + { + Console.Write("fs24bot3: "); + string value = Console.ReadLine()?.TrimEnd(); + if (!string.IsNullOrWhiteSpace(value)) + { + var msg = new MessageGeneric(value, "testchannel", + new User("test", BotContext.Connection)); + BotContext.MessageTrigger(msg); + await BotContext.ExecuteCommand(msg, ConfigurationProvider.Config.Prefix); + } + } + } + + public Task EnsureAuthorization(User user) + { + return Task.FromResult(true); + } } \ No newline at end of file diff --git a/fs24bot3/Backend/Discord.cs b/fs24bot3/Backend/Discord.cs index 2086dea..4dbbd66 100644 --- a/fs24bot3/Backend/Discord.cs +++ b/fs24bot3/Backend/Discord.cs @@ -1,149 +1,149 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.Serialization; -using System.Threading.Tasks; -using DSharpPlus; -using DSharpPlus.EventArgs; -using fs24bot3.Models; -using Serilog; -using Tomlyn; -using System.Text; -using System.Threading; - -namespace fs24bot3.Backend; - -public class DiscordConfiguration -{ - [DataMember(Name = "token")] - public string Token { get; set; } - - public DiscordConfiguration() - { - Token = ""; - } -} - - -public class Discord : IMessagingClient -{ - private const string ConfigPath = "discord.toml"; - public string Name { get; private set; } - public Bot BotContext { get; } - - public Dictionary Fmt { get; } - - private DiscordConfiguration Config { get; } - - private DiscordClient BotClient { get; } - - public Discord() - { - if (File.Exists(ConfigPath)) - { - var loadedconfig = Toml.ToModel(File.ReadAllText(ConfigPath)); - Config = loadedconfig; - Log.Information("Configuration loaded!"); - } - else - { - Config = new DiscordConfiguration(); - Log.Warning("Discord backend was unable to find configuration file, I will create it for you"); - File.WriteAllText(ConfigPath, Toml.FromModel(Config)); - } - - var config = new DSharpPlus.DiscordConfiguration() - { - Token = Config.Token, - TokenType = TokenType.Bot, - Intents = DiscordIntents.All - }; - - - Fmt = new Dictionary - { - // add irc colors - { "b", "" }, - { "r", "" }, - { "white", "" }, - { "black", "" }, - { "blue", "" }, - { "green", "" }, - { "red", "" }, - { "brown", "" }, - { "purple", "" }, - { "orange", "" }, - { "yellow", "" }, - { "lime", "" }, - { "teal", "" }, - { "cyan", "" }, - { "royal", "" }, - { "pink", "" }, - { "gray", "" }, - { "silver", "" } - }; - - BotClient = new DiscordClient(config); - BotContext = new Bot(this); - - BotClient.Ready += Ready; - BotClient.MessageCreated += MessageCreated; - } - - private Task Ready(DiscordClient client, EventArgs args) - { - Name = client.CurrentUser.Username; - Log.Information("Connected!"); - return Task.CompletedTask; - } - - private async Task MessageCreated(DiscordClient client, MessageCreateEventArgs args) - { - Log.Information("{0}", args.Message.Content); - var user = new Core.User(args.Author.Mention.Replace("!", ""), - in BotContext.Connection); - var messageKind = MessageKind.Message; - - if (args.Message.Channel.IsPrivate) - { - messageKind = MessageKind.MessagePersonal; - } - - var msg = new MessageGeneric(args.Message.Content, args.Channel.Id.ToString(), user, messageKind); - - if (!msg.Sender.UserIsIgnored() && !args.Message.Author.IsBot) - { - if (msg.Kind == MessageKind.Message) { BotContext.MessageTrigger(msg); } - await BotContext.ExecuteCommand(msg, "."); - } - - } - - public async Task SendMessage(string channel, string message) - { - - var sb = new StringBuilder(message); - foreach (var (tag, value) in Fmt) - { - sb.Replace($"[{tag}]", value); - } - - var res = ulong.TryParse(channel, out var id); - if (!res) - { - Log.Warning("Unable to parse channel id: {0}", channel); - return; - } - var ch = await BotClient.GetChannelAsync(id); - await BotClient.SendMessageAsync(ch, sb.ToString()); - } - - public void Process() - { - Log.Information("Connecting to Discord..."); - Task.Run(async () => { Log.Verbose(""); - await BotClient.ConnectAsync(); - BotContext.ProccessInfinite(); }); - Console.ReadLine(); - } +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Threading.Tasks; +using DSharpPlus; +using DSharpPlus.EventArgs; +using fs24bot3.Models; +using Serilog; +using Tomlyn; +using System.Text; +using System.Threading; + +namespace fs24bot3.Backend; + +public class DiscordConfiguration +{ + [DataMember(Name = "token")] + public string Token { get; set; } + + public DiscordConfiguration() + { + Token = ""; + } +} + + +public class Discord : IMessagingClient +{ + private const string ConfigPath = "discord.toml"; + public string Name { get; private set; } + public Bot BotContext { get; } + + public Dictionary Fmt { get; } + + private DiscordConfiguration Config { get; } + + private DiscordClient BotClient { get; } + + public Discord() + { + if (File.Exists(ConfigPath)) + { + var loadedconfig = Toml.ToModel(File.ReadAllText(ConfigPath)); + Config = loadedconfig; + Log.Information("Configuration loaded!"); + } + else + { + Config = new DiscordConfiguration(); + Log.Warning("Discord backend was unable to find configuration file, I will create it for you"); + File.WriteAllText(ConfigPath, Toml.FromModel(Config)); + } + + var config = new DSharpPlus.DiscordConfiguration() + { + Token = Config.Token, + TokenType = TokenType.Bot, + Intents = DiscordIntents.All + }; + + + Fmt = new Dictionary + { + // add irc colors + { "b", "" }, + { "r", "" }, + { "white", "" }, + { "black", "" }, + { "blue", "" }, + { "green", "" }, + { "red", "" }, + { "brown", "" }, + { "purple", "" }, + { "orange", "" }, + { "yellow", "" }, + { "lime", "" }, + { "teal", "" }, + { "cyan", "" }, + { "royal", "" }, + { "pink", "" }, + { "gray", "" }, + { "silver", "" } + }; + + BotClient = new DiscordClient(config); + BotContext = new Bot(this); + + BotClient.Ready += Ready; + BotClient.MessageCreated += MessageCreated; + } + + private Task Ready(DiscordClient client, EventArgs args) + { + Name = client.CurrentUser.Username; + Log.Information("Connected!"); + return Task.CompletedTask; + } + + private async Task MessageCreated(DiscordClient client, MessageCreateEventArgs args) + { + Log.Information("{0}", args.Message.Content); + var user = new Core.User(args.Author.Mention.Replace("!", ""), + in BotContext.Connection); + var messageKind = MessageKind.Message; + + if (args.Message.Channel.IsPrivate) + { + messageKind = MessageKind.MessagePersonal; + } + + var msg = new MessageGeneric(args.Message.Content, args.Channel.Id.ToString(), user, messageKind); + + if (!msg.Sender.UserIsIgnored() && !args.Message.Author.IsBot) + { + if (msg.Kind == MessageKind.Message) { BotContext.MessageTrigger(msg); } + await BotContext.ExecuteCommand(msg, "."); + } + + } + + public async Task SendMessage(string channel, string message) + { + + var sb = new StringBuilder(message); + foreach (var (tag, value) in Fmt) + { + sb.Replace($"[{tag}]", value); + } + + var res = ulong.TryParse(channel, out var id); + if (!res) + { + Log.Warning("Unable to parse channel id: {0}", channel); + return; + } + var ch = await BotClient.GetChannelAsync(id); + await BotClient.SendMessageAsync(ch, sb.ToString()); + } + + public void Process() + { + Log.Information("Connecting to Discord..."); + Task.Run(async () => { Log.Verbose(""); + await BotClient.ConnectAsync(); + BotContext.ProccessInfinite(); }); + Console.ReadLine(); + } } \ No newline at end of file diff --git a/fs24bot3/Backend/IMessagingClient.cs b/fs24bot3/Backend/IMessagingClient.cs index 5961ee0..22619b5 100644 --- a/fs24bot3/Backend/IMessagingClient.cs +++ b/fs24bot3/Backend/IMessagingClient.cs @@ -1,40 +1,40 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using fs24bot3.Core; -using fs24bot3.Models; - -namespace fs24bot3.Backend; -public interface IMessagingClient -{ - /// - /// The client name e.g nickname in IRC - /// - public string Name { get; } - /// - /// The main bot context, must be instance of Bot class - /// - public Bot BotContext { get; } - - public Dictionary Fmt { get; } - public void SetupNick(string nickname) { } - public void JoinChannel(string name) - { - throw new NotImplementedException(); - } - public void PartChannel(string name) - { - throw new NotImplementedException(); - } - - public Task SendMessage(string channel, string message); - public void Process() - { - BotContext.ProccessInfinite(); - } - - public Task EnsureAuthorization(User user) - { - return Task.FromResult(true); - } +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using fs24bot3.Core; +using fs24bot3.Models; + +namespace fs24bot3.Backend; +public interface IMessagingClient +{ + /// + /// The client name e.g nickname in IRC + /// + public string Name { get; } + /// + /// The main bot context, must be instance of Bot class + /// + public Bot BotContext { get; } + + public Dictionary Fmt { get; } + public void SetupNick(string nickname) { } + public void JoinChannel(string name) + { + throw new NotImplementedException(); + } + public void PartChannel(string name) + { + throw new NotImplementedException(); + } + + public Task SendMessage(string channel, string message); + public void Process() + { + BotContext.ProccessInfinite(); + } + + public Task EnsureAuthorization(User user) + { + return Task.FromResult(true); + } } \ No newline at end of file diff --git a/fs24bot3/Backend/IRC.cs b/fs24bot3/Backend/IRC.cs index 7833e76..4b138e5 100644 --- a/fs24bot3/Backend/IRC.cs +++ b/fs24bot3/Backend/IRC.cs @@ -1,274 +1,274 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Threading.Tasks; -using fs24bot3.Core; -using fs24bot3.Helpers; -using fs24bot3.Models; -using NetIRC; -using NetIRC.Connection; -using NetIRC.Messages; -using Serilog; -using Tomlyn; - -namespace fs24bot3.Backend; - - -public class IrcConfiguration -{ - [DataMember(Name = "name")] - public string Name { get; set; } - [DataMember(Name = "network")] - public string Network { get; set; } - [DataMember(Name = "channel")] - public string Channel { get; set; } - [DataMember(Name = "port")] - public int Port { get; set; } - [DataMember(Name = "nickserv_pass")] - public string NickservPass { get; set; } - [DataMember(Name = "server_pass")] - public string ServerPassword { get; set; } - - public IrcConfiguration() - { - Name = "fs24bot"; - Network = "irc.esper.net"; - Channel = "#fl-studio"; - Port = 6667; - NickservPass = "zxcvbm1"; - ServerPassword = "zxcvbm1"; - } -} - -/// -/// IRC backend -/// -public class Irc : IMessagingClient -{ - private const string ConfigPath = "irc.toml"; - public string Name { get; private set; } - - public Bot BotContext { get; } - public Dictionary Fmt { get; } - - private Client BotClient { get; } - private IrcConfiguration Config { get; } - - public Irc() - { - BotContext = new Bot(this); - if (File.Exists(ConfigPath)) - { - var loadedconfig = Toml.ToModel(File.ReadAllText(ConfigPath)); - Config = loadedconfig; - Log.Information("Configuration loaded!"); - } - else - { - Config = new IrcConfiguration(); - Log.Warning("IRC backend was unable to find configuration file, I will create it for you"); - File.WriteAllText(ConfigPath, Toml.FromModel(Config)); - } - - Fmt = new Dictionary - { - // add irc colors - { "b", "" }, - { "r", "" }, - { "white", "00" }, - { "black", "01" }, - { "blue", "02" }, - { "green", "03" }, - { "red", "04" }, - { "brown", "05" }, - { "purple", "06" }, - { "orange", "07" }, - { "yellow", "08" }, - { "lime", "09" }, - { "teal", "10" }, - { "cyan", "11" }, - { "royal", "12" }, - { "pink", "13" }, - { "gray", "14" }, - { "silver", "15" } - }; - - SetupNick(Config.Name); - - BotClient = new Client(new NetIRC.User(Name, "Sopli IRC 3.0"), - new TcpClientConnection(Config.Network, Config.Port)); - - BotClient.RawDataReceived += Client_OnRawDataReceived; - BotClient.IRCMessageParsed += Client_OnIRCMessageParsed; - BotClient.RegistrationCompleted += Client_OnRegister; - } - - - private async void Client_OnIRCMessageParsed(Client client, ParsedIRCMessage message) - { - if (message.IRCCommand == IRCCommand.PRIVMSG) - { - var msg = new MessageGeneric(in message, in BotContext.Connection, Name); - var prefix = ConfigurationProvider.Config.Prefix; - - if (!msg.Sender.UserIsIgnored()) - { - if (msg.Kind == MessageKind.Message) { BotContext.MessageTrigger(msg); } - await BotContext.ExecuteCommand(msg, prefix); - } - } - - if (message.IRCCommand == IRCCommand.ERROR) - { - Log.Error("Connection closed due to error..."); - Environment.Exit(1); - } - - if (message.NumericReply == IRCNumericReply.ERR_NICKNAMEINUSE) - { - SetupNick(Name + new Random().Next(int.MinValue, int.MaxValue)); - } - - if (message.NumericReply == IRCNumericReply.ERR_PASSWDMISMATCH) - { - await client.SendRaw("PASS " + Config.ServerPassword); - } - - if (message.IRCCommand == IRCCommand.KICK && message.Parameters[1] == Name) - { - Log.Warning("I've got kick from {0} rejoining...", message.Prefix); - await client.SendRaw("JOIN " + message.Parameters[0]); - await SendMessage(message.Parameters[0], "За что?"); - } - } - - private async void Client_OnRegister(object sender, EventArgs _) - { - JoinChannel(Config.Channel); - await SendMessage("Nickserv", "IDENTIFY " + Config.NickservPass); - } - - private static void Client_OnRawDataReceived(Client client, string rawData) - { - Log.Information(rawData); - } - - public async void SetupNick(string nickname) - { - Name = nickname; - if (BotClient != null) - { - await BotClient.SendRaw("NICK " + nickname); - } - } - public async void JoinChannel(string name) - { - await BotClient.SendRaw("JOIN " + name); - } - - public async void PartChannel(string name) - { - await BotClient.SendRaw("PART " + name); - } - - public void Process() - { - Log.Information("Connecting to: {0}:{1}", Config.Network, Config.Port); - Task.Run(() => BotClient.ConnectAsync()); - BotContext.ProccessInfinite(); - } - - public async Task SendMessage(string channel, string message) - { - List msgLines = message.Split("\n").Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); - int count = 0; - - foreach (string outputstr in msgLines) - { - var sb = new StringBuilder(outputstr); - foreach (var (tag, value) in Fmt) - { - sb.Replace($"[{tag}]", value); - } - - if (sb.Length < 1000) - { - await BotClient.SendAsync(new PrivMsgMessage(channel, sb.ToString())); - count++; - } - else - { - string link = await InternetServicesHelper.UploadToTrashbin( - MessageHelper.StripIRC(message), "addplain"); - await BotClient.SendAsync(new PrivMsgMessage(channel, $"Слишком жесткое сообщение с длинной " + - $"{sb.Length} символов! Психанул?!?!?!")); - await BotClient.SendAsync(new PrivMsgMessage(channel, "Полный вывод: " + link)); - return; - } - - if (count > 4) - { - string link = await InternetServicesHelper.UploadToTrashbin(MessageHelper.StripIRC(message), - "addplain"); - await BotClient.SendAsync(new PrivMsgMessage(channel, "Полный вывод: " + link)); - return; - } - } - } - - - /// - /// Ensures authorization in IRC - /// - /// - /// - public async Task EnsureAuthorization(Core.User user) - { - var tcs = new TaskCompletionSource(); - ParsedIRCMessageHandler messageHandler = null; - - // ACC returns parsable information about a user's - // login status. Note that on many networks, /whois - // shows similar information faster and more reliably. - // ACC also returns the unique entity ID of the given account. - // The answer is in the form [-> account] ACC , - // where is one of the following: - // 0 - account or user does not exist - // 1 - account exists but user is not logged in - // 2 - user is not logged in but recognized (see ACCESS) - // 3 - user is logged in - // If the account is omitted the user's nick is used and - // the " -> account" portion of the reply is omitted. - // Account * means the account the user is logged in with. - // example: - // Totoro ACC 1 AAAAAXXX - - try - { - messageHandler = (client, message) => - { - if (message.Prefix.From == "NickServ") - { - var split = message.Trailing.Split(" "); - - tcs.SetResult(split[2] == "3"); - - BotClient.IRCMessageParsed -= messageHandler; - } - }; - - BotClient.IRCMessageParsed += messageHandler; - - await SendMessage("NickServ", $"ACC {user.Username}"); - return await tcs.Task; - } - catch (Exception e) - { - Log.Error("Unable to verify account status for {0}: {1}", user.Username, e); - return await Task.FromResult(false); - } - } +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using fs24bot3.Core; +using fs24bot3.Helpers; +using fs24bot3.Models; +using NetIRC; +using NetIRC.Connection; +using NetIRC.Messages; +using Serilog; +using Tomlyn; + +namespace fs24bot3.Backend; + + +public class IrcConfiguration +{ + [DataMember(Name = "name")] + public string Name { get; set; } + [DataMember(Name = "network")] + public string Network { get; set; } + [DataMember(Name = "channel")] + public string Channel { get; set; } + [DataMember(Name = "port")] + public int Port { get; set; } + [DataMember(Name = "nickserv_pass")] + public string NickservPass { get; set; } + [DataMember(Name = "server_pass")] + public string ServerPassword { get; set; } + + public IrcConfiguration() + { + Name = "fs24bot"; + Network = "irc.esper.net"; + Channel = "#fl-studio"; + Port = 6667; + NickservPass = "zxcvbm1"; + ServerPassword = "zxcvbm1"; + } +} + +/// +/// IRC backend +/// +public class Irc : IMessagingClient +{ + private const string ConfigPath = "irc.toml"; + public string Name { get; private set; } + + public Bot BotContext { get; } + public Dictionary Fmt { get; } + + private Client BotClient { get; } + private IrcConfiguration Config { get; } + + public Irc() + { + BotContext = new Bot(this); + if (File.Exists(ConfigPath)) + { + var loadedconfig = Toml.ToModel(File.ReadAllText(ConfigPath)); + Config = loadedconfig; + Log.Information("Configuration loaded!"); + } + else + { + Config = new IrcConfiguration(); + Log.Warning("IRC backend was unable to find configuration file, I will create it for you"); + File.WriteAllText(ConfigPath, Toml.FromModel(Config)); + } + + Fmt = new Dictionary + { + // add irc colors + { "b", "" }, + { "r", "" }, + { "white", "00" }, + { "black", "01" }, + { "blue", "02" }, + { "green", "03" }, + { "red", "04" }, + { "brown", "05" }, + { "purple", "06" }, + { "orange", "07" }, + { "yellow", "08" }, + { "lime", "09" }, + { "teal", "10" }, + { "cyan", "11" }, + { "royal", "12" }, + { "pink", "13" }, + { "gray", "14" }, + { "silver", "15" } + }; + + SetupNick(Config.Name); + + BotClient = new Client(new NetIRC.User(Name, "Sopli IRC 3.0"), + new TcpClientConnection(Config.Network, Config.Port)); + + BotClient.RawDataReceived += Client_OnRawDataReceived; + BotClient.IRCMessageParsed += Client_OnIRCMessageParsed; + BotClient.RegistrationCompleted += Client_OnRegister; + } + + + private async void Client_OnIRCMessageParsed(Client client, ParsedIRCMessage message) + { + if (message.IRCCommand == IRCCommand.PRIVMSG) + { + var msg = new MessageGeneric(in message, in BotContext.Connection, Name); + var prefix = ConfigurationProvider.Config.Prefix; + + if (!msg.Sender.UserIsIgnored()) + { + if (msg.Kind == MessageKind.Message) { BotContext.MessageTrigger(msg); } + await BotContext.ExecuteCommand(msg, prefix); + } + } + + if (message.IRCCommand == IRCCommand.ERROR) + { + Log.Error("Connection closed due to error..."); + Environment.Exit(1); + } + + if (message.NumericReply == IRCNumericReply.ERR_NICKNAMEINUSE) + { + SetupNick(Name + new Random().Next(int.MinValue, int.MaxValue)); + } + + if (message.NumericReply == IRCNumericReply.ERR_PASSWDMISMATCH) + { + await client.SendRaw("PASS " + Config.ServerPassword); + } + + if (message.IRCCommand == IRCCommand.KICK && message.Parameters[1] == Name) + { + Log.Warning("I've got kick from {0} rejoining...", message.Prefix); + await client.SendRaw("JOIN " + message.Parameters[0]); + await SendMessage(message.Parameters[0], "За что?"); + } + } + + private async void Client_OnRegister(object sender, EventArgs _) + { + JoinChannel(Config.Channel); + await SendMessage("Nickserv", "IDENTIFY " + Config.NickservPass); + } + + private static void Client_OnRawDataReceived(Client client, string rawData) + { + Log.Information(rawData); + } + + public async void SetupNick(string nickname) + { + Name = nickname; + if (BotClient != null) + { + await BotClient.SendRaw("NICK " + nickname); + } + } + public async void JoinChannel(string name) + { + await BotClient.SendRaw("JOIN " + name); + } + + public async void PartChannel(string name) + { + await BotClient.SendRaw("PART " + name); + } + + public void Process() + { + Log.Information("Connecting to: {0}:{1}", Config.Network, Config.Port); + Task.Run(() => BotClient.ConnectAsync()); + BotContext.ProccessInfinite(); + } + + public async Task SendMessage(string channel, string message) + { + List msgLines = message.Split("\n").Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + int count = 0; + + foreach (string outputstr in msgLines) + { + var sb = new StringBuilder(outputstr); + foreach (var (tag, value) in Fmt) + { + sb.Replace($"[{tag}]", value); + } + + if (sb.Length < 1000) + { + await BotClient.SendAsync(new PrivMsgMessage(channel, sb.ToString())); + count++; + } + else + { + string link = await InternetServicesHelper.UploadToTrashbin( + MessageHelper.StripIRC(message), "addplain"); + await BotClient.SendAsync(new PrivMsgMessage(channel, $"Слишком жесткое сообщение с длинной " + + $"{sb.Length} символов! Психанул?!?!?!")); + await BotClient.SendAsync(new PrivMsgMessage(channel, "Полный вывод: " + link)); + return; + } + + if (count > 4) + { + string link = await InternetServicesHelper.UploadToTrashbin(MessageHelper.StripIRC(message), + "addplain"); + await BotClient.SendAsync(new PrivMsgMessage(channel, "Полный вывод: " + link)); + return; + } + } + } + + + /// + /// Ensures authorization in IRC + /// + /// + /// + public async Task EnsureAuthorization(Core.User user) + { + var tcs = new TaskCompletionSource(); + ParsedIRCMessageHandler messageHandler = null; + + // ACC returns parsable information about a user's + // login status. Note that on many networks, /whois + // shows similar information faster and more reliably. + // ACC also returns the unique entity ID of the given account. + // The answer is in the form [-> account] ACC , + // where is one of the following: + // 0 - account or user does not exist + // 1 - account exists but user is not logged in + // 2 - user is not logged in but recognized (see ACCESS) + // 3 - user is logged in + // If the account is omitted the user's nick is used and + // the " -> account" portion of the reply is omitted. + // Account * means the account the user is logged in with. + // example: + // Totoro ACC 1 AAAAAXXX + + try + { + messageHandler = (client, message) => + { + if (message.Prefix.From == "NickServ") + { + var split = message.Trailing.Split(" "); + + tcs.SetResult(split[2] == "3"); + + BotClient.IRCMessageParsed -= messageHandler; + } + }; + + BotClient.IRCMessageParsed += messageHandler; + + await SendMessage("NickServ", $"ACC {user.Username}"); + return await tcs.Task; + } + catch (Exception e) + { + Log.Error("Unable to verify account status for {0}: {1}", user.Username, e); + return await Task.FromResult(false); + } + } } \ No newline at end of file diff --git a/fs24bot3/Commands/InternetCommandsModule.cs b/fs24bot3/Commands/InternetCommandsModule.cs index afd7aa8..908e592 100644 --- a/fs24bot3/Commands/InternetCommandsModule.cs +++ b/fs24bot3/Commands/InternetCommandsModule.cs @@ -1,526 +1,526 @@ -using fs24bot3.Core; -using fs24bot3.Helpers; -using fs24bot3.Models; -using fs24bot3.QmmandsProcessors; -using Genbox.WolframAlpha; -using HtmlAgilityPack; -using MCQuery; -using NetIRC; -using Newtonsoft.Json; -using Qmmands; -using Serilog; -using SQLite; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; - -namespace fs24bot3.Commands; - -public sealed class InternetCommandsModule : ModuleBase -{ - public CommandService Service { get; set; } - - [Command("execute", "exec")] - [Description("REPL. поддерживает множество языков, lua, php, nodejs, python3, python2, cpp, c, lisp ... и многие другие")] - [Cooldown(5, 2, CooldownMeasure.Minutes, Bot.CooldownBucketType.Global)] - public async Task ExecuteApi(string lang, [Remainder] string code) - { - APIExec.Input codeData = new APIExec.Input - { - clientId = ConfigurationProvider.Config.Services.JdoodleClientID, - clientSecret = ConfigurationProvider.Config.Services.JdoodleClientSecret, - language = lang, - script = code - }; - - try - { - var output = await Context.HttpTools.PostJson("https://api.jdoodle.com/v1/execute", codeData); - var jsonOutput = JsonConvert.DeserializeObject(output); - - if (jsonOutput == null) - { - await Context.SendSadMessage(); - return; - } - - if (jsonOutput.cpuTime != null && jsonOutput.memory != null) - { - await Context.SendMessage(Context.Channel, $"CPU: {jsonOutput.cpuTime * 1000} ms Mem: {jsonOutput.memory} KiB"); - } - - if (jsonOutput.output != null) - { - await Context.SendMessage(Context.Channel, jsonOutput.output); - } - else - { - var jsonErr = JsonConvert.DeserializeObject(output); - await Context.SendMessage(Context.Channel, - $"Ошибка работы API сервиса: {jsonErr.error} ({jsonErr.statusCode})"); - } - } - catch (Exception) - { - await Context.SendMessage(Context.Channel, $"[gray]Не работает короче, блин........"); - } - } - - [Command("executeurl", "execurl")] - [Description("Тоже самое что и exec только работает через URL")] - [Cooldown(5, 3, CooldownMeasure.Minutes, Bot.CooldownBucketType.Global)] - public async Task ExecuteApiUrl(string code, string rawurl) - { - var response = await Context.HttpTools.GetTextPlainResponse(rawurl); - await ExecuteApi(code, response); - } - - [Command("shopcurrency", "shopcur", "curshop", "curshp")] - [Description("Курсы валют различных интернет магазинов. Поддерживается только USD.")] - [Remarks("Параметр shop допускает следующие значения: `ЦБ-РФ`, `Aliexpress`, `GearBest`, `GeekBuying`, `Banggood`")] - public async Task ShopCur(float usd = 1.0f, string shop = "aliexpress") - { - var curs = await InternetServicesHelper.GetShopCurrencies(); - - if (!curs.ContainsKey(shop)) - { - await Context.SendSadMessage(Context.Channel, "Такой интернет магазин не поддерживается"); - return; - } - await Context.SendMessage($"{shop}: {usd} USD -> {curs[shop.ToLower()] * usd} RUB"); - } - - [Command("isup", "isdown", "ping")] - [Description("Работает ли сайт?")] - [Cooldown(5, 1, CooldownMeasure.Minutes, Bot.CooldownBucketType.Channel)] - public async Task IsUp(string url) - { - var urik = new UriBuilder(url); - bool response = await Context.HttpTools.PingHost(urik.Host); - if (response) - { - await Context.SendMessage(Context.Channel, $"[green]{urik.Host}: Работает!"); - } - else - { - await Context.SendMessage(Context.Channel, $"[red]{urik.Host}: Не смог установить соединение..."); - } - } - - [Command("isblocked", "blocked", "block", "blk")] - [Description("Заблокирован ли сайт в России?")] - public async Task IsBlocked(string url) - { - var output = await Context.HttpTools.PostJson("https://isitblockedinrussia.com/", new IsBlockedInRussia.RequestRoot() { host = url }); - var jsonOutput = JsonConvert.DeserializeObject(output); - - int totalblocks = 0; - int totalips = jsonOutput.ips.Count; - - foreach (var item in jsonOutput.ips) - { - if (item.blocked.Any()) - { - totalblocks += 1; - } - } - - if (totalblocks > 0 || jsonOutput.domain.blocked.Any()) - { - await Context.SendMessage(Context.Channel, $"[b]{url}[r]: заблокировано [red]{totalblocks}[r] айпишников из [green]{totalips}[r]!!!" + - $" Также заблочено доменов: [b][red]{jsonOutput.domain.blocked.Count}[r] Подробнее: https://isitblockedinrussia.com/?host={url}"); - } - else - { - await Context.SendMessage(Context.Channel, $"[green]{url}: Не заблокирован!"); - } - } - - [Command("whrand", "whowrand", "howrand")] - public async Task WikiHowRand() - { - var resp = await Context.HttpTools.GetResponseAsync("https://ru.wikihow.com/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:Randomizer"); - resp.EnsureSuccessStatusCode(); - - if (resp.RequestMessage != null && resp.RequestMessage.RequestUri != null) - { - await Context.SendMessage(Context.Channel, resp.RequestMessage.RequestUri.ToString()); - } - else - { - await Context.SendSadMessage(); - } - } - - - [Command("cur", "currency", "coin")] - [Description("Конвертер валют")] - public async Task Currency(float amount = 1, string codeFirst = "USD", string codeSecond = "RUB", string bankProvider = "") - { - var resp = await Context.HttpTools.GetResponseAsync - ("https://api.exchangerate.host/latest?base=" + codeFirst + "&amount=" + amount + "&symbols=" + codeSecond + "&format=csv&source=" + bankProvider); - - - resp.EnsureSuccessStatusCode(); - - // "code","rate","base","date" - // "RUB","82,486331","USD","2022-04-07" -- this - try - { - string currency = resp.Content.ReadAsStringAsync().Result.Split("\n")[1]; - var info = currency.Split("\",\""); - string gotConvCode = info[0].Replace("\"", ""); - string valueString = info[1].Replace("\"", ""); - string gotCode = info[2].Replace("\"", ""); - - if (valueString == "NaN") { valueString = "∞"; } - - await Context.SendMessage(bankProvider.ToUpper() + ": " + amount + " " + gotCode + " -> " + valueString + " " + gotConvCode); - } - catch (IndexOutOfRangeException) - { - await Context.SendSadMessage(); - } - } - - [Command("stocks", "stock")] - [Description("Акции. параметр lookUpOnlySymbol позволяет сразу искать акцию по символу, а не названию компании")] - public async Task Stocks(string stock = "AAPL", bool lookUpOnlySymbol = true) - { - var symbolLockup = await Context.HttpTools.GetJson( - "https://finnhub.io/api/v1/search?q=" + stock + "&token=" + - ConfigurationProvider.Config.Services.FinnhubKey); - - var lookup = symbolLockup.result.FirstOrDefault(); - - if (lookup == null) - { - await Context.SendSadMessage(); - return; - } - - var resp = await Context.HttpTools.GetResponseAsync("https://finnhub.io/api/v1/quote?symbol=" + lookup.symbol + - "&token=" + ConfigurationProvider.Config.Services.FinnhubKey); - - if (resp == null || lookUpOnlySymbol) - { - // trying just find stock by symbol - resp = await Context.HttpTools.GetResponseAsync("https://finnhub.io/api/v1/quote?symbol=" + stock + - "&token=" + ConfigurationProvider.Config.Services.FinnhubKey); - if (resp == null) - { - // give up - return; - } - } - - var stockObj = JsonConvert.DeserializeObject(await resp.Content.ReadAsStringAsync()); - - if (stockObj == null) - { - await Context.SendSadMessage(Context.Channel, "Не удалось найти акцию!"); - return; - } - - await Context.SendMessage( - $"({lookup.description}) {lookup.symbol} [b]{stockObj.c} USD[r] (низ: [red]{stockObj.l} [r]/ выс: [green]{stockObj.h})"); - } - - [Command("curcmp", "currencycomapre", "currencycomp", "curcompare", "ccmp")] - public async Task CurrencyCompare(float amount = 1, string codeFirst = "USD", string codeSecond = "RUB") - { - foreach (string bank in new string[] { "boc", "nbu", "bnro", "nob" }) - { - await Currency(amount, codeFirst, codeSecond, bank); - } - } - - [Command("wh", "wikihow")] - public async Task WikiHow([Remainder] string query) - { - var web = new HtmlWeb(); - var doc = await web.LoadFromWebAsync("https://ru.wikihow.com/wikiHowTo?search=" + query); - HtmlNodeCollection divContainer = doc.DocumentNode.SelectNodes("//a[@class=\"result_link\"]"); - if (divContainer != null) - { - foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//br")) - node.ParentNode.ReplaceChild(doc.CreateTextNode("\n"), node); - - foreach (var node in divContainer) - { - Log.Verbose(node.InnerText); - string hrefValue = node.GetAttributeValue("href", string.Empty); - var title = node.SelectSingleNode("//div[@class=\"result\"]").SelectSingleNode("//div[@class=\"result_title\"]"); - await Context.SendMessage(Context.Channel, $"{title.InnerText} // {hrefValue}"); - break; - } - } - } - - [Command("prz", "prazdnik", "holiday", "kakojsegodnjaprazdnik")] - [Description("Какой сегодня или завтра праздник?")] - public async Task Holiday(uint month = 0, uint day = 0) - { - - if (month == 0 || month > 12) - { - month = (uint)DateTime.Now.Month; - } - - if (day == 0) - { - day = (uint)DateTime.Now.Day; - } - - var humanMonth = new Dictionary() - { - {1, "yanvar" }, - {2, "fevral" }, - {3, "mart" }, - {4, "aprel" }, - {5, "may" }, - {6, "iyun" }, - {7, "iyul" }, - {8, "avgust" }, - {9, "sentyabr"}, - {10, "oktyabr"}, - {11, "noyabr" }, - {12, "dekabr" }, - }; - - - string url = "https://kakoysegodnyaprazdnik.ru/baza/" + humanMonth[(int)month] + "/" + day; - - var response = await Context.HttpTools.GetResponseAsync(url); - Log.Verbose(url); - var doc = new HtmlDocument(); - doc.LoadHtml(await response.Content.ReadAsStringAsync()); - - var outputs = new List(); - - HtmlNodeCollection divContainer = doc.DocumentNode.SelectNodes("//div[@itemprop='suggestedAnswer']//span[@itemprop='text']"); - if (divContainer != null) - { - foreach (var node in divContainer) - { - outputs.Add(node.InnerText); - } - } - - await Context.SendMessage(Context.Channel, $"[b]{day}-{month}-{DateTime.Today.Year}:[r] у нас: [b]{outputs.Random()}"); - } - - [Command("wa", "wolfram", "wolframalpha")] - [Description("Wolfram|Alpha — база знаний и набор вычислительных алгоритмов, вопросно-ответная система. Не является поисковой системой.")] - [Cooldown(20, 10, CooldownMeasure.Minutes, Bot.CooldownBucketType.Global)] - public async Task Wolfram([Remainder] string query) - { - WolframAlphaClient client = new WolframAlphaClient(ConfigurationProvider.Config.Services.WolframID); - var results = await client.QueryAsync(query); - - if (results.IsError) - { - Context.SendErrorMessage(Context.Channel, $"Ошибка при работе сервиса: {results.ErrorDetails}"); - return; - } - - if (!results.IsSuccess || !results.Pods.Any()) - { - await Context.SendSadMessage(); - return; - } - - var result = results.Pods[0].SubPods[0].Plaintext; - - foreach (var pod in results.Pods.Take(3)) - { - if (pod.IsPrimary) - { - foreach (var subPod in pod.SubPods) - { - if (!string.IsNullOrEmpty(subPod.Plaintext)) - { - var output = subPod.Plaintext.Split("\n"); - await Context.SendMessage(Context.Channel, $"[b]{result}[r] = {string.Join(" ", output)}"); - return; - } - } - } - } - - // falling back to old view - foreach (var pod in results.Pods.Take(2)) - { - foreach (var subPod in pod.SubPods.Take(2)) - { - if (!string.IsNullOrEmpty(subPod.Plaintext)) - await Context.SendMessage(Context.Channel, $"[b]{pod.Title}: [r]{subPod.Plaintext}"); - } - } - } - - [Command("pearls", "inpearls", "inp", "ip")] - [Description("Самые душевные цитаты в мире!")] - public async Task InPearls(string category = "", int page = 0) - { - var pagenum = Context.Random.Next(page, 36); - try - { - var output = await Context.ServicesHelper.InPearls(category, pagenum); - - if (output.Any()) - { - await Context.SendMessage(Context.Channel, output.Random()); - } - else - { - await Context.SendSadMessage(); - } - } - catch (InvalidOperationException e) - { - await Context.SendSadMessage(Context.Channel, $"Не удалось получить цитаты с inpearls: {e.Message}"); - } - } - - [Command("talk", "chatbot")] - [Description("Чатбот")] - public async Task Chatbot([Remainder] string message) - { - ChatBotResponse jsonOutput; - for (int i = 0; i < 5; i++) - { - var fmt = $"{Context.User.Username}: {message}\nuser2: "; - var msg = new ChatBotRequest(fmt); - try - { - var output = await Context.HttpTools.PostJson("https://pelevin.gpt.dobro.ai/generate/", msg); - jsonOutput = JsonConvert.DeserializeObject(output); - if (jsonOutput != null) - { - var reply = jsonOutput.Replies.FirstOrDefault(); - if (reply != null) - { - var containsBadword = RandomMsgs.BadWordsSubstrings.Any(x => reply.ToLower().Contains(x)); ; - - if (!containsBadword) - { - await Context.SendMessage(Context.Channel, $"{Context.User.Username}: {jsonOutput.Replies.FirstOrDefault()}"); - return; - } - } - } - else - { - await Context.SendMessage(Context.Channel, $"{Context.User.Username}: я не понимаю о чем ты"); - return; - } - } - catch (HttpRequestException) - { - break; - } - } - - await Context.SendMessage(Context.Channel, $"{Context.User.Username}: {RandomMsgs.NotFoundMessages.Random()}"); - } - - [Command("mc", "minecraft", "mineserver", "mineserv")] - [Description("Информация о сервере Minecraft")] - public async Task MinecraftQuery(string ipaddr) - { - var hostname = Context.HttpTools.ParseHostname(ipaddr); - MCServer server = new MCServer(hostname.Address.ToString(), hostname.Port); - ServerStatus status = server.Status(); - double ping = server.Ping(); - - await Context.SendMessage(Context.Channel, - $"[b]{ipaddr}[r]: " + - $"({status.Version.Name}): Игроки: [b]{status.Players.Online}/{status.Players.Max}[r] [green]Пинг: {ping} мс"); - } - - [Command("oweather", "openweather", "openweathermap")] - public async Task OpenWeatherMap([Remainder] string omskWhereYouLive = "") - { - string city = Context.User.GetCity(omskWhereYouLive); - if (city == "" && omskWhereYouLive == "") - { - await Context.SendSadMessage(Context.Channel, "Пожалуйста, установите город!"); - return; - } - - try - { - var wr = await Context.ServicesHelper.OpenWeatherMap(city); - - await Context.SendMessage($"[b]{wr.CityName}[r]: {wr.Condition.GetDescription()} {wr.Temperature} °C" + - $" (ощущения: [b]{wr.FeelsLike} °C[r]) Влажность: [b]{wr.Humidity}%[r] Ветер: [b]{wr.WindDirection.GetDescription()} {wr.WindHeading}° {(wr.WindSpeed * 1.944):0.0} kts {wr.WindSpeed} m/s[r]"); - } - catch (Exception) - { - await Context.SendSadMessage(); - } - } - - - [Command("metar", "mweather")] - [Description("Запрос METAR информации о погоде")] - public async Task Metar(string airportIcao = "URWW", bool rawOutput = false) - { - - var response = await Context.HttpTools.GetJson>($"https://aviationweather.gov/cgi-bin/data/metar.php?ids={airportIcao}&format=json"); - - var metar = response.FirstOrDefault(); - - if (!rawOutput) - { - if (metar == null) - { - await Context.SendSadMessage(); - return; - } - - int wind = metar.Wspd; - - if (metar.RawOb.Contains("MPS")) - { - wind = (int)Math.Floor(wind * 1.944); - } - - await Context.SendMessage($"[b]{metar.ReportTime}: {metar.IcaoId} ({metar.Name}):[r] [b]{metar.Temp}°C[r] QNH: [b]{metar.Altim}[r] hPA Ветер: [b]{metar.Wdir}° {wind} kts [r]Видимость: [b]{metar.Visib}[r]"); - } - else - { - await Context.SendMessage(metar.RawOb); - } - } - - [Command("weather", "yanderweather")] - public async Task YandexWeather([Remainder] string omskWhereYouLive = "") - { - string city = Context.User.GetCity(omskWhereYouLive); - if (city == "" && omskWhereYouLive == "") - { - await Context.SendSadMessage(Context.Channel, "Пожалуйста, установите город!"); - return; - } - - try - { - var wr = await Context.ServicesHelper.YandexWeather(city); - await Context.SendMessage($"По данным Яндекс.Погоды в [b]{wr.CityName}[r]: {wr.Condition.GetDescription()} {wr.Temperature} °C" + - $" (ощущения: {wr.FeelsLike} °C) Влажность: {wr.Humidity}% Ветер: {wr.WindDirection.GetDescription()} ~{wr.WindHeading}° {(wr.WindSpeed * 1.944):0.0} kts {wr.WindSpeed} m/s"); - } - catch (ArgumentNullException) - { - await Context.SendSadMessage(); - } - catch (Exception) - { - await Context.SendSadMessage(Context.Channel, "Яндекс.Погода не работает, пробуем OpenWeatherMap..."); - await OpenWeatherMap(omskWhereYouLive); - } - } -} +using fs24bot3.Core; +using fs24bot3.Helpers; +using fs24bot3.Models; +using fs24bot3.QmmandsProcessors; +using Genbox.WolframAlpha; +using HtmlAgilityPack; +using MCQuery; +using NetIRC; +using Newtonsoft.Json; +using Qmmands; +using Serilog; +using SQLite; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +namespace fs24bot3.Commands; + +public sealed class InternetCommandsModule : ModuleBase +{ + public CommandService Service { get; set; } + + [Command("execute", "exec")] + [Description("REPL. поддерживает множество языков, lua, php, nodejs, python3, python2, cpp, c, lisp ... и многие другие")] + [Cooldown(5, 2, CooldownMeasure.Minutes, Bot.CooldownBucketType.Global)] + public async Task ExecuteApi(string lang, [Remainder] string code) + { + APIExec.Input codeData = new APIExec.Input + { + clientId = ConfigurationProvider.Config.Services.JdoodleClientID, + clientSecret = ConfigurationProvider.Config.Services.JdoodleClientSecret, + language = lang, + script = code + }; + + try + { + var output = await Context.HttpTools.PostJson("https://api.jdoodle.com/v1/execute", codeData); + var jsonOutput = JsonConvert.DeserializeObject(output); + + if (jsonOutput == null) + { + await Context.SendSadMessage(); + return; + } + + if (jsonOutput.cpuTime != null && jsonOutput.memory != null) + { + await Context.SendMessage(Context.Channel, $"CPU: {jsonOutput.cpuTime * 1000} ms Mem: {jsonOutput.memory} KiB"); + } + + if (jsonOutput.output != null) + { + await Context.SendMessage(Context.Channel, jsonOutput.output); + } + else + { + var jsonErr = JsonConvert.DeserializeObject(output); + await Context.SendMessage(Context.Channel, + $"Ошибка работы API сервиса: {jsonErr.error} ({jsonErr.statusCode})"); + } + } + catch (Exception) + { + await Context.SendMessage(Context.Channel, $"[gray]Не работает короче, блин........"); + } + } + + [Command("executeurl", "execurl")] + [Description("Тоже самое что и exec только работает через URL")] + [Cooldown(5, 3, CooldownMeasure.Minutes, Bot.CooldownBucketType.Global)] + public async Task ExecuteApiUrl(string code, string rawurl) + { + var response = await Context.HttpTools.GetTextPlainResponse(rawurl); + await ExecuteApi(code, response); + } + + [Command("shopcurrency", "shopcur", "curshop", "curshp")] + [Description("Курсы валют различных интернет магазинов. Поддерживается только USD.")] + [Remarks("Параметр shop допускает следующие значения: `ЦБ-РФ`, `Aliexpress`, `GearBest`, `GeekBuying`, `Banggood`")] + public async Task ShopCur(float usd = 1.0f, string shop = "aliexpress") + { + var curs = await InternetServicesHelper.GetShopCurrencies(); + + if (!curs.ContainsKey(shop)) + { + await Context.SendSadMessage(Context.Channel, "Такой интернет магазин не поддерживается"); + return; + } + await Context.SendMessage($"{shop}: {usd} USD -> {curs[shop.ToLower()] * usd} RUB"); + } + + [Command("isup", "isdown", "ping")] + [Description("Работает ли сайт?")] + [Cooldown(5, 1, CooldownMeasure.Minutes, Bot.CooldownBucketType.Channel)] + public async Task IsUp(string url) + { + var urik = new UriBuilder(url); + bool response = await Context.HttpTools.PingHost(urik.Host); + if (response) + { + await Context.SendMessage(Context.Channel, $"[green]{urik.Host}: Работает!"); + } + else + { + await Context.SendMessage(Context.Channel, $"[red]{urik.Host}: Не смог установить соединение..."); + } + } + + [Command("isblocked", "blocked", "block", "blk")] + [Description("Заблокирован ли сайт в России?")] + public async Task IsBlocked(string url) + { + var output = await Context.HttpTools.PostJson("https://isitblockedinrussia.com/", new IsBlockedInRussia.RequestRoot() { host = url }); + var jsonOutput = JsonConvert.DeserializeObject(output); + + int totalblocks = 0; + int totalips = jsonOutput.ips.Count; + + foreach (var item in jsonOutput.ips) + { + if (item.blocked.Any()) + { + totalblocks += 1; + } + } + + if (totalblocks > 0 || jsonOutput.domain.blocked.Any()) + { + await Context.SendMessage(Context.Channel, $"[b]{url}[r]: заблокировано [red]{totalblocks}[r] айпишников из [green]{totalips}[r]!!!" + + $" Также заблочено доменов: [b][red]{jsonOutput.domain.blocked.Count}[r] Подробнее: https://isitblockedinrussia.com/?host={url}"); + } + else + { + await Context.SendMessage(Context.Channel, $"[green]{url}: Не заблокирован!"); + } + } + + [Command("whrand", "whowrand", "howrand")] + public async Task WikiHowRand() + { + var resp = await Context.HttpTools.GetResponseAsync("https://ru.wikihow.com/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:Randomizer"); + resp.EnsureSuccessStatusCode(); + + if (resp.RequestMessage != null && resp.RequestMessage.RequestUri != null) + { + await Context.SendMessage(Context.Channel, resp.RequestMessage.RequestUri.ToString()); + } + else + { + await Context.SendSadMessage(); + } + } + + + [Command("cur", "currency", "coin")] + [Description("Конвертер валют")] + public async Task Currency(float amount = 1, string codeFirst = "USD", string codeSecond = "RUB", string bankProvider = "") + { + var resp = await Context.HttpTools.GetResponseAsync + ("https://api.exchangerate.host/latest?base=" + codeFirst + "&amount=" + amount + "&symbols=" + codeSecond + "&format=csv&source=" + bankProvider); + + + resp.EnsureSuccessStatusCode(); + + // "code","rate","base","date" + // "RUB","82,486331","USD","2022-04-07" -- this + try + { + string currency = resp.Content.ReadAsStringAsync().Result.Split("\n")[1]; + var info = currency.Split("\",\""); + string gotConvCode = info[0].Replace("\"", ""); + string valueString = info[1].Replace("\"", ""); + string gotCode = info[2].Replace("\"", ""); + + if (valueString == "NaN") { valueString = "∞"; } + + await Context.SendMessage(bankProvider.ToUpper() + ": " + amount + " " + gotCode + " -> " + valueString + " " + gotConvCode); + } + catch (IndexOutOfRangeException) + { + await Context.SendSadMessage(); + } + } + + [Command("stocks", "stock")] + [Description("Акции. параметр lookUpOnlySymbol позволяет сразу искать акцию по символу, а не названию компании")] + public async Task Stocks(string stock = "AAPL", bool lookUpOnlySymbol = true) + { + var symbolLockup = await Context.HttpTools.GetJson( + "https://finnhub.io/api/v1/search?q=" + stock + "&token=" + + ConfigurationProvider.Config.Services.FinnhubKey); + + var lookup = symbolLockup.result.FirstOrDefault(); + + if (lookup == null) + { + await Context.SendSadMessage(); + return; + } + + var resp = await Context.HttpTools.GetResponseAsync("https://finnhub.io/api/v1/quote?symbol=" + lookup.symbol + + "&token=" + ConfigurationProvider.Config.Services.FinnhubKey); + + if (resp == null || lookUpOnlySymbol) + { + // trying just find stock by symbol + resp = await Context.HttpTools.GetResponseAsync("https://finnhub.io/api/v1/quote?symbol=" + stock + + "&token=" + ConfigurationProvider.Config.Services.FinnhubKey); + if (resp == null) + { + // give up + return; + } + } + + var stockObj = JsonConvert.DeserializeObject(await resp.Content.ReadAsStringAsync()); + + if (stockObj == null) + { + await Context.SendSadMessage(Context.Channel, "Не удалось найти акцию!"); + return; + } + + await Context.SendMessage( + $"({lookup.description}) {lookup.symbol} [b]{stockObj.c} USD[r] (низ: [red]{stockObj.l} [r]/ выс: [green]{stockObj.h})"); + } + + [Command("curcmp", "currencycomapre", "currencycomp", "curcompare", "ccmp")] + public async Task CurrencyCompare(float amount = 1, string codeFirst = "USD", string codeSecond = "RUB") + { + foreach (string bank in new string[] { "boc", "nbu", "bnro", "nob" }) + { + await Currency(amount, codeFirst, codeSecond, bank); + } + } + + [Command("wh", "wikihow")] + public async Task WikiHow([Remainder] string query) + { + var web = new HtmlWeb(); + var doc = await web.LoadFromWebAsync("https://ru.wikihow.com/wikiHowTo?search=" + query); + HtmlNodeCollection divContainer = doc.DocumentNode.SelectNodes("//a[@class=\"result_link\"]"); + if (divContainer != null) + { + foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//br")) + node.ParentNode.ReplaceChild(doc.CreateTextNode("\n"), node); + + foreach (var node in divContainer) + { + Log.Verbose(node.InnerText); + string hrefValue = node.GetAttributeValue("href", string.Empty); + var title = node.SelectSingleNode("//div[@class=\"result\"]").SelectSingleNode("//div[@class=\"result_title\"]"); + await Context.SendMessage(Context.Channel, $"{title.InnerText} // {hrefValue}"); + break; + } + } + } + + [Command("prz", "prazdnik", "holiday", "kakojsegodnjaprazdnik")] + [Description("Какой сегодня или завтра праздник?")] + public async Task Holiday(uint month = 0, uint day = 0) + { + + if (month == 0 || month > 12) + { + month = (uint)DateTime.Now.Month; + } + + if (day == 0) + { + day = (uint)DateTime.Now.Day; + } + + var humanMonth = new Dictionary() + { + {1, "yanvar" }, + {2, "fevral" }, + {3, "mart" }, + {4, "aprel" }, + {5, "may" }, + {6, "iyun" }, + {7, "iyul" }, + {8, "avgust" }, + {9, "sentyabr"}, + {10, "oktyabr"}, + {11, "noyabr" }, + {12, "dekabr" }, + }; + + + string url = "https://kakoysegodnyaprazdnik.ru/baza/" + humanMonth[(int)month] + "/" + day; + + var response = await Context.HttpTools.GetResponseAsync(url); + Log.Verbose(url); + var doc = new HtmlDocument(); + doc.LoadHtml(await response.Content.ReadAsStringAsync()); + + var outputs = new List(); + + HtmlNodeCollection divContainer = doc.DocumentNode.SelectNodes("//div[@itemprop='suggestedAnswer']//span[@itemprop='text']"); + if (divContainer != null) + { + foreach (var node in divContainer) + { + outputs.Add(node.InnerText); + } + } + + await Context.SendMessage(Context.Channel, $"[b]{day}-{month}-{DateTime.Today.Year}:[r] у нас: [b]{outputs.Random()}"); + } + + [Command("wa", "wolfram", "wolframalpha")] + [Description("Wolfram|Alpha — база знаний и набор вычислительных алгоритмов, вопросно-ответная система. Не является поисковой системой.")] + [Cooldown(20, 10, CooldownMeasure.Minutes, Bot.CooldownBucketType.Global)] + public async Task Wolfram([Remainder] string query) + { + WolframAlphaClient client = new WolframAlphaClient(ConfigurationProvider.Config.Services.WolframID); + var results = await client.QueryAsync(query); + + if (results.IsError) + { + Context.SendErrorMessage(Context.Channel, $"Ошибка при работе сервиса: {results.ErrorDetails}"); + return; + } + + if (!results.IsSuccess || !results.Pods.Any()) + { + await Context.SendSadMessage(); + return; + } + + var result = results.Pods[0].SubPods[0].Plaintext; + + foreach (var pod in results.Pods.Take(3)) + { + if (pod.IsPrimary) + { + foreach (var subPod in pod.SubPods) + { + if (!string.IsNullOrEmpty(subPod.Plaintext)) + { + var output = subPod.Plaintext.Split("\n"); + await Context.SendMessage(Context.Channel, $"[b]{result}[r] = {string.Join(" ", output)}"); + return; + } + } + } + } + + // falling back to old view + foreach (var pod in results.Pods.Take(2)) + { + foreach (var subPod in pod.SubPods.Take(2)) + { + if (!string.IsNullOrEmpty(subPod.Plaintext)) + await Context.SendMessage(Context.Channel, $"[b]{pod.Title}: [r]{subPod.Plaintext}"); + } + } + } + + [Command("pearls", "inpearls", "inp", "ip")] + [Description("Самые душевные цитаты в мире!")] + public async Task InPearls(string category = "", int page = 0) + { + var pagenum = Context.Random.Next(page, 36); + try + { + var output = await Context.ServicesHelper.InPearls(category, pagenum); + + if (output.Any()) + { + await Context.SendMessage(Context.Channel, output.Random()); + } + else + { + await Context.SendSadMessage(); + } + } + catch (InvalidOperationException e) + { + await Context.SendSadMessage(Context.Channel, $"Не удалось получить цитаты с inpearls: {e.Message}"); + } + } + + [Command("talk", "chatbot")] + [Description("Чатбот")] + public async Task Chatbot([Remainder] string message) + { + ChatBotResponse jsonOutput; + for (int i = 0; i < 5; i++) + { + var fmt = $"{Context.User.Username}: {message}\nuser2: "; + var msg = new ChatBotRequest(fmt); + try + { + var output = await Context.HttpTools.PostJson("https://pelevin.gpt.dobro.ai/generate/", msg); + jsonOutput = JsonConvert.DeserializeObject(output); + if (jsonOutput != null) + { + var reply = jsonOutput.Replies.FirstOrDefault(); + if (reply != null) + { + var containsBadword = RandomMsgs.BadWordsSubstrings.Any(x => reply.ToLower().Contains(x)); ; + + if (!containsBadword) + { + await Context.SendMessage(Context.Channel, $"{Context.User.Username}: {jsonOutput.Replies.FirstOrDefault()}"); + return; + } + } + } + else + { + await Context.SendMessage(Context.Channel, $"{Context.User.Username}: я не понимаю о чем ты"); + return; + } + } + catch (HttpRequestException) + { + break; + } + } + + await Context.SendMessage(Context.Channel, $"{Context.User.Username}: {RandomMsgs.NotFoundMessages.Random()}"); + } + + [Command("mc", "minecraft", "mineserver", "mineserv")] + [Description("Информация о сервере Minecraft")] + public async Task MinecraftQuery(string ipaddr) + { + var hostname = Context.HttpTools.ParseHostname(ipaddr); + MCServer server = new MCServer(hostname.Address.ToString(), hostname.Port); + ServerStatus status = server.Status(); + double ping = server.Ping(); + + await Context.SendMessage(Context.Channel, + $"[b]{ipaddr}[r]: " + + $"({status.Version.Name}): Игроки: [b]{status.Players.Online}/{status.Players.Max}[r] [green]Пинг: {ping} мс"); + } + + [Command("oweather", "openweather", "openweathermap")] + public async Task OpenWeatherMap([Remainder] string omskWhereYouLive = "") + { + string city = Context.User.GetCity(omskWhereYouLive); + if (city == "" && omskWhereYouLive == "") + { + await Context.SendSadMessage(Context.Channel, "Пожалуйста, установите город!"); + return; + } + + try + { + var wr = await Context.ServicesHelper.OpenWeatherMap(city); + + await Context.SendMessage($"[b]{wr.CityName}[r]: {wr.Condition.GetDescription()} {wr.Temperature} °C" + + $" (ощущения: [b]{wr.FeelsLike} °C[r]) Влажность: [b]{wr.Humidity}%[r] Ветер: [b]{wr.WindDirection.GetDescription()} {wr.WindHeading}° {(wr.WindSpeed * 1.944):0.0} kts {wr.WindSpeed} m/s[r]"); + } + catch (Exception) + { + await Context.SendSadMessage(); + } + } + + + [Command("metar", "mweather")] + [Description("Запрос METAR информации о погоде")] + public async Task Metar(string airportIcao = "URWW", bool rawOutput = false) + { + + var response = await Context.HttpTools.GetJson>($"https://aviationweather.gov/cgi-bin/data/metar.php?ids={airportIcao}&format=json"); + + var metar = response.FirstOrDefault(); + + if (!rawOutput) + { + if (metar == null) + { + await Context.SendSadMessage(); + return; + } + + int wind = metar.Wspd; + + if (metar.RawOb.Contains("MPS")) + { + wind = (int)Math.Floor(wind * 1.944); + } + + await Context.SendMessage($"[b]{metar.ReportTime}: {metar.IcaoId} ({metar.Name}):[r] [b]{metar.Temp}°C[r] QNH: [b]{metar.Altim}[r] hPA Ветер: [b]{metar.Wdir}° {wind} kts [r]Видимость: [b]{metar.Visib}[r]"); + } + else + { + await Context.SendMessage(metar.RawOb); + } + } + + [Command("weather", "yanderweather")] + public async Task YandexWeather([Remainder] string omskWhereYouLive = "") + { + string city = Context.User.GetCity(omskWhereYouLive); + if (city == "" && omskWhereYouLive == "") + { + await Context.SendSadMessage(Context.Channel, "Пожалуйста, установите город!"); + return; + } + + try + { + var wr = await Context.ServicesHelper.YandexWeather(city); + await Context.SendMessage($"По данным Яндекс.Погоды в [b]{wr.CityName}[r]: {wr.Condition.GetDescription()} {wr.Temperature} °C" + + $" (ощущения: {wr.FeelsLike} °C) Влажность: {wr.Humidity}% Ветер: {wr.WindDirection.GetDescription()} ~{wr.WindHeading}° {(wr.WindSpeed * 1.944):0.0} kts {wr.WindSpeed} m/s"); + } + catch (ArgumentNullException) + { + await Context.SendSadMessage(); + } + catch (Exception) + { + await Context.SendSadMessage(Context.Channel, "Яндекс.Погода не работает, пробуем OpenWeatherMap..."); + await OpenWeatherMap(omskWhereYouLive); + } + } +} diff --git a/fs24bot3/Core/Database.cs b/fs24bot3/Core/Database.cs index 4d4ee26..1b45a05 100644 --- a/fs24bot3/Core/Database.cs +++ b/fs24bot3/Core/Database.cs @@ -78,8 +78,8 @@ public static void InitDatabase(in SQLiteConnection connection) }); } connection.Commit(); - } - Log.Information("Vacuuming database this can take some time..."); + } + Log.Information("Vacuuming database this can take some time..."); connection.Execute("VACUUM"); Log.Information("Databases loaded!"); } diff --git a/fs24bot3/Core/EnumExtensions.cs b/fs24bot3/Core/EnumExtensions.cs index 0dc617c..4f1bd57 100644 --- a/fs24bot3/Core/EnumExtensions.cs +++ b/fs24bot3/Core/EnumExtensions.cs @@ -1,32 +1,32 @@ -using System; -using System.ComponentModel; -using System.Reflection; - -namespace fs24bot3.Core; -public static class EnumExtensions -{ - public static string GetDescription(this T enumerationValue) where T : struct - { - Type type = enumerationValue.GetType(); - if (!type.IsEnum) - { - throw new ArgumentException("EnumerationValue must be of Enum type", nameof(enumerationValue)); - } - - //Tries to find a DescriptionAttribute for a potential friendly name - //for the enum - MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString()); - if (memberInfo != null && memberInfo.Length > 0) - { - object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); - - if (attrs != null && attrs.Length > 0) - { - //Pull out the description value - return ((DescriptionAttribute)attrs[0]).Description; - } - } - //If we have no description attribute, just return the ToString of the enum - return enumerationValue.ToString(); - } +using System; +using System.ComponentModel; +using System.Reflection; + +namespace fs24bot3.Core; +public static class EnumExtensions +{ + public static string GetDescription(this T enumerationValue) where T : struct + { + Type type = enumerationValue.GetType(); + if (!type.IsEnum) + { + throw new ArgumentException("EnumerationValue must be of Enum type", nameof(enumerationValue)); + } + + //Tries to find a DescriptionAttribute for a potential friendly name + //for the enum + MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString()); + if (memberInfo != null && memberInfo.Length > 0) + { + object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); + + if (attrs != null && attrs.Length > 0) + { + //Pull out the description value + return ((DescriptionAttribute)attrs[0]).Description; + } + } + //If we have no description attribute, just return the ToString of the enum + return enumerationValue.ToString(); + } } \ No newline at end of file diff --git a/fs24bot3/Core/LuaExecutor.cs b/fs24bot3/Core/LuaExecutor.cs index 5454e11..9185a7f 100644 --- a/fs24bot3/Core/LuaExecutor.cs +++ b/fs24bot3/Core/LuaExecutor.cs @@ -99,7 +99,7 @@ public async Task Execute(string senderNick, string channel, string message, str try { - var res = (string)lua.DoString(Command.Output)[0]; + var res = lua.DoString(Command.Output)[0].ToString(); await Context.Client.SendMessage(channel, res); } catch (Exception e) diff --git a/fs24bot3/EventProcessors/OnMsgEvent.cs b/fs24bot3/EventProcessors/OnMsgEvent.cs index 7db42d3..6034b4e 100644 --- a/fs24bot3/EventProcessors/OnMsgEvent.cs +++ b/fs24bot3/EventProcessors/OnMsgEvent.cs @@ -13,6 +13,8 @@ using static fs24bot3.Models.OpenWeatherMapResponse; using NetIRC; using System.Collections.Generic; +using static fs24bot3.Models.BandcampSearch; +using static fs24bot3.Models.APIExec; namespace fs24bot3.EventProcessors; public class OnMsgEvent @@ -20,6 +22,7 @@ public class OnMsgEvent private readonly Bot BotContext; private readonly Random Rand = new Random(); private readonly Regex YoutubeRegex = new Regex(@"(?:https?:)?(?:\/\/)?(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*?[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['\""][^<>]*>|<\/a>))[?=&+%\w.-]*", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline); + private readonly Regex URLRegex = new Regex(@"https?:\/\/\S*", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline); public OnMsgEvent(Bot botCtx) { @@ -39,7 +42,7 @@ public async void LevelInscrease(Shop shop, MessageGeneric message) { message.Sender.CreateAccountIfNotExist(); message.Sender.SetLastMessage(); - bool newLevel = message.Sender.IncreaseXp(message.Body.Length * new Random().Next(1, 3)); + bool newLevel = message.Sender.IncreaseXp(message.Body.Length); if (newLevel) { var report = message.Sender.AddRandomRarityItem(shop, ItemInventory.ItemRarity.Rare); @@ -47,6 +50,24 @@ public async void LevelInscrease(Shop shop, MessageGeneric message) } } + public async void HandleURL(MessageGeneric message) + { + var http = new HttpTools(); + + MatchCollection matches = URLRegex.Matches(message.Body); + + foreach (var match in matches) + { + var response = await http.GetResponseAsync(match.ToString()); + + if (response.IsSuccessStatusCode) + { + string text = await response.Content.ReadAsStringAsync(); + + } + } + } + public async void DestroyWallRandomly(Shop shop, MessageGeneric message) { if (Rand.Next(0, 10) == 1 && await message.Sender.RemItemFromInv(shop, "wall", 1)) diff --git a/fs24bot3/Helpers/JsonSerializerHelper.cs b/fs24bot3/Helpers/JsonSerializerHelper.cs index 72881af..51ec5c0 100644 --- a/fs24bot3/Helpers/JsonSerializerHelper.cs +++ b/fs24bot3/Helpers/JsonSerializerHelper.cs @@ -1,11 +1,11 @@ -using Newtonsoft.Json; - -namespace fs24bot3.Helpers; -public class JsonSerializerHelper -{ - public static readonly JsonSerializerSettings OPTIMIMAL_SETTINGS = new JsonSerializerSettings() - { - NullValueHandling = NullValueHandling.Ignore, - MissingMemberHandling = MissingMemberHandling.Ignore, - }; +using Newtonsoft.Json; + +namespace fs24bot3.Helpers; +public class JsonSerializerHelper +{ + public static readonly JsonSerializerSettings OPTIMIMAL_SETTINGS = new JsonSerializerSettings() + { + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + }; } \ No newline at end of file diff --git a/fs24bot3/ItemTraits/BasicItem.cs b/fs24bot3/ItemTraits/BasicItem.cs index 97a7533..4ba72c6 100644 --- a/fs24bot3/ItemTraits/BasicItem.cs +++ b/fs24bot3/ItemTraits/BasicItem.cs @@ -1,19 +1,19 @@ -using fs24bot3.Models; - -namespace fs24bot3.ItemTraits; - -public class BasicItem : IItem -{ - public string Name { get; } - public int Price { get; set; } - public bool Sellable { get; set; } - public ItemInventory.ItemRarity Rarity { get; set; } - - public BasicItem(string name, int price = 0, ItemInventory.ItemRarity rarity = ItemInventory.ItemRarity.Common, bool sellabe = true) - { - Name = name; - Price = price; - Sellable = sellabe; - Rarity = rarity; - } +using fs24bot3.Models; + +namespace fs24bot3.ItemTraits; + +public class BasicItem : IItem +{ + public string Name { get; } + public int Price { get; set; } + public bool Sellable { get; set; } + public ItemInventory.ItemRarity Rarity { get; set; } + + public BasicItem(string name, int price = 0, ItemInventory.ItemRarity rarity = ItemInventory.ItemRarity.Common, bool sellabe = true) + { + Name = name; + Price = price; + Sellable = sellabe; + Rarity = rarity; + } } \ No newline at end of file diff --git a/fs24bot3/ItemTraits/IItem.cs b/fs24bot3/ItemTraits/IItem.cs index 9ed3f93..a884421 100644 --- a/fs24bot3/ItemTraits/IItem.cs +++ b/fs24bot3/ItemTraits/IItem.cs @@ -1,32 +1,32 @@ -using System.Threading.Tasks; - -namespace fs24bot3.ItemTraits; - -public interface IItem -{ - public string Name { get; } - public int Price { get; set; } - public bool Sellable { get; set; } - public Models.ItemInventory.ItemRarity Rarity { get; set; } - - public async Task OnUseMyself(Bot botCtx, string channel, Core.User user) - { - await botCtx.Client.SendMessage(channel, "Этот предмет невозможно использовать на себе!"); - return false; - } - public async Task OnUseOnUser(Bot botCtx, string channel, Core.User user, Core.User targetUser) - { - await botCtx.Client.SendMessage(channel, "Этот предмет невозможно применить на другом пользователе!"); - return false; - } - - public bool OnAdd(Bot botCtx, string channel, Core.User user, Core.User targetUser) - { - return false; - } - - public bool OnDel(Bot botCtx, string channel, Core.User user, Core.User targetUser) - { - return false; - } +using System.Threading.Tasks; + +namespace fs24bot3.ItemTraits; + +public interface IItem +{ + public string Name { get; } + public int Price { get; set; } + public bool Sellable { get; set; } + public Models.ItemInventory.ItemRarity Rarity { get; set; } + + public async Task OnUseMyself(Bot botCtx, string channel, Core.User user) + { + await botCtx.Client.SendMessage(channel, "Этот предмет невозможно использовать на себе!"); + return false; + } + public async Task OnUseOnUser(Bot botCtx, string channel, Core.User user, Core.User targetUser) + { + await botCtx.Client.SendMessage(channel, "Этот предмет невозможно применить на другом пользователе!"); + return false; + } + + public bool OnAdd(Bot botCtx, string channel, Core.User user, Core.User targetUser) + { + return false; + } + + public bool OnDel(Bot botCtx, string channel, Core.User user, Core.User targetUser) + { + return false; + } } \ No newline at end of file diff --git a/fs24bot3/Models/ChatBot.cs b/fs24bot3/Models/ChatBot.cs index c0c8500..11c1f5b 100644 --- a/fs24bot3/Models/ChatBot.cs +++ b/fs24bot3/Models/ChatBot.cs @@ -1,24 +1,24 @@ -using Newtonsoft.Json; -using System.Collections.Generic; - -namespace fs24bot3.Models; - -public class ChatBotResponse -{ - [JsonProperty("replies")] public List Replies { get; set; } -} - -public class ChatBotRequest -{ - [JsonProperty("prompt")] - public string Prompt { get; set; } - - [JsonProperty("length")] - public int Length { get; set; } - - public ChatBotRequest(string message) - { - Prompt = message; - Length = message.Length; - } +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace fs24bot3.Models; + +public class ChatBotResponse +{ + [JsonProperty("replies")] public List Replies { get; set; } +} + +public class ChatBotRequest +{ + [JsonProperty("prompt")] + public string Prompt { get; set; } + + [JsonProperty("length")] + public int Length { get; set; } + + public ChatBotRequest(string message) + { + Prompt = message; + Length = message.Length; + } } \ No newline at end of file diff --git a/fs24bot3/Models/LibreTranslate.cs b/fs24bot3/Models/LibreTranslate.cs index 8750b70..38459ec 100644 --- a/fs24bot3/Models/LibreTranslate.cs +++ b/fs24bot3/Models/LibreTranslate.cs @@ -1,47 +1,47 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace fs24bot3.Models -{ - public class LibreTranslate - { - public class DetectedLanguage - { - [JsonProperty("language")] - public string Language { get; set; } - } - - public class Response - { - [JsonProperty("detectedLanguage")] - public DetectedLanguage DetectedLanguage { get; set; } - - [JsonProperty("translatedText")] - public string TranslatedText { get; set; } - } - - - public class Request - { - [JsonProperty("q")] - public string RequestText { get; set; } - - [JsonProperty("source")] - public string Source { get; set; } - - [JsonProperty("target")] - public string Target { get; set; } - - [JsonProperty("format")] - public string Format { get; set; } - - [JsonProperty("api_key")] - public string ApiKey { get; set; } - } - - } -} +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace fs24bot3.Models +{ + public class LibreTranslate + { + public class DetectedLanguage + { + [JsonProperty("language")] + public string Language { get; set; } + } + + public class Response + { + [JsonProperty("detectedLanguage")] + public DetectedLanguage DetectedLanguage { get; set; } + + [JsonProperty("translatedText")] + public string TranslatedText { get; set; } + } + + + public class Request + { + [JsonProperty("q")] + public string RequestText { get; set; } + + [JsonProperty("source")] + public string Source { get; set; } + + [JsonProperty("target")] + public string Target { get; set; } + + [JsonProperty("format")] + public string Format { get; set; } + + [JsonProperty("api_key")] + public string ApiKey { get; set; } + } + + } +} diff --git a/fs24bot3/Models/MessageGeneric.cs b/fs24bot3/Models/MessageGeneric.cs index 945b2eb..517bfd8 100644 --- a/fs24bot3/Models/MessageGeneric.cs +++ b/fs24bot3/Models/MessageGeneric.cs @@ -1,56 +1,56 @@ -using System.Linq; -using fs24bot3.Core; -using fs24bot3.Helpers; -using NetIRC; -using Serilog; -using SQLite; - -namespace fs24bot3.Models; - -public enum MessageKind -{ - Message, - MessagePersonal, - MessageFromBridge -} - -public class MessageGeneric -{ - public string Body { get; } - public Core.User Sender { get; } - public string Target { get; } - public MessageKind Kind { get; } - - public MessageGeneric(in ParsedIRCMessage message, in SQLiteConnection connection, string clientName) - { - Sender = new Core.User(message.Prefix.From, connection); - Target = message.Parameters[0]; - Body = message.Trailing.TrimEnd(); - Kind = MessageKind.Message; - - if (message.Parameters[0] == clientName) - { - Target = message.Prefix.From; - Kind = MessageKind.MessagePersonal; - } - - if (Sender.Username == ConfigurationProvider.Config.Services.BridgeNickname) - { - // trim bridged user nickname like - // //bpm140//: @ms привет - var msg = Body.Split(":"); - Body = msg.Last().TrimStart(' '); - Sender = new Core.User("@[" + MessageHelper.StripIRC(msg.First()) + "]", connection); - Kind = MessageKind.MessageFromBridge; - Log.Verbose("Message from the bridge: {0} from {1}", Body, Sender); - } - } - - public MessageGeneric(string body, string target, Core.User sender, MessageKind messageKind = MessageKind.Message) - { - Body = body; - Target = target; - Sender = sender; - Kind = messageKind; - } +using System.Linq; +using fs24bot3.Core; +using fs24bot3.Helpers; +using NetIRC; +using Serilog; +using SQLite; + +namespace fs24bot3.Models; + +public enum MessageKind +{ + Message, + MessagePersonal, + MessageFromBridge +} + +public class MessageGeneric +{ + public string Body { get; } + public Core.User Sender { get; } + public string Target { get; } + public MessageKind Kind { get; } + + public MessageGeneric(in ParsedIRCMessage message, in SQLiteConnection connection, string clientName) + { + Sender = new Core.User(message.Prefix.From, connection); + Target = message.Parameters[0]; + Body = message.Trailing.TrimEnd(); + Kind = MessageKind.Message; + + if (message.Parameters[0] == clientName) + { + Target = message.Prefix.From; + Kind = MessageKind.MessagePersonal; + } + + if (Sender.Username == ConfigurationProvider.Config.Services.BridgeNickname) + { + // trim bridged user nickname like + // //bpm140//: @ms привет + var msg = Body.Split(":"); + Body = msg.Last().TrimStart(' '); + Sender = new Core.User("@[" + MessageHelper.StripIRC(msg.First()) + "]", connection); + Kind = MessageKind.MessageFromBridge; + Log.Verbose("Message from the bridge: {0} from {1}", Body, Sender); + } + } + + public MessageGeneric(string body, string target, Core.User sender, MessageKind messageKind = MessageKind.Message) + { + Body = body; + Target = target; + Sender = sender; + Kind = messageKind; + } } \ No newline at end of file diff --git a/fs24bot3/Models/MetarWeather.cs b/fs24bot3/Models/MetarWeather.cs index 3b42848..1a84b06 100644 --- a/fs24bot3/Models/MetarWeather.cs +++ b/fs24bot3/Models/MetarWeather.cs @@ -1,124 +1,124 @@ -using Newtonsoft.Json; -using System.Collections.Generic; - -namespace fs24bot3.Models; - -public class MetarWeather -{ - public class Cloud - { - [JsonProperty("cover")] - public string Cover { get; set; } - - [JsonProperty("base")] - public int Base { get; set; } - } - - public class Root - { - [JsonProperty("metar_id")] - public int MetarId { get; set; } - - [JsonProperty("icaoId")] - public string IcaoId { get; set; } - - [JsonProperty("receiptTime")] - public string ReceiptTime { get; set; } - - [JsonProperty("obsTime")] - public int ObsTime { get; set; } - - [JsonProperty("reportTime")] - public string ReportTime { get; set; } - - [JsonProperty("temp")] - public double Temp { get; set; } - - [JsonProperty("dewp")] - public double Dewp { get; set; } - - [JsonProperty("wdir")] - public int Wdir { get; set; } - - [JsonProperty("wspd")] - public int Wspd { get; set; } - - [JsonProperty("wgst")] - public object Wgst { get; set; } - - [JsonProperty("visib")] - public string Visib { get; set; } - - [JsonProperty("altim")] - public double Altim { get; set; } - - [JsonProperty("slp")] - public double Slp { get; set; } - - [JsonProperty("qcField")] - public int QcField { get; set; } - - [JsonProperty("wxString")] - public object WxString { get; set; } - - [JsonProperty("presTend")] - public object PresTend { get; set; } - - [JsonProperty("maxT")] - public object MaxT { get; set; } - - [JsonProperty("minT")] - public object MinT { get; set; } - - [JsonProperty("maxT24")] - public object MaxT24 { get; set; } - - [JsonProperty("minT24")] - public object MinT24 { get; set; } - - [JsonProperty("precip")] - public object Precip { get; set; } - - [JsonProperty("pcp3hr")] - public object Pcp3hr { get; set; } - - [JsonProperty("pcp6hr")] - public object Pcp6hr { get; set; } - - [JsonProperty("pcp24hr")] - public object Pcp24hr { get; set; } - - [JsonProperty("snow")] - public object Snow { get; set; } - - [JsonProperty("vertVis")] - public object VertVis { get; set; } - - [JsonProperty("metarType")] - public string MetarType { get; set; } - - [JsonProperty("rawOb")] - public string RawOb { get; set; } - - [JsonProperty("mostRecent")] - public int MostRecent { get; set; } - - [JsonProperty("lat")] - public double Lat { get; set; } - - [JsonProperty("lon")] - public double Lon { get; set; } - - [JsonProperty("elev")] - public int Elev { get; set; } - - [JsonProperty("prior")] - public int Prior { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("clouds")] - public List Clouds { get; set; } - } +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace fs24bot3.Models; + +public class MetarWeather +{ + public class Cloud + { + [JsonProperty("cover")] + public string Cover { get; set; } + + [JsonProperty("base")] + public int Base { get; set; } + } + + public class Root + { + [JsonProperty("metar_id")] + public int MetarId { get; set; } + + [JsonProperty("icaoId")] + public string IcaoId { get; set; } + + [JsonProperty("receiptTime")] + public string ReceiptTime { get; set; } + + [JsonProperty("obsTime")] + public int ObsTime { get; set; } + + [JsonProperty("reportTime")] + public string ReportTime { get; set; } + + [JsonProperty("temp")] + public double Temp { get; set; } + + [JsonProperty("dewp")] + public double Dewp { get; set; } + + [JsonProperty("wdir")] + public int Wdir { get; set; } + + [JsonProperty("wspd")] + public int Wspd { get; set; } + + [JsonProperty("wgst")] + public object Wgst { get; set; } + + [JsonProperty("visib")] + public string Visib { get; set; } + + [JsonProperty("altim")] + public double Altim { get; set; } + + [JsonProperty("slp")] + public double Slp { get; set; } + + [JsonProperty("qcField")] + public int QcField { get; set; } + + [JsonProperty("wxString")] + public object WxString { get; set; } + + [JsonProperty("presTend")] + public object PresTend { get; set; } + + [JsonProperty("maxT")] + public object MaxT { get; set; } + + [JsonProperty("minT")] + public object MinT { get; set; } + + [JsonProperty("maxT24")] + public object MaxT24 { get; set; } + + [JsonProperty("minT24")] + public object MinT24 { get; set; } + + [JsonProperty("precip")] + public object Precip { get; set; } + + [JsonProperty("pcp3hr")] + public object Pcp3hr { get; set; } + + [JsonProperty("pcp6hr")] + public object Pcp6hr { get; set; } + + [JsonProperty("pcp24hr")] + public object Pcp24hr { get; set; } + + [JsonProperty("snow")] + public object Snow { get; set; } + + [JsonProperty("vertVis")] + public object VertVis { get; set; } + + [JsonProperty("metarType")] + public string MetarType { get; set; } + + [JsonProperty("rawOb")] + public string RawOb { get; set; } + + [JsonProperty("mostRecent")] + public int MostRecent { get; set; } + + [JsonProperty("lat")] + public double Lat { get; set; } + + [JsonProperty("lon")] + public double Lon { get; set; } + + [JsonProperty("elev")] + public int Elev { get; set; } + + [JsonProperty("prior")] + public int Prior { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("clouds")] + public List Clouds { get; set; } + } } \ No newline at end of file diff --git a/fs24bot3/Models/OpenWeatherMapResponse.cs b/fs24bot3/Models/OpenWeatherMapResponse.cs index bee9470..465550f 100644 --- a/fs24bot3/Models/OpenWeatherMapResponse.cs +++ b/fs24bot3/Models/OpenWeatherMapResponse.cs @@ -1,133 +1,133 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace fs24bot3.Models; - -public class OpenWeatherMapResponse -{ - // Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); - public class Clouds - { - [JsonProperty("all")] - public int All { get; set; } - } - - public class Coord - { - [JsonProperty("lon")] - public double Lon { get; set; } - - [JsonProperty("lat")] - public double Lat { get; set; } - } - - public class Main - { - [JsonProperty("temp")] - public double Temp { get; set; } - - [JsonProperty("feels_like")] - public double FeelsLike { get; set; } - - [JsonProperty("temp_min")] - public double TempMin { get; set; } - - [JsonProperty("temp_max")] - public double TempMax { get; set; } - - [JsonProperty("pressure")] - public int Pressure { get; set; } - - [JsonProperty("humidity")] - public int Humidity { get; set; } - - [JsonProperty("sea_level")] - public int SeaLevel { get; set; } - - [JsonProperty("grnd_level")] - public int GrndLevel { get; set; } - } - - public class Root - { - [JsonProperty("coord")] - public Coord Coord { get; set; } - - [JsonProperty("weather")] - public List Weather { get; set; } - - [JsonProperty("base")] - public string Base { get; set; } - - [JsonProperty("main")] - public Main Main { get; set; } - - [JsonProperty("visibility")] - public int Visibility { get; set; } - - [JsonProperty("wind")] - public Wind Wind { get; set; } - - [JsonProperty("clouds")] - public Clouds Clouds { get; set; } - - [JsonProperty("dt")] - public int Dt { get; set; } - - [JsonProperty("sys")] - public Sys Sys { get; set; } - - [JsonProperty("timezone")] - public int Timezone { get; set; } - - [JsonProperty("id")] - public int Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("cod")] - public int Cod { get; set; } - } - - public class Sys - { - [JsonProperty("country")] - public string Country { get; set; } - - [JsonProperty("sunrise")] - public int Sunrise { get; set; } - - [JsonProperty("sunset")] - public int Sunset { get; set; } - } - - public class Weather - { - [JsonProperty("id")] - public int Id { get; set; } - - [JsonProperty("main")] - public string Main { get; set; } - - [JsonProperty("description")] - public string Description { get; set; } - - [JsonProperty("icon")] - public string Icon { get; set; } - } - - public class Wind - { - [JsonProperty("speed")] - public double Speed { get; set; } - - [JsonProperty("deg")] - public int Deg { get; set; } - - [JsonProperty("gust")] - public double Gust { get; set; } - } - - +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace fs24bot3.Models; + +public class OpenWeatherMapResponse +{ + // Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); + public class Clouds + { + [JsonProperty("all")] + public int All { get; set; } + } + + public class Coord + { + [JsonProperty("lon")] + public double Lon { get; set; } + + [JsonProperty("lat")] + public double Lat { get; set; } + } + + public class Main + { + [JsonProperty("temp")] + public double Temp { get; set; } + + [JsonProperty("feels_like")] + public double FeelsLike { get; set; } + + [JsonProperty("temp_min")] + public double TempMin { get; set; } + + [JsonProperty("temp_max")] + public double TempMax { get; set; } + + [JsonProperty("pressure")] + public int Pressure { get; set; } + + [JsonProperty("humidity")] + public int Humidity { get; set; } + + [JsonProperty("sea_level")] + public int SeaLevel { get; set; } + + [JsonProperty("grnd_level")] + public int GrndLevel { get; set; } + } + + public class Root + { + [JsonProperty("coord")] + public Coord Coord { get; set; } + + [JsonProperty("weather")] + public List Weather { get; set; } + + [JsonProperty("base")] + public string Base { get; set; } + + [JsonProperty("main")] + public Main Main { get; set; } + + [JsonProperty("visibility")] + public int Visibility { get; set; } + + [JsonProperty("wind")] + public Wind Wind { get; set; } + + [JsonProperty("clouds")] + public Clouds Clouds { get; set; } + + [JsonProperty("dt")] + public int Dt { get; set; } + + [JsonProperty("sys")] + public Sys Sys { get; set; } + + [JsonProperty("timezone")] + public int Timezone { get; set; } + + [JsonProperty("id")] + public int Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("cod")] + public int Cod { get; set; } + } + + public class Sys + { + [JsonProperty("country")] + public string Country { get; set; } + + [JsonProperty("sunrise")] + public int Sunrise { get; set; } + + [JsonProperty("sunset")] + public int Sunset { get; set; } + } + + public class Weather + { + [JsonProperty("id")] + public int Id { get; set; } + + [JsonProperty("main")] + public string Main { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("icon")] + public string Icon { get; set; } + } + + public class Wind + { + [JsonProperty("speed")] + public double Speed { get; set; } + + [JsonProperty("deg")] + public int Deg { get; set; } + + [JsonProperty("gust")] + public double Gust { get; set; } + } + + } \ No newline at end of file diff --git a/fs24bot3/Models/Searx.cs b/fs24bot3/Models/Searx.cs index 6183eae..79a3639 100644 --- a/fs24bot3/Models/Searx.cs +++ b/fs24bot3/Models/Searx.cs @@ -1,80 +1,80 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace fs24bot3.Models; - -public class Searx -{ -// Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); - public class Result - { - [JsonProperty("url")] - public string Url { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("content")] - public string Content { get; set; } - - [JsonProperty("engine")] - public string Engine { get; set; } - - [JsonProperty("parsed_url")] - public List ParsedUrl { get; set; } - - [JsonProperty("template")] - public string Template { get; set; } - - [JsonProperty("engines")] - public List Engines { get; set; } - - [JsonProperty("positions")] - public List Positions { get; set; } - - [JsonProperty("score")] - public double Score { get; set; } - - [JsonProperty("category")] - public string Category { get; set; } - - [JsonProperty("pretty_url")] - public string PrettyUrl { get; set; } - - [JsonProperty("open_group")] - public bool OpenGroup { get; set; } - - [JsonProperty("close_group")] - public bool? CloseGroup { get; set; } - } - - public class Root - { - [JsonProperty("query")] - public string Query { get; set; } - - [JsonProperty("number_of_results")] - public ulong NumberOfResults { get; set; } - - [JsonProperty("results")] - public List Results { get; set; } - - [JsonProperty("answers")] - public List Answers { get; set; } - - [JsonProperty("corrections")] - public List Corrections { get; set; } - - [JsonProperty("infoboxes")] - public List Infoboxes { get; set; } - - [JsonProperty("suggestions")] - public List Suggestions { get; set; } - - [JsonProperty("unresponsive_engines")] - public List> UnresponsiveEngines { get; set; } - } - - - +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace fs24bot3.Models; + +public class Searx +{ +// Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); + public class Result + { + [JsonProperty("url")] + public string Url { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("content")] + public string Content { get; set; } + + [JsonProperty("engine")] + public string Engine { get; set; } + + [JsonProperty("parsed_url")] + public List ParsedUrl { get; set; } + + [JsonProperty("template")] + public string Template { get; set; } + + [JsonProperty("engines")] + public List Engines { get; set; } + + [JsonProperty("positions")] + public List Positions { get; set; } + + [JsonProperty("score")] + public double Score { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("pretty_url")] + public string PrettyUrl { get; set; } + + [JsonProperty("open_group")] + public bool OpenGroup { get; set; } + + [JsonProperty("close_group")] + public bool? CloseGroup { get; set; } + } + + public class Root + { + [JsonProperty("query")] + public string Query { get; set; } + + [JsonProperty("number_of_results")] + public ulong NumberOfResults { get; set; } + + [JsonProperty("results")] + public List Results { get; set; } + + [JsonProperty("answers")] + public List Answers { get; set; } + + [JsonProperty("corrections")] + public List Corrections { get; set; } + + [JsonProperty("infoboxes")] + public List Infoboxes { get; set; } + + [JsonProperty("suggestions")] + public List Suggestions { get; set; } + + [JsonProperty("unresponsive_engines")] + public List> UnresponsiveEngines { get; set; } + } + + + } \ No newline at end of file diff --git a/fs24bot3/Models/SproutMessage.cs b/fs24bot3/Models/SproutMessage.cs index 4eb9f02..2019bb4 100644 --- a/fs24bot3/Models/SproutMessage.cs +++ b/fs24bot3/Models/SproutMessage.cs @@ -1,22 +1,22 @@ -using Newtonsoft.Json; -using System; -using System.ComponentModel; - -namespace fs24bot3.Models; - -public enum Kind -{ - Message, - ServerMessage -} -public class SproutMessage -{ - [JsonProperty("author")] - public string Nick { get; set; } - [JsonProperty("body")] - public string Message { get; set; } - [JsonProperty("time")] - public DateTime Date { get; set; } - [DefaultValue(MessageKind.Message)] - public MessageKind Kind { get; set; } -} +using Newtonsoft.Json; +using System; +using System.ComponentModel; + +namespace fs24bot3.Models; + +public enum Kind +{ + Message, + ServerMessage +} +public class SproutMessage +{ + [JsonProperty("author")] + public string Nick { get; set; } + [JsonProperty("body")] + public string Message { get; set; } + [JsonProperty("time")] + public DateTime Date { get; set; } + [DefaultValue(MessageKind.Message)] + public MessageKind Kind { get; set; } +} diff --git a/fs24bot3/Models/Topic.cs b/fs24bot3/Models/Topic.cs index cf2dc3e..cb8d4bd 100644 --- a/fs24bot3/Models/Topic.cs +++ b/fs24bot3/Models/Topic.cs @@ -1,28 +1,28 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace fs24bot3.Models -{ - public class Topic - { - [JsonProperty("article")] - public string Article { get; set; } - - [JsonProperty("language")] - public string Language { get; set; } - - [JsonProperty("numOfTitles")] - public int NumOfTitles { get; set; } - - public Topic(string article, string lauguage = "Russian", int numTitles = 1) - { - Article = article; - Language = lauguage; - NumOfTitles = numTitles; - } - } -} +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace fs24bot3.Models +{ + public class Topic + { + [JsonProperty("article")] + public string Article { get; set; } + + [JsonProperty("language")] + public string Language { get; set; } + + [JsonProperty("numOfTitles")] + public int NumOfTitles { get; set; } + + public Topic(string article, string lauguage = "Russian", int numTitles = 1) + { + Article = article; + Language = lauguage; + NumOfTitles = numTitles; + } + } +} diff --git a/fs24bot3/Models/WeatherEnums.cs b/fs24bot3/Models/WeatherEnums.cs index 1403dbb..3742f55 100644 --- a/fs24bot3/Models/WeatherEnums.cs +++ b/fs24bot3/Models/WeatherEnums.cs @@ -1,66 +1,66 @@ -using System.ComponentModel; - -namespace fs24bot3.Models; - -public enum WeatherConditions -{ - [Description("Ясно")] - Clear, - [Description("Переменная облачность")] - PartlyCloudy, - [Description("Облачно")] - Cloudy, - [Description("Пасмурно")] - Overcast, - [Description("Морось")] - Drizzle, - [Description("Мелкий дождь")] - LightRain, - [Description("Дождь")] - Rain, - [Description("Умеренный дождь")] - ModerateRain, - [Description("Сильный дождь")] - HeavyRain, - [Description("Длительный сильный дождь")] - ContinuousHeavyRain, - [Description("Ливень")] - Showers, - [Description("Мокрый снег")] - WetSnow, - [Description("Рыхлый снег")] - WightSnow, - [Description("Снег")] - Snow, - [Description("Снегопад")] - SnowShowers, - [Description("Град")] - Hail, - [Description("Гроза")] - Thunderstorm, - [Description("Гроза с дождем")] - ThunderstormWithRain, - [Description("Гроза с градом")] - ThunderstormWithHail, -} - -public enum WindDirections { - [Description("⬉")] - Nw, - [Description("⬆")] - N, - [Description("⬈")] - Ne, - [Description("⮕")] - E, - [Description("⬊")] - Se, - [Description("⬇")] - S, - [Description("⬋")] - Sw, - [Description("⬅")] - W, - [Description("*")] - C, +using System.ComponentModel; + +namespace fs24bot3.Models; + +public enum WeatherConditions +{ + [Description("Ясно")] + Clear, + [Description("Переменная облачность")] + PartlyCloudy, + [Description("Облачно")] + Cloudy, + [Description("Пасмурно")] + Overcast, + [Description("Морось")] + Drizzle, + [Description("Мелкий дождь")] + LightRain, + [Description("Дождь")] + Rain, + [Description("Умеренный дождь")] + ModerateRain, + [Description("Сильный дождь")] + HeavyRain, + [Description("Длительный сильный дождь")] + ContinuousHeavyRain, + [Description("Ливень")] + Showers, + [Description("Мокрый снег")] + WetSnow, + [Description("Рыхлый снег")] + WightSnow, + [Description("Снег")] + Snow, + [Description("Снегопад")] + SnowShowers, + [Description("Град")] + Hail, + [Description("Гроза")] + Thunderstorm, + [Description("Гроза с дождем")] + ThunderstormWithRain, + [Description("Гроза с градом")] + ThunderstormWithHail, +} + +public enum WindDirections { + [Description("⬉")] + Nw, + [Description("⬆")] + N, + [Description("⬈")] + Ne, + [Description("⮕")] + E, + [Description("⬊")] + Se, + [Description("⬇")] + S, + [Description("⬋")] + Sw, + [Description("⬅")] + W, + [Description("*")] + C, } \ No newline at end of file diff --git a/fs24bot3/Models/WeatherGeneric.cs b/fs24bot3/Models/WeatherGeneric.cs index 16fe351..0c17ff1 100644 --- a/fs24bot3/Models/WeatherGeneric.cs +++ b/fs24bot3/Models/WeatherGeneric.cs @@ -1,13 +1,13 @@ -namespace fs24bot3.Models; - -public class WeatherGeneric -{ - public double Temperature { get; set; } - public double FeelsLike { get; set; } - public double WindSpeed { get; set; } - public int Humidity { get; set; } - public string CityName { get; set; } - public WeatherConditions Condition { get; set; } - public WindDirections WindDirection { get; set; } - public int WindHeading { get; set; } +namespace fs24bot3.Models; + +public class WeatherGeneric +{ + public double Temperature { get; set; } + public double FeelsLike { get; set; } + public double WindSpeed { get; set; } + public int Humidity { get; set; } + public string CityName { get; set; } + public WeatherConditions Condition { get; set; } + public WindDirections WindDirection { get; set; } + public int WindHeading { get; set; } } \ No newline at end of file diff --git a/fs24bot3/Models/YandexWeather.cs b/fs24bot3/Models/YandexWeather.cs index b465e1b..5d4437e 100644 --- a/fs24bot3/Models/YandexWeather.cs +++ b/fs24bot3/Models/YandexWeather.cs @@ -1,168 +1,168 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace fs24bot3.Models; - -public class YandexWeather -{ - // Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); - public class Fact - { - [JsonProperty("obs_time")] - public int ObsTime { get; set; } - - [JsonProperty("temp")] - public int Temp { get; set; } - - [JsonProperty("feels_like")] - public int FeelsLike { get; set; } - - [JsonProperty("icon")] - public string Icon { get; set; } - - [JsonProperty("condition")] - public string Condition { get; set; } - - [JsonProperty("wind_speed")] - public double WindSpeed { get; set; } - - [JsonProperty("wind_dir")] - public string WindDir { get; set; } - - [JsonProperty("pressure_mm")] - public int PressureMm { get; set; } - - [JsonProperty("pressure_pa")] - public int PressurePa { get; set; } - - [JsonProperty("humidity")] - public int Humidity { get; set; } - - [JsonProperty("daytime")] - public string Daytime { get; set; } - - [JsonProperty("polar")] - public bool Polar { get; set; } - - [JsonProperty("season")] - public string Season { get; set; } - - [JsonProperty("wind_gust")] - public double WindGust { get; set; } - } - - public class Forecast - { - [JsonProperty("date")] - public string Date { get; set; } - - [JsonProperty("date_ts")] - public int DateTs { get; set; } - - [JsonProperty("week")] - public int Week { get; set; } - - [JsonProperty("sunrise")] - public string Sunrise { get; set; } - - [JsonProperty("sunset")] - public string Sunset { get; set; } - - [JsonProperty("moon_code")] - public int MoonCode { get; set; } - - [JsonProperty("moon_text")] - public string MoonText { get; set; } - - [JsonProperty("parts")] - public List Parts { get; set; } - } - - public class Info - { - [JsonProperty("url")] - public string Url { get; set; } - - [JsonProperty("lat")] - public double Lat { get; set; } - - [JsonProperty("lon")] - public double Lon { get; set; } - } - - public class Part - { - [JsonProperty("part_name")] - public string PartName { get; set; } - - [JsonProperty("temp_min")] - public int TempMin { get; set; } - - [JsonProperty("temp_avg")] - public int TempAvg { get; set; } - - [JsonProperty("temp_max")] - public int TempMax { get; set; } - - [JsonProperty("wind_speed")] - public double WindSpeed { get; set; } - - [JsonProperty("wind_gust")] - public double WindGust { get; set; } - - [JsonProperty("wind_dir")] - public string WindDir { get; set; } - - [JsonProperty("pressure_mm")] - public int PressureMm { get; set; } - - [JsonProperty("pressure_pa")] - public int PressurePa { get; set; } - - [JsonProperty("humidity")] - public int Humidity { get; set; } - - [JsonProperty("prec_mm")] - public double PrecMm { get; set; } - - [JsonProperty("prec_prob")] - public double PrecProb { get; set; } - - [JsonProperty("prec_period")] - public double PrecPeriod { get; set; } - - [JsonProperty("icon")] - public string Icon { get; set; } - - [JsonProperty("condition")] - public string Condition { get; set; } - - [JsonProperty("feels_like")] - public int FeelsLike { get; set; } - - [JsonProperty("daytime")] - public string Daytime { get; set; } - - [JsonProperty("polar")] - public bool Polar { get; set; } - } - - public class Root - { - [JsonProperty("now")] - public int Now { get; set; } - - [JsonProperty("now_dt")] - public DateTime NowDt { get; set; } - - [JsonProperty("info")] - public Info Info { get; set; } - - [JsonProperty("fact")] - public Fact FactObj { get; set; } - - [JsonProperty("forecast")] - public Forecast Forecast { get; set; } - } +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace fs24bot3.Models; + +public class YandexWeather +{ + // Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); + public class Fact + { + [JsonProperty("obs_time")] + public int ObsTime { get; set; } + + [JsonProperty("temp")] + public int Temp { get; set; } + + [JsonProperty("feels_like")] + public int FeelsLike { get; set; } + + [JsonProperty("icon")] + public string Icon { get; set; } + + [JsonProperty("condition")] + public string Condition { get; set; } + + [JsonProperty("wind_speed")] + public double WindSpeed { get; set; } + + [JsonProperty("wind_dir")] + public string WindDir { get; set; } + + [JsonProperty("pressure_mm")] + public int PressureMm { get; set; } + + [JsonProperty("pressure_pa")] + public int PressurePa { get; set; } + + [JsonProperty("humidity")] + public int Humidity { get; set; } + + [JsonProperty("daytime")] + public string Daytime { get; set; } + + [JsonProperty("polar")] + public bool Polar { get; set; } + + [JsonProperty("season")] + public string Season { get; set; } + + [JsonProperty("wind_gust")] + public double WindGust { get; set; } + } + + public class Forecast + { + [JsonProperty("date")] + public string Date { get; set; } + + [JsonProperty("date_ts")] + public int DateTs { get; set; } + + [JsonProperty("week")] + public int Week { get; set; } + + [JsonProperty("sunrise")] + public string Sunrise { get; set; } + + [JsonProperty("sunset")] + public string Sunset { get; set; } + + [JsonProperty("moon_code")] + public int MoonCode { get; set; } + + [JsonProperty("moon_text")] + public string MoonText { get; set; } + + [JsonProperty("parts")] + public List Parts { get; set; } + } + + public class Info + { + [JsonProperty("url")] + public string Url { get; set; } + + [JsonProperty("lat")] + public double Lat { get; set; } + + [JsonProperty("lon")] + public double Lon { get; set; } + } + + public class Part + { + [JsonProperty("part_name")] + public string PartName { get; set; } + + [JsonProperty("temp_min")] + public int TempMin { get; set; } + + [JsonProperty("temp_avg")] + public int TempAvg { get; set; } + + [JsonProperty("temp_max")] + public int TempMax { get; set; } + + [JsonProperty("wind_speed")] + public double WindSpeed { get; set; } + + [JsonProperty("wind_gust")] + public double WindGust { get; set; } + + [JsonProperty("wind_dir")] + public string WindDir { get; set; } + + [JsonProperty("pressure_mm")] + public int PressureMm { get; set; } + + [JsonProperty("pressure_pa")] + public int PressurePa { get; set; } + + [JsonProperty("humidity")] + public int Humidity { get; set; } + + [JsonProperty("prec_mm")] + public double PrecMm { get; set; } + + [JsonProperty("prec_prob")] + public double PrecProb { get; set; } + + [JsonProperty("prec_period")] + public double PrecPeriod { get; set; } + + [JsonProperty("icon")] + public string Icon { get; set; } + + [JsonProperty("condition")] + public string Condition { get; set; } + + [JsonProperty("feels_like")] + public int FeelsLike { get; set; } + + [JsonProperty("daytime")] + public string Daytime { get; set; } + + [JsonProperty("polar")] + public bool Polar { get; set; } + } + + public class Root + { + [JsonProperty("now")] + public int Now { get; set; } + + [JsonProperty("now_dt")] + public DateTime NowDt { get; set; } + + [JsonProperty("info")] + public Info Info { get; set; } + + [JsonProperty("fact")] + public Fact FactObj { get; set; } + + [JsonProperty("forecast")] + public Forecast Forecast { get; set; } + } } \ No newline at end of file diff --git a/fs24bot3/Parsers/LangaugeParser.cs b/fs24bot3/Parsers/LangaugeParser.cs index 0094f73..0e2b85d 100644 --- a/fs24bot3/Parsers/LangaugeParser.cs +++ b/fs24bot3/Parsers/LangaugeParser.cs @@ -1,46 +1,46 @@ -using Qmmands; -using System; -using System.Linq; -using System.Threading.Tasks; - -namespace fs24bot3.Parsers -{ - - public class Language - { - public string From; - public string To; - - public Language(string input) - { - string[] langs = input.Split("-"); - - if (langs.Length > 1) - { - From = langs[0]; - To = langs[1]; - } else - { - throw new FormatException($"`{input}` is not a valid string for constructing Language class"); - } - } - - public override string ToString() - { - return $"{From}-{To}"; - } - } - public class LanugageParser : TypeParser - { - public override ValueTask> ParseAsync(Parameter parameter, string value, CommandContext context) - { - if (string.IsNullOrWhiteSpace(value)) - return TypeParserResult.Failed("Value cannot be null or whitespace."); - - if (value.All(char.IsLetter)) - return TypeParserResult.Failed("Both parts of value must consist of only letters."); - - return TypeParserResult.Successful(new Language(value)); - } - } -} +using Qmmands; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace fs24bot3.Parsers +{ + + public class Language + { + public string From; + public string To; + + public Language(string input) + { + string[] langs = input.Split("-"); + + if (langs.Length > 1) + { + From = langs[0]; + To = langs[1]; + } else + { + throw new FormatException($"`{input}` is not a valid string for constructing Language class"); + } + } + + public override string ToString() + { + return $"{From}-{To}"; + } + } + public class LanugageParser : TypeParser + { + public override ValueTask> ParseAsync(Parameter parameter, string value, CommandContext context) + { + if (string.IsNullOrWhiteSpace(value)) + return TypeParserResult.Failed("Value cannot be null or whitespace."); + + if (value.All(char.IsLetter)) + return TypeParserResult.Failed("Both parts of value must consist of only letters."); + + return TypeParserResult.Successful(new Language(value)); + } + } +} diff --git a/fs24bot3/Systems/Profiler.cs b/fs24bot3/Systems/Profiler.cs index a2486eb..bed26ee 100644 --- a/fs24bot3/Systems/Profiler.cs +++ b/fs24bot3/Systems/Profiler.cs @@ -1,95 +1,95 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using fs24bot3.Models; - -namespace fs24bot3.Systems -{ - public class Profiler - { - private const int WindowSize = 50; - private Dictionary, Stopwatch)> Metrics = new Dictionary, Stopwatch)>(); - - public void AddMetric(string metric) - { - Metrics.Add(metric, (new List(), new Stopwatch())); - } - - public void BeginMeasure(string metric) - { - Metrics[metric].Item2.Start(); - } - - public void EndMeasure(string measure) - { - Metrics[measure].Item2.Stop(); - Metrics[measure].Item1.Add(Metrics[measure].Item2.ElapsedMilliseconds); - Metrics[measure].Item2.Reset(); - if (Metrics[measure].Item1.Count > WindowSize) - { - Metrics[measure].Item1.RemoveAt(0); - } - } - - public float GetMeasureLast(string metric) - { - return !Metrics[metric].Item1.Any() ? 0 : Metrics[metric].Item1.Last(); - } - - public int GetMeasureAvg(string metric) - { - if (!Metrics[metric].Item1.Any()) { return 0; } - return (int)Metrics[metric].Item1.Average(); - } - - public float GetMeasureMin(string metric) - { - return !Metrics[metric].Item1.Any() ? 0 : Metrics[metric].Item1.Min(); - } - - public float GetMeasureMax(string metric) - { - return !Metrics[metric].Item1.Any() ? 0 : Metrics[metric].Item1.Max(); - } - - public string FmtMetric(float metric) - { - if (metric > 1000) - { - return $"[yellow]{(metric / 1000):0.0000} s[r]"; - } - return $"{metric} ms"; - } - - public string Fmt(string metric) - { - if (Metrics[metric].Item1.Any()) - { - return string.Format("{0,15} │ last {1,8} │ avg {2,8} │ min {3,8} │ max {4,8}", metric, - FmtMetric(GetMeasureLast(metric)), - FmtMetric(GetMeasureAvg(metric)), - FmtMetric(GetMeasureMin(metric)), - FmtMetric(GetMeasureMax(metric))); - } - - return $"{0,15} │ last {0,8} │ avg {0,8} │ min {0,8} │ max {0,8}"; - } - - public string FmtAll() - { - var sb = new StringBuilder(); - foreach (var metric in Metrics) - { - if (metric.Value.Item1.Any()) - { - sb.Append(Fmt(metric.Key)); - sb.Append('\n'); - } - } - - return sb.ToString(); - } - } +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using fs24bot3.Models; + +namespace fs24bot3.Systems +{ + public class Profiler + { + private const int WindowSize = 50; + private Dictionary, Stopwatch)> Metrics = new Dictionary, Stopwatch)>(); + + public void AddMetric(string metric) + { + Metrics.Add(metric, (new List(), new Stopwatch())); + } + + public void BeginMeasure(string metric) + { + Metrics[metric].Item2.Start(); + } + + public void EndMeasure(string measure) + { + Metrics[measure].Item2.Stop(); + Metrics[measure].Item1.Add(Metrics[measure].Item2.ElapsedMilliseconds); + Metrics[measure].Item2.Reset(); + if (Metrics[measure].Item1.Count > WindowSize) + { + Metrics[measure].Item1.RemoveAt(0); + } + } + + public float GetMeasureLast(string metric) + { + return !Metrics[metric].Item1.Any() ? 0 : Metrics[metric].Item1.Last(); + } + + public int GetMeasureAvg(string metric) + { + if (!Metrics[metric].Item1.Any()) { return 0; } + return (int)Metrics[metric].Item1.Average(); + } + + public float GetMeasureMin(string metric) + { + return !Metrics[metric].Item1.Any() ? 0 : Metrics[metric].Item1.Min(); + } + + public float GetMeasureMax(string metric) + { + return !Metrics[metric].Item1.Any() ? 0 : Metrics[metric].Item1.Max(); + } + + public string FmtMetric(float metric) + { + if (metric > 1000) + { + return $"[yellow]{(metric / 1000):0.0000} s[r]"; + } + return $"{metric} ms"; + } + + public string Fmt(string metric) + { + if (Metrics[metric].Item1.Any()) + { + return string.Format("{0,15} │ last {1,8} │ avg {2,8} │ min {3,8} │ max {4,8}", metric, + FmtMetric(GetMeasureLast(metric)), + FmtMetric(GetMeasureAvg(metric)), + FmtMetric(GetMeasureMin(metric)), + FmtMetric(GetMeasureMax(metric))); + } + + return $"{0,15} │ last {0,8} │ avg {0,8} │ min {0,8} │ max {0,8}"; + } + + public string FmtAll() + { + var sb = new StringBuilder(); + foreach (var metric in Metrics) + { + if (metric.Value.Item1.Any()) + { + sb.Append(Fmt(metric.Key)); + sb.Append('\n'); + } + } + + return sb.ToString(); + } + } } \ No newline at end of file diff --git a/fs24bot3/build-linux-shared.ps1 b/fs24bot3/build-linux-shared.ps1 index 27ca8a9..bfbc214 100644 --- a/fs24bot3/build-linux-shared.ps1 +++ b/fs24bot3/build-linux-shared.ps1 @@ -1,12 +1,12 @@ -Remove-Item -Recurse -Force ./releases -Remove-Item -Recurse -Force ./bin/Release - -New-Item -ItemType Directory -Path ./releases -New-Item -ItemType Directory -Path ./releases\linux-x64-shared - -dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained false - -Copy-Item -Recurse -Path .\bin\Release\net6.0\linux-x64\publish\* -Destination .\releases\linux-x64-shared -Compress-Archive -Path .\releases\linux-x64-shared -DestinationPath releases\linux-x64-shared.zip -Compress-Archive -Path .\releases\linux-x64-shared\fs24bot3 -DestinationPath releases\fs24bot3.zip +Remove-Item -Recurse -Force ./releases +Remove-Item -Recurse -Force ./bin/Release + +New-Item -ItemType Directory -Path ./releases +New-Item -ItemType Directory -Path ./releases\linux-x64-shared + +dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained false + +Copy-Item -Recurse -Path .\bin\Release\net6.0\linux-x64\publish\* -Destination .\releases\linux-x64-shared +Compress-Archive -Path .\releases\linux-x64-shared -DestinationPath releases\linux-x64-shared.zip +Compress-Archive -Path .\releases\linux-x64-shared\fs24bot3 -DestinationPath releases\fs24bot3.zip Read-Host -Prompt "Press Enter to continue" \ No newline at end of file diff --git a/fs24bot3/build-linux.bash b/fs24bot3/build-linux.bash index fc24042..489b979 100644 --- a/fs24bot3/build-linux.bash +++ b/fs24bot3/build-linux.bash @@ -1,11 +1,11 @@ -#/usr/bin/bash - -# This is script for CI usage only -rm -rf releases/ -rm -rf bin/x64/Release - -mkdir releases/ -mkdir releases/linux-x64-shared - -dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained false +#/usr/bin/bash + +# This is script for CI usage only +rm -rf releases/ +rm -rf bin/x64/Release + +mkdir releases/ +mkdir releases/linux-x64-shared + +dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained false cp -r ./fs24bot3/bin/Release/net6.0/linux-x64/publish/* releases/linux-x64-shared/ \ No newline at end of file