-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from emallson/master
Update to master
- Loading branch information
Showing
28 changed files
with
1,725 additions
and
764 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Copyright (c) 2020 J David Smith, All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. | ||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. | ||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
Discord bot for [Arena Highlander][discord] to run | ||
leagues and display results. | ||
|
||
## Setting Up | ||
|
||
This codebase uses [Docker Compose](https://docs.docker.com/compose/) as the | ||
primary build system and can be run on any system with that installed: | ||
|
||
docker-compose build | ||
|
||
It is often helpful to be able to run things (like `cargo check` or `cargo | ||
test`) outside of docker. This project is implemented in (mostly) | ||
[Rust](https://rustup.rs), so installing that---while not required---is | ||
encouraged. | ||
|
||
### Environment Variables | ||
|
||
The bot uses 3 environment variables during its run, two of which are optional: | ||
|
||
- `DATABASE_URL` (required): The connection string for the (PostgreSQL) database | ||
- `DISCORD_TOKEN`: The access token for the discord bot. See their API docs for details. | ||
- `SENTRY_TOKEN`: The access token for [sentry](https://sentry.io), which is used for logging in production. | ||
|
||
For development, you'll want to copy the [example `.env` | ||
file](bot-rs/.env.example) to `bot-rs/.env`. The example value provided uses | ||
the default login credentials for the database. These credentials are obviously | ||
NOT SECURE and should be changed if you are running outside of a local | ||
development machine. | ||
|
||
If `DISCORD_TOKEN` is unset, the only thing you'll be able to do is work with | ||
existing results via the site (which is accessible at `localhost:3000` by | ||
default) | ||
|
||
### Database Initialization | ||
|
||
The base docker images should set up *almost* everything. After successfully building, you will need to run: | ||
|
||
```bash | ||
docker-compose up db -d # start the DB first so postgres has time to start | ||
docker-compose run botrs diesel database setup --locked-schema # setup the DB | ||
``` | ||
|
||
Changes to the schema should be committed to version control using `diesel migration` commands. For example: | ||
|
||
```bash | ||
diesel migration generate example # generation migration named "example" | ||
# edit your migration | ||
diesel migration run # run the migration | ||
diesel migration redo # revert and re-run the migration as necessary to get it right | ||
``` | ||
|
||
Some test data is included in `db-setup/test_data.sql`. If you have | ||
`psql` installed, you can import it with: | ||
|
||
```bash | ||
psql $DATABASE_URL < db-setup/test_data.sql | ||
``` | ||
|
||
### Running Tests | ||
|
||
The full test suite requires the database to be running and the `DATABASE_URL` environment variable to be set. | ||
|
||
```bash | ||
docker-compose up db -d # start the DB in the background | ||
export DATABASE_URL=.... # set the DB connection info | ||
cargo test # run the tests | ||
docker-compose run botrs cargo test # alternative to cargo test if you didn't install rust locally | ||
``` | ||
|
||
## Deploying | ||
|
||
Contact `emallson` via the [Arena Highlander Discord][discord] if you are | ||
interested in deploying your own league bot. | ||
|
||
[discord]: https://discord.gg/h2nEQHg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# connects to the default credentials in the docker-compose setup. | ||
# change this if you're actually putting this online | ||
DATABASE_URL=postgres://user:arstarst@db/db | ||
# token needed to connect to discord | ||
#DISCORD_TOKEN= | ||
# token needed to connect to sentry | ||
#SENTRY_TOKEN= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
FROM rust | ||
RUN apt update && apt install libpq5 | ||
RUN cargo install diesel_cli --no-default-features --features postgres | ||
WORKDIR /opt/bot | ||
COPY dummy.rs . | ||
COPY Cargo.toml . | ||
COPY Cargo.lock . | ||
RUN cargo build --release --bin dummy --locked | ||
COPY . . | ||
RUN cargo build --release --bin bot --locked | ||
CMD cargo run --release --bin bot --locked |
Binary file not shown.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
use chrono::{Utc}; | ||
use chrono_english::{parse_date_string, Dialect}; | ||
use serenity::framework::standard::{ | ||
macros::{command, group}, | ||
Args, CommandResult, | ||
}; | ||
use serenity::model::channel::Message; | ||
use serenity::prelude::*; | ||
|
||
use crate::DbConn; | ||
use crate::actions; | ||
|
||
#[group] | ||
#[prefix("admin")] | ||
#[only_in(guilds)] | ||
#[required_permissions("ADMINISTRATOR")] | ||
#[commands(new_league, list_leagues, delete_league)] | ||
pub(crate) struct LeagueControl; | ||
|
||
#[command] | ||
#[num_args(3)] | ||
#[delimiters(", ")] | ||
#[description("Define a new league. All times are in UTC")] | ||
#[usage("<title>, <start-date>, <end-date>")] | ||
#[example("!new-league April 2020, 1 April 2020, 1 May 2020")] | ||
fn new_league(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { | ||
let data = ctx.data.read(); | ||
let conn = data.get::<DbConn>().unwrap(); | ||
let title = args.single::<String>()?; | ||
let from = parse_date_string(args.single::<String>()?.as_str(), Utc::now(), Dialect::Us) | ||
.expect("Unable to parse 'from' argument"); | ||
let to = parse_date_string(args.single::<String>()?.as_str(), Utc::now(), Dialect::Us) | ||
.expect("Unable to parse 'from' argument"); | ||
let _league = actions::league::create_league(&*conn.lock().unwrap(), title, from, to) | ||
.expect("Unable to create new league"); | ||
|
||
msg.channel_id | ||
.say(&ctx.http, "League successfully created!")?; | ||
|
||
Ok(()) | ||
} | ||
|
||
#[command] | ||
#[description("List all existing leagues (includes inactive leagues).")] | ||
fn list_leagues(ctx: &mut Context, msg: &Message) -> CommandResult { | ||
let data = ctx.data.read(); | ||
let conn = data.get::<DbConn>().unwrap(); | ||
let leagues = | ||
actions::league::list_leagues(&*conn.lock().unwrap()).expect("Unable to list leagues"); | ||
|
||
let message = leagues | ||
.into_iter() | ||
.map(|l| { | ||
format!( | ||
"**{} League** (id: {}): {} to {}", | ||
l.title, l.id, l.start_date, l.end_date | ||
) | ||
}) | ||
.collect::<Vec<_>>() | ||
.join("\n"); | ||
msg.channel_id.send_message(&ctx.http, |m| { | ||
m.embed(|e| e.title("All Leagues").description(message)); | ||
m | ||
})?; | ||
Ok(()) | ||
} | ||
|
||
#[command] | ||
#[description("Delete a league. All associated decks will exist, but be unassigned to any league.")] | ||
#[num_args(1)] | ||
#[usage("<id>")] | ||
fn delete_league(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { | ||
let id = args.single::<i32>()?; | ||
let data = ctx.data.read(); | ||
let conn = data.get::<DbConn>().unwrap(); | ||
|
||
let _count = actions::league::delete_league(&*conn.lock().unwrap(), id) | ||
.expect("Unable to delete league"); | ||
let message = format!("Deleted league {}", id); | ||
msg.channel_id.say(&ctx.http, &message)?; | ||
|
||
Ok(()) | ||
} |
Oops, something went wrong.