Skip to content
This repository has been archived by the owner on Oct 28, 2020. It is now read-only.

Commit

Permalink
impr: improve wolfram alpha command output
Browse files Browse the repository at this point in the history
Add environment variable to select wolfram alpha command output
verbosity.
Improve wolfram alpha command output to prioritize displaying plots as
the image for the resulting embed.
  • Loading branch information
indiv0 committed Nov 24, 2017
1 parent 6c6fa47 commit 2de13f8
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 29 deletions.
8 changes: 5 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Smexybot Configuration
## Smexybot Configuration
#

# The Discord bot token to be used for login. By default, the bot will attempt
Expand All @@ -11,9 +11,11 @@ export DISCORD_BOT_TOKEN="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
## Plugin Configurations
#

# XKCD
## XKCD
export GOOGLE_XKCD_CUSTOM_SEARCH_API_KEY="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
export GOOGLE_XKCD_CUSTOM_SEARCH_ENGINE_ID="012345678901234567890:AAAAAAAAAAA"

# Wolfram
## Wolfram
export WOLFRAM_ALPHA_API_APP_ID="ABC123-ABC123ABCD"
# whether or not to display simplified Wolfram|Alpha results.
export WOLFRAM_RESULT_SIMPLE_DISPLAY="true"
76 changes: 50 additions & 26 deletions src/command/wolfram_alpha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use hyper_tls::HttpsConnector;
use serenity::utils::builder::{CreateEmbed, CreateEmbedField};
use std::env;
use std::error::Error as StdError;
use std::str::FromStr;
use tokio_core::reactor::Core;
use util::{check_msg, random_colour, stringify};
use wolfram_alpha::{self, Error as WolframError};
Expand All @@ -23,6 +24,14 @@ use wolfram_alpha::model::{Pod, QueryResult};
lazy_static! {
static ref API_APP_ID: String = env::var("WOLFRAM_ALPHA_API_APP_ID")
.expect("WOLFRAM_ALPHA_API_APP_ID env var not set");
static ref WOLFRAM_RESULT_SIMPLE_DISPLAY: bool =
env::var("WOLFRAM_RESULT_SIMPLE_DISPLAY")
.as_ref()
.map(|s| &s[..])
.map(bool::from_str)
.ok()
.and_then(Result::ok)
.unwrap_or(false);
}

pub struct WolframPlugin {
Expand Down Expand Up @@ -81,7 +90,7 @@ command!(wolfram(_ctx, msg, args) {
let pods = query_result.pod
.ok_or_else(|| "Result did not contain any parsable information")?;
check_msg(msg.channel_id.send_message(
|m| m.embed(|e| format_pods(&pods, e).colour(colour)),
|m| m.embed(|e| format_pods(&pods, e, *WOLFRAM_RESULT_SIMPLE_DISPLAY).colour(colour)),
));
} else if let Some(didyoumeans) = query_result.didyoumeans {
let colour = random_colour();
Expand Down Expand Up @@ -126,7 +135,10 @@ command!(wolfram(_ctx, msg, args) {
}
});

fn format_pods(pods: &[Pod], embed: CreateEmbed) -> CreateEmbed {
/// Formats pods to be displayed in a Discord embed.
///
/// If `simple` is set to `true`, the embed will only include the primary pod.
fn format_pods(pods: &[Pod], embed: CreateEmbed, simple: bool) -> CreateEmbed {
let mut iter = pods.iter();

// First result is the interpretation.
Expand All @@ -141,22 +153,37 @@ fn format_pods(pods: &[Pod], embed: CreateEmbed) -> CreateEmbed {

if let Some(img) = pods.iter()
.skip(1)
.filter_map(|p| p.subpod.iter().filter_map(|s| s.img.clone()).next())
.next() {
.filter_map(|p|
p.subpod.iter()
.filter(|s| {
// Find all subpods that have a blank "plaintext" field.
// This usually indicates they have an image which should be
// displayed instead.
match s.plaintext {
Some(ref text) if text == "" || text == "\n" => true,
_ => false,
}
})
.filter_map(|s| s.img.clone())
.next()
)
.next()
{
embed = embed.image(unescape(img.src.as_str()).as_ref());
}

// If there is a primary pod, then only format and print that pod.
if let Some(pod) = pods.iter().find(|p| p.primary == Some(true)) {
embed = embed.field(|f| format_pod(pod, f));
} else {
// Parse all the remaining pods.
for pod in iter {
embed = embed.field(|f| format_pod(pod, f.inline(false)));
// If there is a primary pod, and we only want a simple display, then only
// format and print that pod.
if simple {
if let Some(pod) = pods.iter().find(|p| p.primary == Some(true)) {
return embed.field(|f| format_pod(pod, f));
}
}

embed
// Parse all the remaining pods.
pods.iter().fold(embed, |embed, pod| {
embed.field(|f| format_pod(pod, f))
})
}

fn format_pod(pod: &Pod, f: CreateEmbedField) -> CreateEmbedField {
Expand All @@ -166,25 +193,22 @@ fn format_pod(pod: &Pod, f: CreateEmbedField) -> CreateEmbedField {
let mut result = String::new();
for subpod in &pod.subpod {
let text = match subpod.plaintext {
// If the text field is empty, add a message indicating as such
// (discord doesn't like empty/just newline fields).
Some(ref text) if text == "" || text == "\n" => "[No text]".to_owned(),
// If the text field exists, but is blank, we likely have an image
// we should display here instead (and Discord doesn't like
// empty/just newline fields in embeds anyways).
// However, image selection is done outside of this function, so we
// just ignore it.
Some(ref text) if text == "" || text == "\n" => {
"[No text]".to_owned()
},
// Grab all the consecutive blobs of text.
Some(ref text) => {
trace!("Adding text: {}", text);
text.to_owned()
},
// If there's no text, then there's usually an image.
_ => {
match subpod.img {
Some(ref img) => {
let url = unescape(img.src.as_ref());
trace!("Adding img src: {}", url);
url
},
None => break,
}
},
// If there was no plaintext field and no image, we don't display
// anything.
None => break,
};

result.push_str(&format!("{}\n", &text));
Expand Down

0 comments on commit 2de13f8

Please sign in to comment.