Skip to content

Commit

Permalink
Merge pull request #24 from Assaro/dev
Browse files Browse the repository at this point in the history
Feature Update 1.0.0
  • Loading branch information
Assaro authored Apr 1, 2023
2 parents 3945185 + 4895be2 commit 3471e83
Show file tree
Hide file tree
Showing 22 changed files with 1,179 additions and 98 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<h1 align="center">DD_Bot</h1>

<p align="center">A Discord-Bot to start and stop Docker Containers, using the Docker Socket</p>

<p align="center">
<a href="https://hub.docker.com/r/assaro/ddbot"><img alt="Docker Image Size (tag)" src="https://img.shields.io/docker/image-size/assaro/ddbot/latest?style=for-the-badge">
<img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/assaro/ddbot?style=for-the-badge"></a>
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/assaro/DD_Bot?color=brightgreen&style=for-the-badge">
<img alt="GitHub" src="https://img.shields.io/github/license/assaro/dd_bot?style=for-the-badge"></p>

`"Conveniently, the program itself can be used as a Docker Container"` - ***Gadget Gabe***
`"Conveniently, the program itself can be used as a Docker Container"` - ***Gadget Gabe*** \
**NEW: Now with commands to adjust permissions**

## Screenshots

Expand All @@ -20,6 +20,7 @@
## Features

- Remotely start and stop Docker Containers using Discord Slash Commands
- Easily grant Users and Groups on your Discord access to selected containers
- Enable Friends to start specified Containers, e.g. Gameservers
- Save Energy when noone is playing
- DD_Bot is designed to work on the same machine in its own Container
Expand All @@ -36,6 +37,8 @@

## [Settings](/sites/settings.md)

## [Commands](/sites/commands.md)

## [FAQ/Troubleshooting](/sites/faq.md)

## To-Do List
Expand All @@ -46,9 +49,9 @@
- [ ] Commands to grant and revoke privileges to users and groups
- [ ] Fully customizable messages for Discord
- [ ] More statistics
- [ ] \(Maybe) Auto-Shutdown for certain containers
- [ ] \(Maybe) more command options
- [ ] \(Maybe) implement RCON to control gameservers
- [ ] \(Maybe\) Auto-Shutdown for certain containers
- [ ] \(Maybe\) more command options
- [ ] \(Maybe\) implement RCON to control gameservers


### If you like my work, feel free to buy me a coffee
Expand Down
Binary file modified pics/Settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions sites/commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# **Command Overview**

### /admin
- choose a user to grant or revoke admin privilieges to
- Can only be done by admins
- An admin can not revoke his own admin privileges

### /docker
- used to start, stop or restart a docker container
- admins are allowed to control every container
- users can only start and stop containers that have been assigned to them by admins
- start and stop permissions are granted separately
- permissions can be done per user and for roles

### /list
- this command lists all containers the user is allowed to interact with
- includes the status (running or stopped)
- admins see every container

### /permission
- lists a users permissions
- admins can enter a user or role for permissions to be shown

### /role
- used to grant/revoke permissions to a role

### /role
- used to grant/ revoke permissions to a single user
18 changes: 11 additions & 7 deletions sites/faq.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
<h1 align="center">FAQ</h1>
<p align="center">If you are here, I probably did something wrong</p>

## I updated the Bot and my commands are not working anymore
- The 1.0.0 update introduced a new permission system
- Either revert back to version 0.1.0 or adapt to the new system
- Info about the new settings has been added to the [settings readme](sites/../settings.md)

## I just installed your Bot but i do not have admin rights
-You need to add your Discord ID to the settings.json. For more info about settings click [here](sites/../settings.md)

## The Bot does not go online in Discord

- Token is not valid
- Check if you entered your token correctly in the settings.json
- Restart the Container for Changes to take effect
- If that did not work, regenerate the Token on Discord's Developer Portal

## The Container crashes

- Check if the Container generated a settings.json
- If it exists, check your settings
- If it doesn't exist, make sure that you have a folder pointing to /app/settings
- Check if /var/run/docker.sock exists on your machine. Eventually adjust path to docker.sock if it has been relocated

## I updated to a newer image and now it crashes
- I probably added new settings.
- Back up your settings.json and let the Container generate a new one
- This will be changed at some point, sorry for the Inconvenience
- Check if `/var/run/docker.sock` exists on your machine. Adjust path to `docker.sock`

## I get ``` Unhandled exception. Discord.Net.HttpException: The server responded with error 50035: Invalid Form Body ``` when using the /list command
- Too many characters in your list. Lower the `ContainersPerMessage` setting value until it works again

## How can i contact you
## How can i contact you?
- [Github Issue](https://github.com/Assaro/DD_Bot/issues/new)
- [Discord](https://discord.com/users/341195755677286401) (Assaro Delamar#5823)
9 changes: 6 additions & 3 deletions sites/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
4. Start image using `docker run -d --name='DD_Bot' -v 'path/to/settings':'/app/settings/':'rw' -v /var/run/docker.sock:/var/run/docker.sock 'assaro/ddbot:latest' `
- For Unraid, please refer to [this Screenshot](/pics/Unraidsettings.PNG)
5. The Container will generate a settings file in your set directory
6. Stop the Container, input your settings and then start it again. [Click for info about settings](/sites/settings.md)
6. Stop the Container, input your Discord Token + Discord Id and then start it again. [Click for info about settings](/sites/settings.md)
- Everything but the Discord Token can be changed while the container is running
7. You should be good to go, if not, see [discordbot](/sites/discordbot.md), [settings](/sites/settings.md) or [faq](/sites/faq.md)
8. If something is still not working, feel free to dm me or open an issue
- Everything but the Discord Token can now be changed with a command
7. You should be good to go, if not, see [discordbot](/sites/discordbot.md), [settings](/sites/settings.md) or [faq](/sites/faq.md)
8. Infrormation about commands can be found [here](/sites/commands.md)
9. If something is still not working, feel free to dm me or open an issue
10. For information about the commands, click [here](/sites/commands.md)
19 changes: 13 additions & 6 deletions sites/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@
- Token: Your Discord Bot-Token
- AdminIDs: A list of UserIDs that are allowed to control all Dockers
- [how to find your ID](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-)
- UserWhitelist: If enabled, only users specified in UserIDs have control over AllowedContainers. Defaults to true
- UserIDs: List of Users allowed to control Containers specified in AllowedContainers. Only active if UserWhitelist is set to true
- [how to find your ID](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-)
- UsersCanStopContainers: If set to true, every user can stop and restart AllowedContainers. Whitelist still applies
- AllowedContainers: List of Containers that will be listed and controllable for normal Users. **Case-Sensitive!!** Whitelist still applies
- DockerSettings
- BotName: The Name you gave this Container. Prevents shutting down itself
- Retries: The Amount of checks that should be performed before a command is considered failed
- TimeBeforeRetry: The Time between two checks in seconds
- ContainersPerMessage: Splits the list into multiple messages if more containers are found. Lower it to prevent Error 50035
- ContainersPerMessage: Splits the list into multiple messages if more containers are found. Lower it to prevent Error 50035
<p>
<b>All Settings not Listed here are managed with Commands. Do not Change!!
For Info about setting Permissions, see <a href="/sites/commands.md">commands</a>
</b>
</p>

## **Deprecated Settings**
- UserWhitelist: If enabled, only users specified in UserIDs have control over AllowedContainers. Defaults to true
- UserIDs: List of Users allowed to control Containers specified in AllowedContainers. Only active if UserWhitelist is set to true
- [how to find your ID](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-)
- UsersCanStopContainers: If set to true, every user can stop and restart AllowedContainers. Whitelist still applies
- AllowedContainers: List of Containers that will be listed and controllable for normal Users. **Case-Sensitive!!** Whitelist still applies
127 changes: 127 additions & 0 deletions src/DD_Bot.Application/Commands/AdminCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* DD_Bot - A Discord Bot to control Docker containers*/

/* Copyright (C) 2022 Maxim Kovac
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

using System;
using Discord;
using Discord.WebSocket;
using DD_Bot.Application.Services;
using System.Linq;
using DD_Bot.Domain;

namespace DD_Bot.Application.Commands
{
public class AdminCommand
{
private DiscordSocketClient _discord;

public AdminCommand(DiscordSocketClient discord)
{
_discord = discord;
}

#region CreateCommand

public static ApplicationCommandProperties Create()
{
var builder = new SlashCommandBuilder()
{
Name = "admin",
Description = "Grant or Revoke Admin Privileges"
};

builder.AddOption("user",
ApplicationCommandOptionType.User,
"choose a user",
isRequired: true
);

builder.AddOption("choice",
ApplicationCommandOptionType.String,
"choose grant or revoke",
true,
choices: new[]
{
new ApplicationCommandOptionChoiceProperties()
{
Name = "grant",
Value = "grant",
},
new ApplicationCommandOptionChoiceProperties()
{
Name = "revoke",
Value = "revoke",
}
});

return builder.Build();
}

#endregion

#region ExecuteCommand

public static async void Execute(SocketSlashCommand arg, Settings settings, SettingsService settingsService)
{
await arg.RespondAsync("Contacting Settings Service...");
DiscordSettings discordSettings = settings.DiscordSettings;
if (!discordSettings.AdminIDs.Contains(arg.User.Id))
{
await arg.ModifyOriginalResponseAsync(edit => edit.Content = "You are not an Admin!");
}
else
{
var choice = arg.Data.Options.FirstOrDefault(option => option.Name == "choice")?.Value as string;
var user = arg.Data.Options.FirstOrDefault(option => option.Name == "user")?.Value as SocketGuildUser;
switch (choice)
{
case "grant":
Console.WriteLine("grant");
if (discordSettings.AdminIDs.Contains(user.Id))
{
await arg.ModifyOriginalResponseAsync(edit => edit.Content = user.Username + " is already an admin!");
}
else
{
settings.DiscordSettings.AdminIDs.Add(user.Id);
settingsService.WriteSettings(settings);
await arg.ModifyOriginalResponseAsync(edit => edit.Content = "Made " + user.Username + " an admin!");
}
break;
case "revoke":
if (user.Id == arg.User.Id)
{
await arg.ModifyOriginalResponseAsync(edit => edit.Content = "You are not allowed to revoke your own admin privileges!");
}else if (!discordSettings.AdminIDs.Contains(user.Id))
{
await arg.ModifyOriginalResponseAsync(edit => edit.Content = "User is not an admin!");
}
else
{
settings.DiscordSettings.AdminIDs.Remove(user.Id);
settingsService.WriteSettings(settings);
await arg.ModifyOriginalResponseAsync(edit => edit.Content = user.Username + "'s admin privileges have been removed!");
}
break;
}
}
}

#endregion
}
}
61 changes: 50 additions & 11 deletions src/DD_Bot.Application/Commands/DockerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,28 +87,67 @@ public static async void Execute(SocketSlashCommand arg, DockerService dockerSer
await dockerService.DockerUpdate();

var command = arg.Data.Options.FirstOrDefault(option => option.Name == "command")?.Value as string;

var dockerName = arg.Data.Options.FirstOrDefault(option => option.Name == "dockername")?.Value as string;

#region authCheck

bool authorized = true;

if (!settings.AdminIDs.Contains(arg.User.Id)) //Auth Checks
{
if (settings.UserWhitelist && !settings.UserIDs.Contains(arg.User.Id))
{
await arg.ModifyOriginalResponseAsync(edit => edit.Content = "You are not allowed to control this docker");
return;
}
authorized = false;
var socketUser = arg.User as SocketGuildUser;
var guild = socketUser.Guild;
var socketGuildUser = guild.GetUser(socketUser.Id);
var userRoles = socketGuildUser.Roles;

if (!settings.AllowedContainers.Contains(dockerName))
switch (command)
{
await arg.ModifyOriginalResponseAsync(edit => edit.Content = "You are not allowed to control this docker");
return;
case "start":
if (settings.UserStartPermissions.ContainsKey(arg.User.Id))
{
if (settings.UserStartPermissions[arg.User.Id].Contains(dockerName))
{
authorized = true;
}
}
foreach (var role in userRoles)
{
if (settings.RoleStartPermissions.ContainsKey(role.Id))
{
if (settings.RoleStartPermissions[role.Id].Contains(dockerName))
{
authorized = true;
}
}
}
break;
case "stop":
case "restart":
if (settings.UserStopPermissions.ContainsKey(arg.User.Id))
{
if (settings.UserStopPermissions[arg.User.Id].Contains(dockerName))
{
authorized = true;
}
}
foreach (var role in userRoles)
{
if (settings.RoleStopPermissions.ContainsKey(role.Id))
{
if (settings.RoleStopPermissions[role.Id].Contains(dockerName))
{
authorized = true;
}
}
}
break;
}

if (!settings.UsersCanStopContainers && (command == "stop"|| command == "restart"))
if (!authorized)
{
await arg.ModifyOriginalResponseAsync(edit => edit.Content = "You are not allowed to stop or restart this docker");
await arg.ModifyOriginalResponseAsync(edit =>
edit.Content = "You are not allowed to use this command");
return;
}
}
Expand Down
Loading

0 comments on commit 3471e83

Please sign in to comment.