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

add CoC update message... command #89

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 12 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,18 @@ fn app() -> Result<(), Error> {
api::is_mod,
);

cmds.add_protected(
"?CoC update message...",
welcome::update_welcome_message,
api::is_mod,
);
cmds.help_protected(
"?CoC update",
"Update the welcome message content",
welcome::update_help,
api::is_mod,
);

// Post the welcome message to the welcome channel.
cmds.add_protected("?CoC {channel}", welcome::post_message, api::is_mod);
cmds.help_protected(
Expand All @@ -188,7 +200,6 @@ fn app() -> Result<(), Error> {
welcome::help,
api::is_mod,
);

let menu = cmds.menu();
cmds.add("?help", move |args: Args| {
let output = main_menu(&args, menu.as_ref().unwrap());
Expand Down
86 changes: 86 additions & 0 deletions src/welcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ pub(crate) fn post_message(args: Args) -> Result<(), Error> {

let white_check_mark = ReactionType::from("✅");
message.react(args.cx, white_check_mark)?;

cache_welcome_message(args.cx, message)?;
}
Ok(())
}
Expand Down Expand Up @@ -126,6 +128,90 @@ pub(crate) fn assign_talk_role(cx: &Context, reaction: &Reaction) -> Result<(),
Ok(())
}

pub(crate) fn update_welcome_message(args: Args) -> Result<(), Error> {
use std::str::FromStr;

let new_message = &args
.params
.get("message")
.ok_or("unable to retrieve message param")?;

let welcome_message_is_not_cached = {
let data = args.cx.data.read();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Say this function was ran twice in parallel. This check could be hit twice before the message is stored in data, which could cause parallel attempts to populate it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are absolutely correct, nice catch, this is a problem and I will address it.

!data.contains::<CachedWelcomeMessage>()
};

if welcome_message_is_not_cached {
info!("Welcome message not cached, caching");
let conn = DB.get()?;

let res = conn
.build_transaction()
.read_only()
.run::<_, Box<dyn std::error::Error>, _>(|| {
let res: Option<_> = messages::table
.filter(messages::name.eq("welcome"))
.first::<(i32, String, String, String)>(&conn)
.optional()?;

Ok(res)
})?;

if let Some((_, _, message_id, channel_id)) = res {
let message = ChannelId::from(u64::from_str(&channel_id)?)
.message(args.cx, u64::from_str(&message_id)?)?;

cache_welcome_message(args.cx, message)?;
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of failing, maybe we should somehow have it post the message? Might be tricky, ergonomically speaking, because of the lack of awareness of which channel to post in.

api::send_reply(
&args,
"No welcome message found, please post the welcome message",
)?;
return Ok(());
}
}

let mut data = args.cx.data.write();
let welcome_message = data.get_mut::<CachedWelcomeMessage>().unwrap();
welcome_message.edit(args.cx, |m| m.content(new_message))?;

Ok(())
}

pub(crate) struct CachedWelcomeMessage;

impl TypeMapKey for CachedWelcomeMessage {
type Value = Message;
}

pub(crate) fn cache_welcome_message(cx: &Context, message: Message) -> Result<(), Error> {
let mut data = cx.data.write();
data.insert::<CachedWelcomeMessage>(message);

Ok(())
}

pub(crate) fn update_help(args: Args) -> Result<(), Error> {
let help_string = format!(
"
Update the existing welcome message content
```
{command}
```
**Example:**
```
?CoC update my new message

```
will update the welcome message to \"my new message\"
",
command = "?CoC update message..."
);

api::send_reply(&args, &help_string)?;
Ok(())
}

pub(crate) fn help(args: Args) -> Result<(), Error> {
let help_string = format!(
"
Expand Down