aboutsummaryrefslogtreecommitdiff
path: root/examples/08_search/src/main.rs
blob: c4c923054b0e150d506786be2a2a1fc82c6da275 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Requires the "cache", "methods", and "voice" features be enabled in your
//! Cargo.toml, like so:
//!
//! ```toml
//! [dependencies.serenity]
//! version = "*"
//! features = ["cache", "framework"]
//! ```
//!
//! Note that - due to bot users not being able to search - this example may
//! only be run under a user account.
//!
//! This particular example will automatically ensure that only the current user
//! may search; this acts as a "selfbot".

#[macro_use]
extern crate serenity;

use serenity::client::{CACHE, Client, Context};
use serenity::model::Message;
use serenity::utils::builder::{SortingMode, SortingOrder};
use std::env;

fn main() {
    let mut client = Client::login_user(&env::var("DISCORD_TOKEN").unwrap());

    client.with_framework(|f| f
        .configure(|c| c.prefix("~").on_mention(true))
        .command("search", |c| c
            .exec(search)
            .check(self_check)));

    client.on_ready(|_context, ready| {
        println!("{} is connected!", ready.user.name);
    });

    if let Err(why) = client.start() {
        println!("Client error: {:?}", why);
    }
}

fn self_check(_context: &mut Context, message: &Message) -> bool {
    message.author.id == CACHE.read().unwrap().user.id
}

command!(search(context, message, args) {
    let query = args.join(" ");

    if query.is_empty() {
        let _ = context.say("You must provide a query");

        return Ok(());
    }

    let guild_id = match message.guild_id() {
        Some(guild_id) => guild_id,
        None => {
            let _ = context.say("Only supports guilds");

            return Ok(());
        },
    };

    let channel_ids = {
        let cache = CACHE.read().unwrap();

        let guild = match cache.get_guild(guild_id) {
            Some(guild) => guild,
            None => {
                let _ = context.say("Guild data not found");

                return Ok(());
            },
        };

        let channel_ids = guild.read().unwrap()
            .channels
            .values()
            .filter(|c| c.read().unwrap().name.starts_with("search-"))
            .map(|c| c.read().unwrap().id)
            .collect::<Vec<_>>();

        channel_ids.clone()
    };

    let search = guild_id.search_channels(&channel_ids, |s| s
        .content(&query)
        .context_size(0)
        .has_attachment(true)
        .has_embed(true)
        .max_id(message.id.0 - 1)
        .sort_by(SortingMode::Timestamp)
        .sort_order(SortingOrder::Descending));

    let messages = match search {
        Ok(messages) => messages,
        Err(why) => {
            println!("Error performing search '{}': {:?}", query, why);

            let _ = context.say("Error occurred while searching");

            return Ok(());
        },
    };

    let _ = context.send_message(|m| m
        .content(&format!("Found {} total results", messages.total))
        .embed(move |mut e| {
            for (i, mut messages) in messages.results.into_iter().enumerate() {
                let mut message = &mut messages[0];
                message.content.truncate(1000);

                e = e.field(|f| f
                    .name(&format!("Result {}", i))
                    .value(&message.content));
            }

            e
        }));
});