Пример #1
0
        /// <summary>
        /// Called when mod is loaded
        /// </summary>
        public override void OnModLoad()
        {
            GlobalLogger = string.IsNullOrEmpty(TestVersion) ? new Logger(DiscordLogLevel.Warning) : new Logger(DiscordLogLevel.Debug);

            GlobalLogger.Info($"Using Discord Extension Version: {GetExtensionVersion}");
            AppDomain.CurrentDomain.UnhandledException += (sender, exception) =>
            {
                GlobalLogger.Exception("An exception was thrown!", exception.ExceptionObject as Exception);
            };

            string configPath = Path.Combine(Interface.Oxide.InstanceDirectory, "discord.config.json");

            if (!File.Exists(configPath))
            {
                DiscordConfig = new DiscordConfig(configPath);
                DiscordConfig.Save();
            }

            DiscordConfig = ConfigFile.Load <DiscordConfig>(configPath);
            DiscordConfig.Save();

            DiscordLink          = new DiscordLink(GlobalLogger);
            DiscordCommand       = new DiscordCommand(DiscordConfig.Commands.CommandPrefixes);
            DiscordSubscriptions = new DiscordSubscriptions(GlobalLogger);

            Manager.RegisterLibrary(nameof(DiscordLink), DiscordLink);
            Manager.RegisterLibrary(nameof(DiscordCommand), DiscordCommand);
            Manager.RegisterLibrary(nameof(DiscordSubscriptions), DiscordSubscriptions);
            Interface.Oxide.RootPluginManager.OnPluginAdded   += DiscordClient.OnPluginAdded;
            Interface.Oxide.RootPluginManager.OnPluginRemoved += DiscordClient.OnPluginRemoved;
        }
Пример #2
0
    public static Task Main(string[] args)
    {
        var services = new ServiceCollection();

        services.AddLogging((builder) =>
        {
            builder.AddSimpleConsole(console =>
            {
                console.SingleLine = true;
            });
        });
        services.AddSingleton(_credentials);
        services.AddSingleton <ArmDeployment>();
        services.AddHttpClient <DiscordClient>();
        services.AddSingleton <ILookupClient, LookupClient>();
        services.AddSingleton <AcmeCertificateGenerator>();
        services.AddSingleton((sp) =>
        {
            var options = new JsonSerializerOptions();
            options.Converters.Add(new JsonStringEnumConverter());
            return(JsonSerializer.Deserialize <Dictionary <string, ApplicationCommand> >(
                       File.ReadAllText("commands.json"), options) !);
        });
        var serviceProvider = services.BuildServiceProvider();

        var root = new RootCommand("Deployment utilities for AzureBot")
        {
            InfraCommand.GetCommand(serviceProvider),
            DiscordCommand.GetCommand(serviceProvider),
        };

        return(root.InvokeAsync(args));
    }
Пример #3
0
        private static async Task ProcessMessage(DiscordMessage message, DiscordUser author, DiscordChannel channel)
        {
            DateTimeOffset startTime = DateTimeOffset.Now;

            if (!string.IsNullOrWhiteSpace(message?.Content) && !author.IsBot && !author.IsCurrent && !ProcessedMessageIds.Contains(message.Id))
            {
                if (message.Content.ToLower().StartsWith(Config.Prefix.ToLower()))
                {
                    _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] Found command prefix, parsing...");
                    IEnumerable <string> commandSegments = Strings.SplitCommandLine(message.Content.Substring(Config.Prefix.Length));

                    foreach (IParseExtension extenstion in ParseExtensions)
                    {
                        commandSegments = extenstion.Parse(commandSegments, channel);
                    }

                    if (commandSegments.Any())
                    {
                        string commandAlias = commandSegments.First().ToLower();
                        IEnumerable <DiscordCommand> foundCommands = Commands.Where(c => c.Aliases.Any(a => a.ToLower() == commandAlias));
                        DiscordCommand commandToRun = foundCommands.FirstOrDefault();
                        if (foundCommands.Count() == 1)
                        {
                            await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(1), commandAlias, commandToRun, startTime);
                        }
                        else if (commandSegments.Count() >= 2)
                        {
                            foundCommands = AssemblyCommands.FirstOrDefault(c => c.Key.Name.ToLowerInvariant() == commandAlias)
                                            .Value?.Where(c => c.Aliases.Contains(commandSegments.ElementAt(1).ToLower()));

                            if (foundCommands != null && foundCommands.Count() == 1)
                            {
                                await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(2), commandAlias, foundCommands.First(), startTime);
                            }
                            else
                            {
                                if (commandToRun != null)
                                {
                                    await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(1), commandAlias, foundCommands.First(), startTime);
                                }
                                else
                                {
                                    _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] Unable to find command with alias \"{commandAlias}\".");
                                    await SendTemporaryMessage(message, author, channel, $"```\r\n{commandAlias}: command not found!\r\n```");

                                    TelemetryClient?.TrackRequest(GetRequestTelemetry(author, channel, null, startTime, "404", false));
                                }
                            }
                        }
                        else if (commandToRun != null)
                        {
                            await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(1), commandAlias, foundCommands.First(), startTime);
                        }
                    }
                }
            }
        }
Пример #4
0
 public InvalidParameterEventArgs(DiscordCommand command, ParameterAttribute param, string input) : base(command, param)
 {
     InputtedParameter = input;
 }
Пример #5
0
        private static void ManageException(DiscordMessage message, DiscordUser author, DiscordChannel channel, Exception ex, DiscordCommand command)
        {
            _appLogArea.WriteLine($"\n --- Something's f****d up! --- \n{ex.ToString()}\n");
            TelemetryClient?.TrackException(ex, new Dictionary <string, string> {
                { "command", command.GetType().Name }
            });

            if (!(ex is TaskCanceledException) && !(ex is OperationCanceledException))
            {
                if (_ownerDm != null)
                {
                    try
                    {
                        _ownerDm.SendMessageAsync($"An {ex.GetType().Name} has occured processing command \"{command.Name}\" in {channel.Mention}{(channel.Guild != null ? $" ({channel.Guild.Name})" : "")}");
                        _ownerDm.SendMessageAsync($"```\r\n" +
                                                  $"{ex.ToString()}" +
                                                  $"```");
                        _ownerDm.SendMessageAsync($"Message content: `{message.Content}`");
                        _ownerDm.SendMessageAsync($"Message author:  {author.Mention}");
                    }
                    catch { }
                }

                new Task(async() =>
                {
                    try
                    {
                        DiscordMessage msg = await channel.SendMessageAsync(
                            $"Something's gone very wrong executing that command, and an {ex.GetType().Name} occured." +
                            $"{(_ownerDm != null ? "\r\nThis error has been reported, and should be fixed soon:tm:!" : "")}" +
                            $"\r\nThis message will be deleted in 10 seconds.");

                        await Task.Delay(10_000);
                        await msg.DeleteAsync();
                    }
                    catch { }
                }).Start();
            }
        }
Пример #6
0
        private static async Task RunCommandAsync(DiscordMessage message, DiscordUser author, DiscordChannel channel, IEnumerable <string> commandSegments, string commandAlias, DiscordCommand command, DateTimeOffset start)
        {
            bool success = true;

            try
            {
                using (WamBotContext dbContext = new WamBotContext())
                {
                    await channel.TriggerTypingAsync();

                    command = InstantateDiscordCommand(command.GetType());
                    HappinessData.TryGetValue(author.Id, out sbyte h);

                    CommandContext context = new CommandContext(commandSegments.ToArray(), message, Client)
                    {
                        Happiness = h,
                        _logger   = _loggerFactory.CreateLogger("Commands"),
                        UserData  = await dbContext.Users.FindOrCreateAsync(author.Id, () => new UserData(author))
                    };
                    CommandResult result = await command.RunCommand(commandSegments.ToArray(), context);

                    _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] \"{command.Name}\" returned ReturnType.{result.ReturnType}.");
                    if (result.ReturnType != ReturnType.None)
                    {
                        if (result.ReturnType == ReturnType.Text && result.ResultText.Length > 2000)
                        {
                            for (int i = 0; i < result.ResultText.Length; i += 1993)
                            {
                                string str = result.ResultText.Substring(i, Math.Min(1993, result.ResultText.Length - i));
                                if (result.ResultText.StartsWith("```") && !str.StartsWith("```"))
                                {
                                    str = "```" + str;
                                }
                                if (result.ResultText.EndsWith("```") && !str.EndsWith("```"))
                                {
                                    str = str + "```";
                                }

                                _appLogArea.WriteLine($"Chunking message to {str.Length} chars");
                                await channel.SendMessageAsync(str);

                                await Task.Delay(2000);
                            }
                        }
                        else
                        {
                            if (!string.IsNullOrWhiteSpace(result.Attachment))
                            {
                                await channel.SendFileAsync(result.Attachment, result.ResultText, embed : result.ResultEmbed);
                            }
                            else if (result.Stream != null || result.ReturnType == ReturnType.File)
                            {
                                if (result.Stream.Length <= 8 * 1024 * 1024)
                                {
                                    await channel.SendFileAsync(result.Stream, result.FileName, result.ResultText, false, result.ResultEmbed);
                                }
                                else
                                {
                                    await channel.SendMessageAsync("This command has resulted in an attachment that is over 8MB in size and cannot be sent.");
                                }
                            }
                            else
                            {
                                await channel.SendMessageAsync(result.ResultText, embed : result.ResultEmbed);
                            }
                        }
                    }


                    RequestTelemetry request = GetRequestTelemetry(author, channel, command, start, success ? "200" : "500", success);
                    foreach (var pair in result.InsightsData)
                    {
                        request.Properties.Add(pair);
                    }

                    TelemetryClient?.TrackRequest(request);

                    HappinessData[author.Id] = (sbyte)((int)(context.Happiness).Clamp(sbyte.MinValue, sbyte.MaxValue));
                }
            }
            catch (BadArgumentsException)
            {
                await HandleBadRequest(message, author, channel, commandSegments, commandAlias, command, start);
            }
            catch (CommandException ex)
            {
                await channel.SendMessageAsync(ex.Message);

                TelemetryClient?.TrackRequest(GetRequestTelemetry(author, channel, command, start, "400", false));
            }
            catch (ArgumentOutOfRangeException)
            {
                await channel.SendMessageAsync("Hey there! That's gonna cause some issues, no thanks!!");

                TelemetryClient?.TrackRequest(GetRequestTelemetry(author, channel, command, start, "400", false));
            }
            catch (Exception ex)
            {
                success = false;
                ManageException(message, author, channel, ex, command);

                sbyte h = 0;
                HappinessData?.TryGetValue(author.Id, out h);

                HappinessData[author.Id] = (sbyte)((int)h - 1).Clamp(sbyte.MinValue, sbyte.MaxValue);
            }
            finally
            {
                if (command is IDisposable disp)
                {
                    disp.Dispose();
                }
            }
        }
Пример #7
0
        private static async Task HandleBadRequest(DiscordMessage message, DiscordUser author, DiscordChannel channel, IEnumerable <string> commandSegments, string commandAlias, DiscordCommand command, DateTimeOffset start)
        {
            _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] {command.Name} does not take {commandSegments.Count()} arguments.");
            TelemetryClient?.TrackRequest(GetRequestTelemetry(author, channel, command, start, "400", false));

            if (command.Usage != null)
            {
                await SendTemporaryMessage(message, author, channel, $"```\r\n{commandAlias} usage: {Config.Prefix}{commandAlias} [{command.Usage}]\r\n```");
            }
        }
Пример #8
0
        private static async Task ExecuteCommandAsync(DiscordMessage message, DiscordUser author, DiscordChannel channel, IEnumerable <string> commandSegments, string commandAlias, DiscordCommand command, DateTimeOffset start)
        {
            _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] Found {command.Name} command!");
            ProcessedMessageIds.Add(message.Id);
            if (command.ArgumentCountPrecidate(commandSegments.Count()))
            {
                if (CheckPermissions(channel.Guild?.CurrentMember ?? Client.CurrentUser, channel, command))
                {
                    if (CheckPermissions(author, channel, command))
                    {
                        _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] Running command \"{command.Name}\" asynchronously.");
                        new Task(async() => await RunCommandAsync(message, author, channel, commandSegments, commandAlias, command, start)).Start();
                    }
                    else
                    {
                        _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] Attempt to run command without correct user permissions.");
                        await SendTemporaryMessage(message, author, channel, $"Oi! You're not alowed to run that command! F**k off!");

                        TelemetryClient?.TrackRequest(GetRequestTelemetry(author, channel, command, start, "401", false));
                    }
                }
                else
                {
                    _appLogArea.WriteLine($"[{message.Channel.Guild.Name ?? message.Channel.Name}] Attempt to run command without correct bot permissions.");
                    await SendTemporaryMessage(message, author, channel, $"Sorry! I don't have permission to run that command in this server! Contact an admin/mod for more info.");

                    TelemetryClient?.TrackRequest(GetRequestTelemetry(author, channel, command, start, "403", false));
                }
            }
            else
            {
                await HandleBadRequest(message, author, channel, commandSegments, commandAlias, command, start);
            }
        }
Пример #9
0
        internal static async Task LoadPluginsAsync()
        {
            _appLogArea.WriteLine("");
            List <string> dlls = Directory.EnumerateFiles("Plugins").Where(f => Path.GetExtension(f) == ".dll").ToList();

            dlls.Insert(0, Assembly.GetExecutingAssembly().Location);
            foreach (string str in Config.AdditionalPluginDirectories)
            {
                dlls.AddRange(Directory.EnumerateFiles(str).Where(f => Path.GetExtension(f) == ".dll"));
            }

            _appLogArea.WriteLine($"{(Commands.Any() ? "Reloading" : "Loading")} {dlls.Count()} plugins...");

            Commands.Clear();
            AssemblyCommands.Clear();
            ParseExtensions.Clear();

            foreach (string dllPath in dlls)
            {
                try
                {
                    Assembly assembly = Assembly.LoadFrom(dllPath);
                    if (assembly != null && assembly.DefinedTypes.Any(t => t.GetInterfaces()?.Contains(typeof(ICommandsAssembly)) == true))
                    {
                        Debug.WriteLine(dllPath);
                        _appLogArea.WriteLine($"Searching {Path.GetFileName(dllPath)} for commands.");
                        ICommandsAssembly     asm         = null;
                        List <DiscordCommand> asmCommands = new List <DiscordCommand>();
                        foreach (Type type in assembly.GetTypes())
                        {
                            if (type.GetInterfaces().Contains(typeof(ICommandsAssembly)))
                            {
                                asm = (ICommandsAssembly)Activator.CreateInstance(type);
                            }

                            if (type.GetInterfaces().Contains(typeof(IParseExtension)))
                            {
                                ParseExtensions.Add((IParseExtension)Activator.CreateInstance(type));
                            }

                            if (type.GetInterfaces().Contains(typeof(IParamConverter)))
                            {
                                Tools.RegisterPatameterParseExtension((IParamConverter)Activator.CreateInstance(type));
                            }

                            if (type.IsSubclassOf(typeof(DiscordCommand)) && !type.IsAbstract)
                            {
                                DiscordCommand command = InstantateDiscordCommand(type);

                                if (command != null)
                                {
                                    asmCommands.Add(command);
                                }
                            }
                        }

                        if (asm == null)
                        {
                            _appLogArea.WriteLine($"Loaded {asmCommands.Count()} commands from {Path.GetFileName(dllPath)} without command assembly manifest. Categorised help will be unavailable for these commands.");
                            _appLogArea.WriteLine("Consider adding an \"ICommandAssembly\" class as soon as possible.");
                        }
                        else
                        {
                            if (asm is IBotStartup s)
                            {
                                await s.Startup(Client);
                            }

                            _appLogArea.WriteLine($"Loaded {asmCommands.Count()} plugins from {Path.GetFileName(dllPath)}!");
                        }

                        Commands.AddRange(asmCommands);
                        if (asm != null)
                        {
                            AssemblyCommands.Add(asm, asmCommands);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _appLogArea.WriteLine($"An {ex.GetType().Name} occured while loading from {Path.GetFileName(dllPath)}\n{ex.Message}");
                }
            }

            _appLogArea.WriteLine("");
            _appLogArea.WriteLine($"Plugins loaded!");
            _appLogArea.WriteLine($"{Commands.Count} commands available: {string.Join(", ", Commands.Select(c => c.Name))}");
            _appLogArea.WriteLine($"{ParseExtensions.Count} parse extensions available: {string.Join(", ", ParseExtensions.Select(c => c.Name))}");
            _appLogArea.WriteLine("");
        }
Пример #10
0
        static void Main(string[] args)
        {
            DiscordClient client = new DiscordClient("token", true, true);

            client.EnableVerboseLogging = true;
            client.GetTextClientLogger.EnableLogging       = true;
            client.GetTextClientLogger.LogMessageReceived += (sender, e) => Console.WriteLine($"{e.message.TimeStamp} -- {e.message.Message}");

            Console.WriteLine("Attempting to connect!");
            client.CommandPrefixes.Add("testbot.");
            client.AddCommand(DiscordCommand.Create("create")
                              .AddParameter("name")
                              .Do(e =>
            {
                Hook.Webhook hook    = e.Channel.CreateWebhook(e.args[0]);
                SlackMessage message = new SlackMessage();
                message.Add(new SlackText("text", "List of Webhooks"));

                SlackContainer attachment = new SlackContainer();
                attachment.Add(new SlackText("color", "#36a64f"));
                attachment.Add(new SlackText("pretext", hook.Token));
                attachment.Add(new SlackText("author_name", $"{hook.Name} [{hook.ID}]"));
                attachment.Add(new SlackText("author_icon", hook.User.GetAvatarURL().ToString()));
                attachment.Add(new SlackText("title", hook.Name));
                attachment.Add(new SlackText("text", hook.Token));
                attachment.Add(new SlackText("image_url", hook.Avatar));

                message.Add(new SlackContainerList("attachments", new List <SlackContainer>()
                {
                    attachment
                }));

                hook.SendSlack(message.ToJObject());
            }
                                  ));

            client.AddCommand(DiscordCommand.Create("list")
                              .Do(e =>
            {
                Hook.Webhook fHook = null;

                SlackMessage message = new SlackMessage();
                message.Add(new SlackText("text", $"New {Formatter.Bold(Formatter.Bold("webhook"))} {Formatter.InlineCode("created")}"));
                List <SlackContainer> attachments = new List <SlackContainer>();
                foreach (Hook.Webhook hook in e.Channel.GetWebhooks())
                {
                    if (fHook == null)
                    {
                        fHook = hook;
                    }

                    SlackContainer attachment = new SlackContainer();
                    attachment.Add(new SlackText("color", "#36a64f"));
                    attachment.Add(new SlackText("pretext", hook.Token));
                    attachment.Add(new SlackText("author_name", $"{hook.Name} [{hook.ID}]"));
                    attachment.Add(new SlackText("author_icon", hook.User.GetAvatarURL().ToString()));
                    attachment.Add(new SlackText("title", hook.Name));
                    attachment.Add(new SlackText("text", hook.Token));
                    attachment.Add(new SlackText("image_url", hook.Avatar));

                    attachments.Add(attachment);
                }
                message.Add(new SlackContainerList("attachments", attachments));
                fHook.SendSlack(message.ToJObject(), false);
            }
                                  ));
            client.AddCommand(DiscordCommand.Create("removeall")
                              .Do(e =>
            {
                foreach (Hook.Webhook hook in e.Channel.GetWebhooks())
                {
                    hook.Delete();
                }
            }
                                  ));

            try
            {
                client.SendLoginRequest();
                client.Connect();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            client.Connected += (sender, e) =>
            {
                Console.WriteLine("CLIENT CONNECTED");
            };
            client.MessageReceived += (sender, e) =>                                    // Channel message has been received
            {
                if (e.MessageText == "tiaqoy0 is the most awesome person in the world") // fixed* -> love you afro <3
                {
                    e.Channel.SendMessage(e.MessageText);
                }
            };

            Console.ReadLine();
            Environment.Exit(0);
        }