Skip to content

Commit

Permalink
Introduce React-based UI (fixes #23) (related #22)
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Apr 4, 2019
1 parent 21d708d commit 6b1c18c
Show file tree
Hide file tree
Showing 30 changed files with 13,336 additions and 752 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Cleaned up old cruft in the codebase (`gfx` module).
- Moved log configuration to external file (see [example log4rs.yaml]).
- No longer raise an error on bad input.
- UI is now built in React ([#23]).
* This adds the `-WebRoot` option to [`tools/setmod.ps1`] to override where to load files from for development purposes.

### Removed
- Removed `!counter` in favor of `!command` with same functionality. Using the `{{count}}` variable in the template will cause the count to be incremented.
- `[[aliases]]` section from configuration. Aliases are now stored in the database.

[`alias configuration`]: README.md#alias
[example log4rs.yaml]: log4rs.yaml
[`tools/setmod.ps1`]: tools/setmod.ps1

[#18]: https://github.com/udoprog/setmod/issues/18
[#22]: https://github.com/udoprog/setmod/issues/22
[#23]: https://github.com/udoprog/setmod/issues/23
[#24]: https://github.com/udoprog/setmod/issues/24

[Unreleased]: https://github.com/udoprog/setmod/compare/0.2.3...HEAD
Expand Down
11 changes: 11 additions & 0 deletions bot/migrations/2019-04-04-061908_after_streams_id/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CREATE TABLE after_streams2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
channel VARCHAR,
added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
user TEXT NOT NULL,
text TEXT NOT NULL
);

INSERT INTO after_streams2 (channel, added_at, user, text) SELECT channel, added_at, user, text FROM after_streams;
DROP TABLE after_streams;
ALTER TABLE after_streams2 RENAME TO after_streams;
20 changes: 2 additions & 18 deletions bot/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod after_streams;
mod aliases;
mod commands;
pub mod models;
Expand All @@ -8,6 +9,7 @@ mod words;
use crate::player;

pub use self::{
after_streams::{AfterStream, AfterStreams},
aliases::{Alias, Aliases},
commands::{Command, Commands},
persisted_set::PersistedSet,
Expand Down Expand Up @@ -69,24 +71,6 @@ impl Database {
Settings { db: self.clone() }
}

/// Add an afterstream reminder.
pub fn insert_afterstream(&self, user: &str, text: &str) -> Result<(), failure::Error> {
use self::schema::after_streams::dsl;

let c = self.pool.get()?;

let after_stream = models::AfterStream {
user: String::from(user),
text: String::from(text),
};

diesel::insert_into(dsl::after_streams)
.values(&after_stream)
.execute(&c)?;

Ok(())
}

/// Find user balance.
pub fn balance_of(&self, name: &str) -> Result<Option<i32>, failure::Error> {
use self::schema::balances::dsl::*;
Expand Down
51 changes: 51 additions & 0 deletions bot/src/db/after_streams.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::db::{self, models, schema};
use diesel::prelude::*;

pub use self::models::AfterStream;

#[derive(Clone)]
pub struct AfterStreams {
db: db::Database,
}

impl AfterStreams {
/// Open the after streams database.
pub fn load(db: db::Database) -> Result<Self, failure::Error> {
Ok(AfterStreams { db })
}

/// Push the given afterstream message.
pub fn push(&self, channel: &str, user: &str, text: &str) -> Result<(), failure::Error> {
use self::schema::after_streams::dsl;
let c = self.db.pool.get()?;

let after_stream = models::InsertAfterStream {
channel: Some(String::from(channel)),
user: String::from(user),
text: String::from(text),
};

diesel::insert_into(dsl::after_streams)
.values(&after_stream)
.execute(&c)?;

Ok(())
}

/// Delete the after stream with the given id.
pub fn delete(&self, id: i32) -> Result<bool, failure::Error> {
use self::schema::after_streams::dsl;
let c = self.db.pool.get()?;
let count = diesel::delete(dsl::after_streams.filter(dsl::id.eq(id))).execute(&c)?;
Ok(count == 1)
}

/// List all available after streams.
pub fn list(&self) -> Result<Vec<AfterStream>, failure::Error> {
use self::schema::after_streams::dsl;
let c = self.db.pool.get()?;
Ok(dsl::after_streams
.order(dsl::added_at.asc())
.load::<models::AfterStream>(&c)?)
}
}
13 changes: 12 additions & 1 deletion bot/src/db/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,19 @@ pub struct Alias {
pub text: String,
}

#[derive(diesel::Insertable)]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, diesel::Queryable)]
pub struct AfterStream {
pub id: i32,
pub channel: Option<String>,
pub added_at: NaiveDateTime,
pub user: String,
pub text: String,
}

#[derive(diesel::Insertable)]
#[table_name = "after_streams"]
pub struct InsertAfterStream {
pub channel: Option<String>,
pub user: String,
pub text: String,
}
Expand Down
5 changes: 3 additions & 2 deletions bot/src/db/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ table! {
}

table! {
after_streams (channel, added_at, user) {
channel -> Text,
after_streams (id) {
id -> Integer,
channel -> Nullable<Text>,
added_at -> Timestamp,
user -> Text,
text -> Text,
Expand Down
4 changes: 3 additions & 1 deletion bot/src/irc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub struct Irc<'a> {
pub commands: db::Commands<db::Database>,
pub aliases: db::Aliases<db::Database>,
pub bad_words: db::Words<db::Database>,
pub after_streams: db::AfterStreams,
pub global_bus: Arc<bus::Bus>,
pub modules: &'a [Box<dyn module::Module + 'static>],
pub shutdown: utils::Shutdown,
Expand All @@ -96,6 +97,7 @@ impl Irc<'_> {
commands,
aliases,
bad_words,
after_streams,
global_bus,
modules,
shutdown,
Expand Down Expand Up @@ -240,7 +242,7 @@ impl Irc<'_> {
"afterstream",
after_stream::AfterStream {
cooldown: irc_config.afterstream_cooldown.clone(),
db: db.clone(),
after_streams,
},
);
}
Expand Down
5 changes: 3 additions & 2 deletions bot/src/irc/after_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{command, db, utils};
/// Handler for the `!afterstream` command.
pub struct AfterStream {
pub cooldown: utils::Cooldown,
pub db: db::Database,
pub after_streams: db::AfterStreams,
}

impl command::Handler for AfterStream {
Expand All @@ -13,7 +13,8 @@ impl command::Handler for AfterStream {
return Ok(());
}

self.db.insert_afterstream(ctx.user.name, ctx.rest())?;
self.after_streams
.push(ctx.user.target, ctx.user.name, ctx.rest())?;
ctx.respond("Reminder added.");
Ok(())
}
Expand Down
2 changes: 2 additions & 0 deletions bot/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![recursion_limit = "128"]

#[macro_use]
extern crate diesel;
#[macro_use]
Expand Down
14 changes: 7 additions & 7 deletions bot/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,20 @@ fn main() -> Result<(), failure::Error> {
.parent()
.ok_or_else(|| format_err!("missing parent"))?;

let web_root = m
.value_of("web-root")
.map(PathBuf::from)
.unwrap_or_else(|| root.join("web"));
let web_root = m.value_of("web-root").map(PathBuf::from);
let web_root = web_root.as_ref().map(|p| p.as_path());

setup_logs(root).context("failed to setup logs")?;

match try_main(&root, &web_root, &config) {
match try_main(&root, web_root, &config) {
Err(e) => utils::log_err("bot crashed", e),
Ok(()) => log::info!("bot was shut down"),
}

Ok(())
}

fn try_main(root: &Path, web_root: &Path, config: &Path) -> Result<(), failure::Error> {
fn try_main(root: &Path, web_root: Option<&Path>, config: &Path) -> Result<(), failure::Error> {
log::info!("Starting SetMod Version {}", setmod_bot::VERSION);

let thread_pool = Arc::new(tokio_threadpool::ThreadPool::new());
Expand Down Expand Up @@ -110,6 +108,7 @@ fn try_main(root: &Path, web_root: &Path, config: &Path) -> Result<(), failure::
let commands = db::Commands::load(db.clone())?;
let aliases = db::Aliases::load(db.clone())?;
let bad_words = db::Words::load(db.clone())?;
let after_streams = db::AfterStreams::load(db.clone())?;

// TODO: remove this migration next major release.
if let Some(irc) = config.irc.as_ref() {
Expand Down Expand Up @@ -147,7 +146,7 @@ fn try_main(root: &Path, web_root: &Path, config: &Path) -> Result<(), failure::
let mut futures =
Vec::<Box<dyn Future<Item = (), Error = failure::Error> + Send + 'static>>::new();

let (web, future) = web::setup(web_root, global_bus.clone())?;
let (web, future) = web::setup(web_root, global_bus.clone(), after_streams.clone())?;

// NB: spawn the web server on a separate thread because it's needed for the synchronous authentication flow below.
core.runtime().executor().spawn(future.map_err(|e| {
Expand Down Expand Up @@ -285,6 +284,7 @@ fn try_main(root: &Path, web_root: &Path, config: &Path) -> Result<(), failure::
commands,
aliases,
bad_words,
after_streams,
global_bus,
modules: &modules,
shutdown,
Expand Down
Loading

0 comments on commit 6b1c18c

Please sign in to comment.