6 use std::fs; |
6 use std::fs; |
7 use std::str; |
7 use std::str; |
8 use std::thread; |
8 use std::thread; |
9 use std::time; |
9 use std::time; |
10 |
10 |
11 fn inform(url: &str, title: &str, author: &str) { |
11 struct StateInfo { |
|
12 url: String, |
|
13 previous_title: String, |
|
14 previous_author: String, |
|
15 } |
|
16 |
|
17 fn inform(state: &mut StateInfo, title: &str, author: &str) { |
|
18 if state.previous_title == title && state.previous_author == author { |
|
19 return; |
|
20 } |
|
21 |
|
22 state.previous_title = title.to_string(); |
|
23 state.previous_author = author.to_string(); |
|
24 |
12 let c = Connection::get_private(BusType::Session).unwrap(); |
25 let c = Connection::get_private(BusType::Session).unwrap(); |
13 let mut m = Message::new_method_call( |
26 let mut m = Message::new_method_call( |
14 "org.kde.konversation", |
27 "org.kde.konversation", |
15 "/irc", |
28 "/irc", |
16 "org.kde.konversation", |
29 "org.kde.konversation", |
17 "say", |
30 "say", |
18 ) |
31 ) |
19 .unwrap(); |
32 .unwrap(); |
20 let msg_str = &format!("[{}] {}: {}", url, author, title)[..]; |
33 let msg_str = &format!("[{}] {}: {}", state.url, author, title)[..]; |
21 |
34 |
22 info!("Notification: {}", msg_str); |
35 info!("Notification: {}", msg_str); |
23 |
36 |
24 m.append_items(&["freenode".into(), "#hedgewars".into(), msg_str.into()]); |
37 m.append_items(&["freenode".into(), "#hedgewars".into(), msg_str.into()]); |
25 let r = c.send(m).unwrap(); |
38 let _r = c.send(m).unwrap(); |
26 } |
39 } |
27 |
40 |
28 fn handle_page(url: &str, data: &[u8]) -> Result<usize, WriteError> { |
41 fn handle_page(state: &mut StateInfo, data: &[u8]) -> Result<usize, WriteError> { |
29 let page = str::from_utf8(data).unwrap(); |
42 let page = str::from_utf8(data).unwrap(); |
30 let document = Html::parse_document(page); |
43 let document = Html::parse_document(page); |
31 |
44 |
32 let title_selector = Selector::parse("title").unwrap(); |
45 let title_selector = Selector::parse("title").unwrap(); |
33 let mut titles = document.select(&title_selector); |
46 let mut titles = document.select(&title_selector); |
42 |
55 |
43 if let Some(author_name) = authors.next() { |
56 if let Some(author_name) = authors.next() { |
44 let author = &author_name.inner_html(); |
57 let author = &author_name.inner_html(); |
45 //info!("Author is '{}'", author); |
58 //info!("Author is '{}'", author); |
46 |
59 |
47 inform(url, title, &author[1..author.len() - 1]); |
60 inform(state, title, &author[1..author.len() - 1]); |
48 } else { |
61 } else { |
49 warn!("Author not found"); |
62 warn!("Author not found"); |
50 } |
63 } |
51 } else { |
64 } else { |
52 warn!("No title found"); |
65 warn!("No title found"); |
53 } |
66 } |
54 |
67 |
55 Ok(data.len()) |
68 Ok(data.len()) |
56 } |
69 } |
57 |
70 |
58 fn query(url: &str) -> Result<(), Error> { |
71 fn query(state: &mut StateInfo) -> Result<(), Error> { |
59 let mut easy = Easy::new(); |
72 let mut easy = Easy::new(); |
60 |
73 |
61 easy.url(url)?; |
74 easy.url(&state.url)?; |
62 easy.fail_on_error(true); |
75 easy.fail_on_error(true)?; |
63 |
76 |
64 let mut transfer = easy.transfer(); |
77 let mut transfer = easy.transfer(); |
65 transfer.write_function(|data| handle_page(url, data))?; |
78 transfer.write_function(|data| handle_page(state, data))?; |
66 transfer.perform() |
79 transfer.perform() |
67 } |
80 } |
68 |
81 |
69 fn main() { |
82 fn main() { |
70 stderrlog::new() |
83 stderrlog::new() |
73 .module(module_path!()) |
86 .module(module_path!()) |
74 .init() |
87 .init() |
75 .unwrap(); |
88 .unwrap(); |
76 |
89 |
77 let short_delay = time::Duration::from_secs(3); |
90 let short_delay = time::Duration::from_secs(3); |
78 let long_delay = time::Duration::from_secs(7 * 60); |
91 let long_delay = time::Duration::from_secs(100); |
79 let file_name = "/usr/home/unC0Rr/.local/unC0Rr/forumchecker/node.txt"; |
92 let file_name = "/usr/home/unC0Rr/.local/unC0Rr/forumchecker/node.txt"; |
80 let mut node_id: u32 = fs::read_to_string(file_name).unwrap().parse().unwrap(); |
93 let mut node_id: u32 = fs::read_to_string(file_name).unwrap().parse().unwrap(); |
|
94 let mut known_good_id: Option<u32> = None; |
|
95 let mut shift: u32 = 0; |
|
96 |
|
97 let mut state = StateInfo { |
|
98 url: String::new(), |
|
99 previous_title: String::new(), |
|
100 previous_author: String::new() |
|
101 }; |
81 |
102 |
82 info!("Starting from node id {}", node_id); |
103 info!("Starting from node id {}", node_id); |
83 |
104 |
84 loop { |
105 loop { |
85 debug!("Quering node id {}", node_id); |
106 let try_id = node_id + shift; |
86 |
107 |
87 let res = query(&format!("https://www.hedgewars.org/node/{}", node_id)); |
108 debug!("Quering node id {}", try_id); |
|
109 |
|
110 thread::sleep(short_delay); |
|
111 |
|
112 state.url = format!("https://www.hedgewars.org/node/{}", try_id); |
|
113 |
|
114 let res = query(&mut state); |
88 |
115 |
89 if let Ok(_) = res { |
116 if let Ok(_) = res { |
90 node_id += 1; |
117 if shift > 0 && known_good_id == None { |
91 fs::write(file_name, node_id.to_string()).unwrap(); |
118 known_good_id = Some(try_id); |
92 thread::sleep(short_delay); |
119 shift = 0; |
|
120 } else { |
|
121 node_id = try_id + 1; |
|
122 if Some(node_id) == known_good_id { |
|
123 node_id += 1; |
|
124 known_good_id = None; |
|
125 } |
|
126 shift = 0; |
|
127 fs::write(file_name, node_id.to_string()).unwrap(); |
|
128 } |
93 } else { |
129 } else { |
94 thread::sleep(long_delay); |
130 if known_good_id == None { |
|
131 shift = (shift + 1) % 11; |
|
132 thread::sleep(long_delay); |
|
133 } else if Some(try_id + 1) == known_good_id { |
|
134 node_id = known_good_id.unwrap() + 1; |
|
135 known_good_id = None; |
|
136 shift = 0; |
|
137 fs::write(file_name, node_id.to_string()).unwrap(); |
|
138 } else { |
|
139 shift += 1; |
|
140 } |
95 } |
141 } |
96 } |
142 } |
97 } |
143 } |