Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.0.0 #41

Merged
merged 65 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
b851f3c
fix(cmds/order) SourceChannel was using the wrong ID.
refractored Nov 23, 2023
d0cc128
feat(models/orders) Added AcceptedAt to the order struct.
refractored Nov 23, 2023
e3b9e11
Merge remote-tracking branch 'origin/dev' into 8-finish-up-ordering-s…
refractored Nov 23, 2023
f2a4b9e
Merge remote-tracking branch 'origin/master' into 8-finish-up-orderin…
refractored Nov 23, 2023
6f41ea4
feat(cmds/order): Orders will now be announced in the kitchen channel…
refractored Nov 23, 2023
23bda69
fix(models/order): properly setup softdelete
Baconing Nov 23, 2023
c3a0acd
feat(config): implement more config variables and add config verifica…
Baconing Nov 23, 2023
29123de
docs(readme): update README.md with config reference, build info, etc
Baconing Nov 23, 2023
16629fc
docs(config): update config.json.example to be up to date with curren…
Baconing Nov 23, 2023
b20dcf0
fix(config/database): allow database variables to be empty if databas…
Baconing Nov 23, 2023
e3ec104
fix(config): Missing quote
refractored Nov 23, 2023
d663ac6
docs(readme/config): fix config reference description for `tokensPerO…
Baconing Nov 24, 2023
00f745c
Merge pull request #28 from refractored/19-configify
Baconing Nov 24, 2023
4c70725
fix(cmds/setpermissionlevel): Command parameters are no longer optional
refractored Nov 24, 2023
8d323c9
Merge remote-tracking branch 'origin/dev' into 8-finish-up-ordering-s…
refractored Nov 24, 2023
0952cc3
fix(cmds/order): update config.go for upcoming changes
refractored Nov 24, 2023
2d03a2e
Merge pull request #29 from refractored/permission-level-patch-refrac
Baconing Nov 24, 2023
79c14b2
Merge branch 'dev' into 8-finish-up-ordering-system-refrac
Baconing Nov 24, 2023
5207a70
style(cmds/order): removed one-use variables
refractored Nov 24, 2023
5551a8f
feat(cmds/order): added order accepting
refractored Nov 24, 2023
6fad9c1
docs: update docs with new config information
refractored Nov 24, 2023
0853f5f
Merge remote-tracking branch 'origin/8-finish-up-ordering-system-refr…
refractored Nov 24, 2023
52c8e1f
feat(orders): added Order Status to database
refractored Nov 24, 2023
ae839c6
feat(orders): added more order statuses
refractored Nov 24, 2023
8fb50b5
feat(orders): bot will attempt to message user if order has failed
refractored Nov 24, 2023
88ee6a1
fix(cmds/acceptorder): small bug fixes
refractored Nov 25, 2023
61aabf8
fix(main): Fixed incorrect counting
refractored Nov 25, 2023
ef4228a
feat(cmds/prepare): artists can now get the server invite and deliver…
refractored Nov 25, 2023
5727675
feat(cmds/prepare): error handling if the bot cant make a invite
refractored Nov 25, 2023
93b9d73
feat(order): finish order system
refractored Nov 26, 2023
ea09ebc
feat(cmds/tip): Add a optional ID
refractored Nov 28, 2023
ebab14f
feat(cmds/prepare): Make invite temporary
refractored Nov 28, 2023
c8b34f8
chore(prepare): Remove TODO
refractored Nov 28, 2023
9bd4f26
fix(cmds/cancelorder) cancel order no longer deletes the order.
refractored Nov 28, 2023
e1ddab9
style(cmds/acceptorder): update cmd description
refractored Nov 28, 2023
bdd9bbd
style(cmds/deliver): fix grammar errors
refractored Nov 28, 2023
42e38df
style(cmds/prepare): update description
refractored Nov 28, 2023
6331ad2
style(cmds/prepare): fix grammar errors
refractored Nov 28, 2023
3ff7cc7
fix(cmds/purgecmds): command should only be registered inside of serv…
refractored Nov 28, 2023
948cd4b
style(cmds/tipped): fix grammar errors
refractored Nov 28, 2023
d65e486
style(cmds/tipped): fix newline
refractored Nov 28, 2023
b3e8f93
Merge pull request #30 from refractored/8-finish-up-ordering-system-r…
refractored Nov 28, 2023
f348c90
Merge remote-tracking branch 'origin/master' into dev
refractored Nov 29, 2023
8eb54c8
feat(cmds/usermanage): Create command with basic code
refractored Nov 29, 2023
c4039e7
feat(cmds/usermanage): Reset Daily
refractored Nov 29, 2023
ac8f6f5
feat(prepare): added modify subcommand
refractored Nov 29, 2023
d668d60
fix(cmds/daily): fixed crashing issue when DailyClaimedAt is nil
refractored Nov 29, 2023
ae3e95f
fix(cmds/usermanage): usermap missing if statement
refractored Nov 29, 2023
20413ef
feat(cmds/info): moved info command into its own command user and bot…
refractored Nov 30, 2023
81c3068
fix(cmds/info): remove broken guild count
refractored Dec 1, 2023
a356091
Fix(orders): use .Find instead of .First
refractored Dec 6, 2023
c0296a1
Fix(cmds/usermanage): do not let users set others to a higher permiss…
refractored Dec 6, 2023
f645bf7
Feat(cmds/bot): combine shutdown and purgecmds into a single command
refractored Dec 6, 2023
7a82a18
feat(cmds/order): combine order and cancelorder into a single command
refractored Dec 6, 2023
d152b1a
feat(cmds/status): combine deliver.go,prepare.go, and acceptorder.go …
refractored Dec 6, 2023
3032807
feat(cmds/blacklist): combine unblacklist.go into blacklist.go
refractored Dec 6, 2023
2571df9
chore(command_handler): remove unused command.
refractored Dec 6, 2023
4a865c1
feat(command_handler): added new subcommands, addcredits and take cre…
refractored Dec 6, 2023
7e26302
chore(cmds): restructuring
refractored Dec 6, 2023
c363bbd
chore(cmds): restructuring
refractored Dec 6, 2023
eaee662
Feat(cmds): DMs can now be toggled using the command interface now.
refractored Dec 6, 2023
5353e66
Fix(cmds/usermanage): Permissions are now looked up with GetPermissio…
refractored Dec 6, 2023
d348666
fix(cmds/usermanage): prevent people from modifying permissions of pe…
refractored Dec 6, 2023
b396862
fix(cmds): small changes
refractored Dec 7, 2023
2ead540
Merge pull request #40 from refractored/user-management-refrac
refractored Dec 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 134 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,153 @@
## 🥪 Sandwich Delivery 🥪
Sandwich Delivery is a Discord bot in which people can order any sandwich they desire (even non-existent ones), have it made in our Discord by our top-of-the-line sandwich artists, and then have it delivered to your Discord server.

To see the bot in action, or you want to use our bot to order sandwiches, [Join our discord](https://discord.gg/uHVzYBt8jD)!
[Join our Discord](https://discord.gg/uHVzYBt8jD) for quick responses, support, and to see the bot in action!


If you find any bugs or have a suggestion, please [create an issue](../../issues/new)!

## Self Hosting
### Bare Metal
#### Requirements

* Golang 1.20 or above
* MariaDB 10 or later
* A Discord server
* [Discord bot token](https://discord.com/developers/applications)

#### Setting Up

To get started, you first get an executable, you can either compile yourself (see [compilation](#compilation)) or download the latest release: [stable](../../releases/latest) or [nightly/beta](https://nightly.link/refractored/sandwich-delivery/workflows/go/master/sandwich-delivery-linux-amd64.zip).

Once you have the executable, you need to create a config file in the working directory, you can use the [example config](config.json.example) as a template.
You can find a configuration reference [here](#configuration).

Once you have the config file, you can run the executable and you're off!

### Docker
#### Requirements

* Docker
* Docker Compose (optional)
* MariaDB 10 or later (must be accessible from the container)
* A Discord server
* [Discord bot token](https://discord.com/developers/applications)

#### Setting Up

To run the bot yourself, clone the project using<br />
``https://github.com/refractored/sandwich-delivery.git``,<br />
then run it in the main directory using<br />
``go run ./src/main``
For Docker, you can use our example [docker-compose.yml](docker-compose.yml.example) file as a reference.
You can use our image, or build one yourself, see [compilation](#compilation) (long story short, you can just change the line containing `image` to `build: .`).

Once you have a container, you need to create a config file in the volume attached to `/app/work`, you can use the [example config](config.json.example) as a template.
You can find a configuration reference [here](#configuration).

Once you have the config file, you can run the container with `docker-compose up -d` (or `docker-compose up` if you want to see the logs).



## Configuration

### Config File

The config file is a JSON file that contains all the configuration for the bot.
The config file is located in the working directory and is called `config.json`.

### Config Reference

| Key | Type | Description | Optional? |
|-------------------------|-------------------------------|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------|
| `token` | `string` | The Discord bot token | No |
| `owners` | `array` of `string` | The Discord IDs of the bot owners | One is required |
| `guildID` | `string` | The Discord ID of the guild that certain commands will be registered in (e.g. `/blacklist`) | No |
| `kitchenChannelID` | `string` | The Discord ID of the channel where orders will be sent. | No |
| `startupChannelID` | `string` | The Discord ID of the channel where startup and shutdown messages will be sent. | Yes |
| `database` | `object` | The database configuration | No |
| `database.host` | `string` | The database host | No, unless `database.URL` is set, then it must be empty. |
| `database.port` | `int` | The database port | No, unless `database.URL` is set, then it must be empty. |
| `database.user` | `string` | The database user | No, unless `database.URL` is set, then it must be empty. |
| `database.password` | `string` | The database password | No, unless `database.URL` is set, then it must be empty. |
| `database.database` | `string` | The database name | No, unless `database.URL` is set, then it must be empty. |
| `database.extraOptions` | `map` of `string` -> `string` | Extra options to pass to the database connection | Yes, unless `database.URL` is set, then it must be empty. |
| `database.URL` | `string` | The database URL/DSN. A reference can be found [here](https://github.com/go-sql-driver/mysql#dsn-data-source-name) | Yes, unless other database entries are not set. |
| `tokensPerOrder` | `int` | The amount of tokens an order costs. Must be > 0 and defaults to 1. | Yes |
| `dailyTokens` | `int` | The amount of tokens a user gets per day. Must be > 0 and defaults to 1. | Yes |

### !! Warning !!
If you are using the `database.URL` option and do not add `parseTime=true` as an option, you will run into issues.
This will also occur if you add an entry to `database.extraOptions` with the key `parseTime` and the value `false`.



## Compilation
### Getting the Source

To get the source code, you can either download the source code from the [latest release](../../releases/latest) or clone the repository with git:

```bash
git clone https://github.com/refractored/sandwich-delivery
```

Then you can `cd` into the directory.

### Bare Metal Executable
#### Requirements

* Go 1.21.4 or later

#### Building

After you have the source, building is as easy as one command:

```bash
go build -v -o sandwich-delivery src/main
```

A new executable should be created in the working directory called `sandwich-delivery`.

### Docker Image
#### Requirements

* Docker
* Docker Compose (optional)

#### Building

After you have the source, building is as easy as one command:

```bash
docker build -t sandwich-delivery .
```

**OR**

You can use the [docker-compose.yml](docker-compose.yml.example) file as a reference, but replace `image: ` with `build: .`

Then you can run the container with `docker-compose up -d` (or `docker-compose up` if you want to see the logs).



## Bugs

If you find any bugs or have a suggestion, please [create an issue](../../issues/new)!

For quick responses and community support, you can also [join our Discord](https://discord.gg/uHVzYBt8jD).



## Contributing

If you want to contribute, you can create a pull request, currently, however, there are no guidelines for contributing apart from the [code of conduct](CODE_OF_CONDUCT.md).



## License

This project is licensed under the [GPLv3 License](LICENSE).



## Credits

* [Refractored](https://refractored.net) - Project Owner & Lead Developer
* [Bacon](https://baconing.tech) - Developer
* [All our contributors](../../graphs/contributors)
* [All our dependencies](../../network/dependencies)
* And you for using it ❤️
17 changes: 13 additions & 4 deletions config.json.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"token": "BOT_TOKEN",
"mysqldsn": "user:password@tcp(localhost:3306)/your_database_name?parseTime=true",
"owners": ["1234", "1234"],
"guildid": "1234"
"token": "secret",
"owners": ["you", "and", "your", "friends"],
"guildID": "some numbers",

"kitchenChannelID": "some numbers",

"database": {
"host": "127.0.0.1",
"port": 3306,
"user": "sandwich",
"password": "secret",
"database": "sandwich"
}
}
66 changes: 59 additions & 7 deletions src/commands/blacklist.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,30 @@ func (c BlacklistCommand) getCommandData() *discordgo.ApplicationCommand {
Description: "Blacklist a user from using the bot.",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "user",
Description: "The user to blacklist.",
Required: true,
Name: "add",
Description: "Add an user to the blacklisted users.",
Type: discordgo.ApplicationCommandOptionSubCommand,
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "user",
Description: "The user to blacklist.",
Required: true,
},
},
},
{
Name: "remove",
Description: "remove an user from the blacklisted users.",
Type: discordgo.ApplicationCommandOptionSubCommand,
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "user",
Description: "The user to remove.",
Required: true,
},
},
},
},
}
Expand All @@ -37,12 +57,25 @@ func (c BlacklistCommand) permissionLevel() models.UserPermissionLevel {
}

func (c BlacklistCommand) execute(session *discordgo.Session, event *discordgo.InteractionCreate) {
userOption := event.ApplicationCommandData().Options[0].UserValue(session)
switch event.ApplicationCommandData().Options[0].Name {
case "add":
BlacklistAdd(session, event)
break
case "remove":
BlacklistRemove(session, event)
break
}
}

var user models.User
func BlacklistAdd(session *discordgo.Session, event *discordgo.InteractionCreate) {
userOption := event.ApplicationCommandData().Options[0].Options[0].UserValue(session)

database.GetDB().First(&user, "user_id = ?", userOption.ID)
var user models.User

resp := database.GetDB().Find(&user, "user_id = ?", userOption.ID)
if resp.RowsAffected == 0 {
user.UserID = userOption.ID
}
user.IsBlacklisted = true
database.GetDB().Save(&user)

Expand All @@ -53,3 +86,22 @@ func (c BlacklistCommand) execute(session *discordgo.Session, event *discordgo.I
},
})
}

func BlacklistRemove(session *discordgo.Session, event *discordgo.InteractionCreate) {
userOption := event.ApplicationCommandData().Options[0].Options[0].UserValue(session)

var user models.User

resp := database.GetDB().Find(&user, "user_id = ?", userOption.ID)
if resp.RowsAffected == 0 {
user.UserID = userOption.ID
}
user.IsBlacklisted = true
database.GetDB().Save(&user)
session.InteractionRespond(event.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: "User blacklisted successfully.",
},
})
}
109 changes: 109 additions & 0 deletions src/commands/bot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package commands

import (
"github.com/bwmarrin/discordgo"
"math/rand"
"os"
"sandwich-delivery/src/config"
"sandwich-delivery/src/models"
)

type BotCommand struct{}

func (c BotCommand) getName() string {
return "bot"
}

func (c BotCommand) getCommandData() *discordgo.ApplicationCommand {
DMPermission := new(bool)
*DMPermission = false
return &discordgo.ApplicationCommand{Name: c.getName(),
Description: "Manage the bot.",
Options: []*discordgo.ApplicationCommandOption{
{
Name: "shutdown",
Description: "Shutdown the bot.",
Type: discordgo.ApplicationCommandOptionSubCommand,
},
{
Name: "purgecmds",
Description: "Purges all commands and restarts.",
Type: discordgo.ApplicationCommandOptionSubCommand,
},
},
DMPermission: DMPermission,
}
}

func (c BotCommand) registerGuild() string {
return config.GetConfig().GuildID
}

func (c BotCommand) permissionLevel() models.UserPermissionLevel {
return models.PermissionLevelAdmin
}

func (c BotCommand) execute(session *discordgo.Session, event *discordgo.InteractionCreate) {
switch event.ApplicationCommandData().Options[0].Name {
case "shutdown":
BotShutdown(session, event)
break
case "purgecmds":
BotPurgeCMDS(session, event)
break
}
}
func BotShutdown(session *discordgo.Session, event *discordgo.InteractionCreate) {
var shutdownMessages = []string{
"Was it something I did? :( *(Shutting Down)*",
"Whatever you say... *(Shutting Down)*",
"Whatever. *(Shutting Down)*",
"Rude. *(Shutting Down)*",
"Fine... I guess... :( *(Shutting Down)*",
}

selection := rand.Intn(len(shutdownMessages))

session.InteractionRespond(event.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: shutdownMessages[selection],
},
})

session.Close()
os.Exit(0)
}

func BotPurgeCMDS(session *discordgo.Session, event *discordgo.InteractionCreate) {
session.InteractionRespond(event.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: "Give me a minute...",
},
})

applicationCommands, err := session.ApplicationCommands(session.State.User.ID, "")
if err != nil {
return
}
for _, applicationCommand := range applicationCommands {
session.InteractionRespond(event.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
})
session.ApplicationCommandDelete(session.State.User.ID, "", applicationCommand.ID)
}

if InteractionIsDM(event) {
applicationCommands, err := session.ApplicationCommands(session.State.User.ID, event.GuildID)
if err != nil {
return
}
for _, applicationCommand := range applicationCommands {
session.ApplicationCommandDelete(session.State.User.ID, event.GuildID, applicationCommand.ID)
}
}

session.Close()
os.Exit(0)
}
4 changes: 2 additions & 2 deletions src/commands/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func InteractionIsDM(event *discordgo.InteractionCreate) bool {
func DoesUserExist(userID string) bool {
var user models.User

resp := database.GetDB().First(&user, "user_id = ?", userID)
resp := database.GetDB().Find(&user, "user_id = ?", userID)

return resp.RowsAffected != 0
}
Expand All @@ -62,7 +62,7 @@ func IsUserBlacklisted(userID string) bool {

var user models.User

resp := database.GetDB().First(&user, "user_id = ?", userID)
resp := database.GetDB().Find(&user, "user_id = ?", userID)

if resp.RowsAffected == 0 {
return false
Expand Down
Loading
Loading