|
1 use curl::easy::{Easy, WriteError}; |
|
2 use curl::Error; |
|
3 use dbus::{BusType, Connection, Message}; |
|
4 use log::{debug, info, warn}; |
|
5 use scraper::{Html, Selector}; |
|
6 use std::fs; |
|
7 use std::str; |
|
8 use std::thread; |
|
9 use std::time; |
|
10 |
|
11 fn inform(url: &str, title: &str, author: &str) { |
|
12 let c = Connection::get_private(BusType::Session).unwrap(); |
|
13 let mut m = Message::new_method_call( |
|
14 "org.kde.konversation", |
|
15 "/irc", |
|
16 "org.kde.konversation", |
|
17 "say", |
|
18 ) |
|
19 .unwrap(); |
|
20 let msg_str = &format!("[{}] {}: {}", url, author, title)[..]; |
|
21 |
|
22 info!("Notification: {}", msg_str); |
|
23 |
|
24 m.append_items(&["freenode".into(), "#hedgewars".into(), msg_str.into()]); |
|
25 let r = c.send(m).unwrap(); |
|
26 } |
|
27 |
|
28 fn handle_page(url: &str, data: &[u8]) -> Result<usize, WriteError> { |
|
29 let page = str::from_utf8(data).unwrap(); |
|
30 let document = Html::parse_document(page); |
|
31 |
|
32 let title_selector = Selector::parse("title").unwrap(); |
|
33 let mut titles = document.select(&title_selector); |
|
34 |
|
35 if let Some(title_str) = titles.next() { |
|
36 let t = &title_str.inner_html(); |
|
37 let title = &t[..t.len() - 12]; |
|
38 //info!("Topic is '{}'", title); |
|
39 |
|
40 let author_selector = Selector::parse("div.forum-post-wrapper div.forum-post-panel-sub div.author-pane div.author-pane-inner div.author-pane-name-status.author-pane-section div.author-pane-line.author-name").unwrap(); |
|
41 let mut authors = document.select(&author_selector); |
|
42 |
|
43 if let Some(author_name) = authors.next() { |
|
44 let author = &author_name.inner_html(); |
|
45 //info!("Author is '{}'", author); |
|
46 |
|
47 inform(url, title, &author[1..author.len() - 1]); |
|
48 } else { |
|
49 warn!("Author not found"); |
|
50 } |
|
51 } else { |
|
52 warn!("No title found"); |
|
53 } |
|
54 |
|
55 Ok(data.len()) |
|
56 } |
|
57 |
|
58 fn query(url: &str) -> Result<(), Error> { |
|
59 let mut easy = Easy::new(); |
|
60 |
|
61 easy.url(url)?; |
|
62 easy.fail_on_error(true); |
|
63 |
|
64 let mut transfer = easy.transfer(); |
|
65 transfer.write_function(|data| handle_page(url, data))?; |
|
66 transfer.perform() |
|
67 } |
|
68 |
|
69 fn main() { |
|
70 stderrlog::new() |
|
71 .verbosity(3) |
|
72 .timestamp(stderrlog::Timestamp::Second) |
|
73 .module(module_path!()) |
|
74 .init() |
|
75 .unwrap(); |
|
76 |
|
77 let short_delay = time::Duration::from_secs(3); |
|
78 let long_delay = time::Duration::from_secs(7 * 60); |
|
79 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(); |
|
81 |
|
82 info!("Starting from node id {}", node_id); |
|
83 |
|
84 loop { |
|
85 debug!("Quering node id {}", node_id); |
|
86 |
|
87 let res = query(&format!("https://www.hedgewars.org/node/{}", node_id)); |
|
88 |
|
89 if let Ok(_) = res { |
|
90 node_id += 1; |
|
91 fs::write(file_name, node_id.to_string()).unwrap(); |
|
92 thread::sleep(short_delay); |
|
93 } else { |
|
94 thread::sleep(long_delay); |
|
95 } |
|
96 } |
|
97 } |