Skip to content

Commit 7d65f30

Browse files
authored
Merge pull request #27 from tinaun/crate-search
added `?crate` command to search crates.io
2 parents b07ca11 + ac50a31 commit 7d65f30

File tree

5 files changed

+199
-0
lines changed

5 files changed

+199
-0
lines changed

Cargo.lock

Lines changed: 116 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ license = "MIT"
1111
serenity = { version = "0.8.0", features = ["cache", "model"] }
1212
diesel = { version = "1.4.0", features = ["postgres", "r2d2"] }
1313
diesel_migrations = { version = "1.4.0", features = ["postgres"] }
14+
reqwest = { version = "0.10", features = ["blocking", "json"] }
1415
serde = "1.0"
1516
serde_derive = "1.0"
1617
lazy_static = "1.4.0"

src/commands.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::state_machine::{CharacterSet, StateMachine};
2+
use reqwest::blocking::Client as HttpClient;
23
use serenity::{model::channel::Message, prelude::Context};
34
use std::collections::HashMap;
45

@@ -7,19 +8,22 @@ pub(crate) type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
78
pub(crate) type CmdPtr = for<'m> fn(Args<'m>) -> Result<()>;
89

910
pub struct Args<'m> {
11+
pub http: &'m HttpClient,
1012
pub cx: &'m Context,
1113
pub msg: &'m Message,
1214
pub params: HashMap<&'m str, &'m str>,
1315
}
1416

1517
pub(crate) struct Commands {
1618
state_machine: StateMachine,
19+
client: HttpClient,
1720
}
1821

1922
impl Commands {
2023
pub(crate) fn new() -> Self {
2124
Self {
2225
state_machine: StateMachine::new(),
26+
client: HttpClient::new(),
2327
}
2428
}
2529

@@ -64,6 +68,7 @@ impl Commands {
6468
self.state_machine.process(message).map(|matched| {
6569
info!("Executing command {}", message);
6670
let args = Args {
71+
http: &self.client,
6772
cx: &cx,
6873
msg: &msg,
6974
params: matched.params,

src/crates.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use crate::{
2+
api,
3+
commands::{Args, Result},
4+
};
5+
6+
use reqwest::header;
7+
use serde::Deserialize;
8+
9+
const USER_AGENT: &str = "rust-lang/discord-mods-bot";
10+
11+
#[derive(Debug, Deserialize)]
12+
struct Crates {
13+
crates: Vec<Crate>,
14+
}
15+
#[derive(Debug, Deserialize)]
16+
struct Crate {
17+
id: String,
18+
name: String,
19+
#[serde(rename = "newest_version")]
20+
version: String,
21+
#[serde(rename = "updated_at")]
22+
updated: String,
23+
downloads: u64,
24+
description: String,
25+
}
26+
27+
pub fn search(args: Args) -> Result<()> {
28+
let query = args
29+
.params
30+
.get("query")
31+
.ok_or("Unable to retrieve param: query")?;
32+
33+
info!("searching for crate `{}`", query);
34+
35+
let crate_list = args
36+
.http
37+
.get("https://crates.io/api/v1/crates")
38+
.header(header::USER_AGENT, USER_AGENT)
39+
.query(&[("q", query)])
40+
.send()?
41+
.json::<Crates>()?;
42+
43+
if let Some(krate) = crate_list.crates.get(0) {
44+
args.msg.channel_id.send_message(&args.cx, |m| {
45+
m.embed(|e| {
46+
e.title(&krate.name)
47+
.url(format!("https://crates.io/crates/{}", krate.id))
48+
.description(&krate.description)
49+
.field("version", &krate.version, true)
50+
.field("downloads", &krate.downloads, true)
51+
.timestamp(krate.updated.as_str())
52+
});
53+
54+
m
55+
})?;
56+
} else {
57+
let message = "No crates found.";
58+
api::send_reply(&args, message)?;
59+
}
60+
61+
Ok(())
62+
}
63+
64+
/// Print the help message
65+
pub fn help(args: Args) -> Result<()> {
66+
let help_string = "search for a crate on crates.io
67+
```
68+
?crate query...
69+
```";
70+
api::send_reply(&args, &help_string)?;
71+
Ok(())
72+
}

src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ extern crate log;
99

1010
mod api;
1111
mod commands;
12+
mod crates;
1213
mod db;
1314
mod events;
1415
mod schema;
@@ -75,6 +76,10 @@ fn app() -> Result {
7576
cmds.add("?tags get-all", tags::get_all);
7677
cmds.add("?tags help", tags::help);
7778

79+
// crates.io
80+
cmds.add("?crate help", crates::help);
81+
cmds.add("?crate query...", crates::search);
82+
7883
// Slow mode.
7984
// 0 seconds disables slowmode
8085
cmds.add("?slowmode {channel} {seconds}", slow_mode);

0 commit comments

Comments
 (0)