Browse Source

Allow publishing programs

pull/3/head
Stephen 3 weeks ago
parent
commit
dc6f30cb41
5 changed files with 172 additions and 7 deletions
  1. +2
    -0
      migrations/2020-12-22-183017_addProgramPublishedFlag/down.sql
  2. +1
    -0
      migrations/2020-12-22-183017_addProgramPublishedFlag/up.sql
  3. +111
    -1
      src/handler.rs
  4. +51
    -0
      src/program.rs
  5. +7
    -6
      src/schema.rs

+ 2
- 0
migrations/2020-12-22-183017_addProgramPublishedFlag/down.sql View File

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
ALTER TABLE user_programs DROP COLUMN published;

+ 1
- 0
migrations/2020-12-22-183017_addProgramPublishedFlag/up.sql View File

@ -0,0 +1 @@
ALTER TABLE user_programs ADD COLUMN published INT NOT NULL DEFAULT 0;

+ 111
- 1
src/handler.rs View File

@ -89,7 +89,20 @@ impl Handler {
"DIR" => {
if self.list_saved_programs(msg, ctx).await.is_none() {
msg.channel_id
.send_message(&ctx, "Could not get list of programs from database.");
.say(&ctx, "Could not get list of programs from database.")
.await
.unwrap();
}
}
"PUBDIR" => {
if self.list_published_programs(msg, ctx).await.is_none() {
msg.channel_id
.say(
&ctx,
"Could not get list of published programs from database.",
)
.await
.unwrap();
}
}
_ => {
@ -101,6 +114,43 @@ impl Handler {
self.interpreter_load(name, msg, ctx).await;
}
if let Some(name) = line.strip_prefix("PUB ") {
if self.publish_program(name, msg, ctx).await.is_none() {
msg.channel_id
.say(&ctx, format!("Could not publish {}.", name))
.await
.unwrap();
}
}
if let Some(name) = line.strip_prefix("UNPUB ") {
if self.unpublish_program(name, msg, ctx).await.is_none() {
msg.channel_id
.say(&ctx, &format!("Could not unpublish {}.", name))
.await
.unwrap();
}
}
if let Some(id_str) = line.strip_prefix("PUBLOAD ") {
match id_str.parse::<i32>() {
Ok(id) => {
if self.load_published_program(msg, ctx, id).await.is_none() {
msg.channel_id
.say(&ctx, formatNone!("Could not load {}.", id))
.await
.unwrap();
}
}
Err(_) => {
msg.channel_id
.say(&ctx, "PUBLOAD requires a numerical ID.")
.await
.unwrap();
}
}
}
let mut split = line.splitn(2, ' ');
let first = split.next().unwrap();
if let Ok(num) = first.parse::<u32>() {
@ -163,6 +213,66 @@ impl Handler {
Some(())
}
async fn list_published_programs(&self, msg: &Message, ctx: &Context) -> Option<()> {
let program_names: Vec<String> =
Program::list_published_programs(self.conn.lock().ok()?.borrow())?
.iter()
.map(|row| format!("{}\t{}", row.0, row.1))
.collect();
msg.channel_id
.say(
&ctx,
format!(
"Found {} public programs:\r\n```\r\nid\tname\r\n{}\r\n```\r\n Load one with `PUBLOAD <id>`",
program_names.len(),
program_names.join("\r\n")),
)
.await
.unwrap();
Some(())
}
async fn publish_program(&self, name: &str, msg: &Message, ctx: &Context) -> Option<()> {
Program::set_program_published(self.conn.lock().ok()?.borrow(), name, msg.author.id, true)?;
msg.channel_id
.say(&ctx, format!("Published {}.", name))
.await
.unwrap();
Some(())
}
async fn unpublish_program(&self, name: &str, msg: &Message, ctx: &Context) -> Option<()> {
Program::set_program_published(
self.conn.lock().ok()?.borrow(),
name,
msg.author.id,
false,
)?;
msg.channel_id
.say(&ctx, format!("Published {}.", name))
.await
.unwrap();
Some(())
}
async fn load_published_program(&self, msg: &Message, ctx: &Context, id: i32) -> Option<()> {
let name = get_user_programs!(&self, &msg.author.id)
.load_published_program(&self.conn.lock().ok()?.borrow(), id)?;
msg.channel_id
.say(&ctx, format!("Loaded {} (\"{}\") into memory.", id, name))
.await
.unwrap();
Some(())
}
async fn interpreter_list(&self, msg: &Message, ctx: &Context) {
msg.channel_id
.say(


+ 51
- 0
src/program.rs View File

@ -26,6 +26,57 @@ impl Program {
.ok()
}
pub fn list_published_programs(conn: &PgConnection) -> Option<Vec<(i32, String)>> {
user_programs
.filter(columns::published.eq(1))
.select((columns::id, columns::name))
.load(conn)
.ok()
}
pub fn load_published_program(&mut self, conn: &PgConnection, id: i32) -> Option<String> {
let program: Vec<(String, String)> = user_programs
.filter(columns::id.eq(id).and(columns::published.eq(1)))
.limit(1)
.select((columns::name, columns::code))
.get_results(conn)
.ok()?;
if program.is_empty() {
return None;
}
let name = &program[0].0;
let code = &program[0].1;
self.parse_string(code)?;
Some(name.to_string())
}
pub fn set_program_published(
conn: &PgConnection,
name: &str,
user_id: UserId,
published: bool,
) -> Option<()> {
if diesel::update(
user_programs.filter(
columns::discord_user_id
.eq(BigDecimal::from_u64(*user_id.as_u64()).unwrap())
.and(columns::name.eq(name)),
),
)
.set(columns::published.eq(if published { 1 } else { 0 }))
.execute(conn)
.ok()? == 1
{
Some(())
} else {
None
}
}
pub fn stringify(&self) -> String {
let mut code: Vec<(u32, String)> =
self.code.iter().map(|(a, b)| (*a, b.to_owned())).collect();


+ 7
- 6
src/schema.rs View File

@ -1,8 +1,9 @@
table! {
user_programs (id) {
id -> Int4,
discord_user_id -> Numeric,
name -> Varchar,
code -> Text,
}
user_programs (id) {
id -> Int4,
discord_user_id -> Numeric,
name -> Varchar,
code -> Text,
published -> Int4,
}
}

Loading…
Cancel
Save