mirror of
https://github.com/osmarks/autobotrobot
synced 2025-01-03 04:10:27 +00:00
Initial commit, and yes the code is a mess.
This commit is contained in:
commit
90a5fce01e
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.env
|
||||
target
|
2036
Cargo.lock
generated
Normal file
2036
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "autobotrobot"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
serenity = "0.5"
|
||||
dotenv = "0.13"
|
||||
calculate = "0.5"
|
||||
ddg = "0.5"
|
||||
regex = "1.0"
|
||||
reqwest = "0.9"
|
||||
lazy_static = "1.2"
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# AutoBotRobot
|
||||
|
||||
https://discordapp.com/oauth2/authorize?&client_id=509849474647064576&scope=bot&permissions=68608
|
173
src/main.rs
Normal file
173
src/main.rs
Normal file
@ -0,0 +1,173 @@
|
||||
#[macro_use] extern crate serenity;
|
||||
extern crate dotenv;
|
||||
extern crate calc;
|
||||
extern crate ddg;
|
||||
extern crate regex;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
||||
use serenity::client::{Client, EventHandler};
|
||||
use serenity::framework::standard::{StandardFramework, help_commands};
|
||||
use serenity::model::{channel::Message, id::ChannelId};
|
||||
use serenity::utils::Colour;
|
||||
use std::env;
|
||||
use std::fmt::Display;
|
||||
use regex::Regex;
|
||||
|
||||
struct Handler;
|
||||
|
||||
impl EventHandler for Handler {}
|
||||
|
||||
pub fn main() {
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
// Load bot token from environment,
|
||||
let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("token unavailable"), Handler)
|
||||
.expect("Error creating client");
|
||||
|
||||
client.with_framework(StandardFramework::new()
|
||||
.configure(|c|
|
||||
c
|
||||
.prefixes(vec!["++", "$", ">"])
|
||||
.allow_whitespace(true)
|
||||
.case_insensitivity(true)
|
||||
.on_mention(true))
|
||||
.help(help_commands::with_embeds)
|
||||
.before(|_context, _message, command| { println!("Executing {}!", command); true })
|
||||
.command("ping", |c| c.cmd(ping).desc("Says Pong.").known_as("test"))
|
||||
.command("search", |c| c.cmd(search).desc("Executes a search using DuckDuckGo.").known_as("ddg"))
|
||||
.command("eval", |c| c.cmd(eval).desc("Evaluates an arithmetic expression.").known_as("calc"))
|
||||
.command("exec", |c| c.cmd(exec).desc("DO NOT USE"))
|
||||
.command("eval-polish", |c| c.cmd(eval_polish).desc("Evaluates a Polish-notation arithmetic expression.")));
|
||||
|
||||
if let Err(why) = client.start() {
|
||||
eprintln!("An error occured: {:?}", why);
|
||||
}
|
||||
}
|
||||
|
||||
command!(ping(_context, message) {
|
||||
message.reply("Pong!")?;
|
||||
});
|
||||
|
||||
fn send_error(channel: &ChannelId, text: &str) -> std::result::Result<(), serenity::Error> {
|
||||
channel.send_message(|m| {
|
||||
m
|
||||
.embed(|e| e.title("Error").description(text).colour((255, 0, 0)))
|
||||
}).map(|_| ())
|
||||
}
|
||||
|
||||
fn send_text(channel: &ChannelId, text: &str) -> std::result::Result<(), serenity::Error> {
|
||||
channel.send_message(|m| {
|
||||
m
|
||||
.embed(|e| e.title("Result").description(text).colour((0, 255, 0)))
|
||||
}).map(|_| ())
|
||||
}
|
||||
|
||||
fn send_result<T: Display, E: Display>(message: &Message, res: &Result<T, E>) -> std::result::Result<(), serenity::Error> {
|
||||
match res {
|
||||
Ok(x) => send_text(&message.channel_id, &x.to_string()),
|
||||
Err(e) => send_error(&message.channel_id, &e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate an arithmetic expression
|
||||
command!(eval(_context, message, args) {
|
||||
let expr = args.multiple::<String>()?.join(" "); // yes, this is kind of undoing the work the command parser does...
|
||||
send_result(message, &calc::eval(&expr))?;
|
||||
});
|
||||
|
||||
// Evaluate an arithmetic expression in polish notation
|
||||
command!(eval_polish(_context, message, args) {
|
||||
let expr = args.multiple::<String>()?.join(" ");
|
||||
send_result(message, &calc::eval_polish(&expr))?;
|
||||
});
|
||||
|
||||
command!(exec(_context, message) {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new("^.*exec.*```(.*)\n(.*)```").unwrap();
|
||||
}
|
||||
|
||||
println!("{:?}", &message.content);
|
||||
println!("{:?}", RE.captures(&message.content));
|
||||
});
|
||||
|
||||
// BELOW THIS LINE BE DRAGONS
|
||||
|
||||
struct SearchResult {
|
||||
url: Option<String>,
|
||||
image: Option<String>,
|
||||
text: String,
|
||||
title: String
|
||||
}
|
||||
|
||||
fn send_search_result(channel: &ChannelId, res: SearchResult) -> std::result::Result<(), serenity::Error> {
|
||||
channel.send_message(|m| {
|
||||
m
|
||||
.embed(|e| {
|
||||
let e = e.title(res.title).description(res.text).colour((0, 255, 255));
|
||||
let e = match res.url {
|
||||
Some(u) => e.url(u),
|
||||
None => e
|
||||
};
|
||||
let e = match res.image {
|
||||
Some(u) => e.image(u),
|
||||
None => e
|
||||
};
|
||||
e
|
||||
})
|
||||
}).map(|_| ())
|
||||
}
|
||||
|
||||
fn none_if_empty(s: String) -> Option<String> {
|
||||
if s.len() == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(s)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_topics(t: ddg::RelatedTopic) -> Vec<ddg::response::TopicResult> {
|
||||
match t {
|
||||
ddg::RelatedTopic::TopicResult(t) => vec![t],
|
||||
ddg::RelatedTopic::Topic(t) => {
|
||||
let mut out = vec![];
|
||||
for subtopic in t.topics {
|
||||
out.append(&mut get_topics(subtopic))
|
||||
}
|
||||
out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
command!(search(_context, message, args) {
|
||||
let query = args.multiple::<String>()?.join(" ");
|
||||
let result = ddg::Query::new(query.as_str(), "autobotrobot").no_html().execute()?;
|
||||
let channel = &message.channel_id;
|
||||
match result.response_type {
|
||||
ddg::Type::Article | ddg::Type::Name => send_search_result(channel, SearchResult {
|
||||
title: query,
|
||||
image: none_if_empty(result.image),
|
||||
text: result.abstract_text,
|
||||
url: none_if_empty(result.abstract_url)
|
||||
})?,
|
||||
ddg::Type::Disambiguation => {
|
||||
for related_topic in result.related_topics {
|
||||
for topic in get_topics(related_topic) {
|
||||
send_search_result(channel, SearchResult {
|
||||
url: none_if_empty(topic.first_url),
|
||||
image: none_if_empty(topic.icon.url),
|
||||
title: query.clone(),
|
||||
text: topic.text
|
||||
})?;
|
||||
}
|
||||
}
|
||||
},
|
||||
ddg::Type::Exclusive => send_search_result(channel, SearchResult {
|
||||
title: query,
|
||||
text: String::from("[see link]"),
|
||||
image: None,
|
||||
url: Some(result.abstract_url)
|
||||
})?,
|
||||
ddg::Type::Nothing => send_error(channel, "No results.")?,
|
||||
other => send_error(channel, &format!("{:?} - unrecognized result type", other))?
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue
Block a user