aboutsummaryrefslogtreecommitdiff
path: root/src/feature
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature')
-rw-r--r--src/feature/mod.rs6
-rw-r--r--src/feature/topanime.rs119
2 files changed, 124 insertions, 1 deletions
diff --git a/src/feature/mod.rs b/src/feature/mod.rs
index a52bb2c..b57c179 100644
--- a/src/feature/mod.rs
+++ b/src/feature/mod.rs
@@ -2,9 +2,11 @@ use std::boxed::Box;
2 2
3extern crate telegram_bot; 3extern crate telegram_bot;
4use telegram_bot::{Api, Message}; 4use telegram_bot::{Api, Message};
5extern crate rustc_serialize;
5 6
6pub mod jisoku; 7pub mod jisoku;
7pub mod tasterank; 8pub mod tasterank;
9pub mod topanime;
8 10
9pub enum FeatureResult { 11pub enum FeatureResult {
10 Handled, 12 Handled,
@@ -18,5 +20,7 @@ pub trait Feature {
18} 20}
19 21
20pub fn init() -> Vec<Box<Feature>> { 22pub fn init() -> Vec<Box<Feature>> {
21 vec![Box::new(tasterank::Tasterank::new()), Box::new(jisoku::Jisoku::new())] 23 vec![Box::new(tasterank::Tasterank::new()),
24 Box::new(jisoku::Jisoku::new()),
25 Box::new(topanime::TopAnime::new())]
22} 26}
diff --git a/src/feature/topanime.rs b/src/feature/topanime.rs
new file mode 100644
index 0000000..cccc976
--- /dev/null
+++ b/src/feature/topanime.rs
@@ -0,0 +1,119 @@
1use std::io;
2use std::io::prelude::*;
3use std::fs::File;
4use std::usize;
5
6extern crate telegram_bot;
7use telegram_bot::{Api, Message, MessageType};
8extern crate time;
9extern crate regex;
10use self::regex::Regex;
11use super::rustc_serialize::json;
12
13use feature::FeatureResult;
14use feature::Feature;
15
16#[derive(RustcDecodable)]
17pub struct Anime {
18 name: String,
19 score: f64,
20}
21
22impl Anime {
23 pub fn new(name: &str, score: f64) -> Anime {
24 Anime {
25 name: name.to_owned(),
26 score: score,
27 }
28 }
29}
30
31pub struct TopAnime {
32 animes: Vec<Anime>,
33 last_access: f64,
34}
35
36impl Feature for TopAnime {
37 fn name(&self) -> &'static str {
38 "Tasterank"
39 }
40 fn init(&mut self) {}
41 fn handle(&mut self, a: Api, m: Message) -> Result<FeatureResult, String> {
42 if let MessageType::Text(s) = m.msg {
43 let re = Regex::new(r"(?i)luggas top ([0-9]{1,3}) anime").unwrap();
44 let cap = re.captures(&s);
45 let s_num = match cap {
46 Some(s) => s.at(1),
47 None => return Ok(FeatureResult::Skip),
48 };
49 let s_num = match s_num {
50 Some(s) => s,
51 None => return Ok(FeatureResult::Skip),
52 };
53
54 // parse to int
55 let num = match s_num.parse::<i32>() {
56 Ok(n) => n,
57 Err(e) => {
58 println!("{}", e);
59 return Ok(FeatureResult::Skip);
60 }
61 };
62 let start = time::precise_time_ns();
63 if let Err(e) = self.update_animes() {
64 println!("{}", e);
65 return Ok(FeatureResult::Skip);
66 }
67 println!("(benchm) updating animes: {}ms",
68 (time::precise_time_ns() - start) / 1000000);
69
70 let mut msg = String::new();
71 for i in 0..num {
72 let i = i as usize;
73 if self.animes.len() <= i {
74 break;
75 }
76 msg.push_str(&format!("{}. {} ({}%)\n",
77 i + 1,
78 self.animes[i].name,
79 self.animes[i].score));
80 }
81 println!("(benchm) anime before send: {}ms",
82 (time::precise_time_ns() - start) / 1000000);
83 if let Err(e) = a.send_message(m.chat.id(), msg, None, None, Some(m.message_id), None) {
84 println!("{}", e);
85 }
86 println!("(benchm) anime: {}ms",
87 (time::precise_time_ns() - start) / 1000000);
88 return Ok(FeatureResult::Handled);
89 }
90 Ok(FeatureResult::Skip)
91 }
92}
93
94impl TopAnime {
95 pub fn new() -> TopAnime {
96 let mut t = TopAnime {
97 animes: vec![],
98 last_access: 0f64,
99 };
100 t.init();
101 t
102 }
103 fn update_animes(&mut self) -> Result<(), io::Error> {
104 let now = time::precise_time_s();
105 if now - self.last_access < 3600.0f64 {
106 return Ok(());
107 }
108 let mut f = try!(File::open("data/animescore.json"));
109 let mut buf = String::new();
110 try!(f.read_to_string(&mut buf));
111 let v: Vec<Anime> = match json::decode(&buf) {
112 Ok(v) => v,
113 Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, format!("{}", e))),
114 };
115 self.animes = v;
116 self.last_access = now;
117 Ok(())
118 }
119}