--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore Sun Apr 07 23:20:41 2019 +0200
@@ -0,0 +1,4 @@
+syntax: glob
+forum_notifier/target
+*.lock
+.idea
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/forum_notifier/Cargo.toml Sun Apr 07 23:20:41 2019 +0200
@@ -0,0 +1,12 @@
+[package]
+name = "forum_notifier"
+version = "0.1.0"
+authors = ["Andrey Korotaev <a.korotaev@hedgewars.org>"]
+edition = "2018"
+
+[dependencies]
+curl = "0.4.20"
+log = "0.4.6"
+stderrlog = "0.4.1"
+scraper = "0.9.2"
+dbus = "0.6.4"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/forum_notifier/src/main.rs Sun Apr 07 23:20:41 2019 +0200
@@ -0,0 +1,97 @@
+use curl::easy::{Easy, WriteError};
+use curl::Error;
+use dbus::{BusType, Connection, Message};
+use log::{debug, info, warn};
+use scraper::{Html, Selector};
+use std::fs;
+use std::str;
+use std::thread;
+use std::time;
+
+fn inform(url: &str, title: &str, author: &str) {
+ let c = Connection::get_private(BusType::Session).unwrap();
+ let mut m = Message::new_method_call(
+ "org.kde.konversation",
+ "/irc",
+ "org.kde.konversation",
+ "say",
+ )
+ .unwrap();
+ let msg_str = &format!("[{}] {}: {}", url, author, title)[..];
+
+ info!("Notification: {}", msg_str);
+
+ m.append_items(&["freenode".into(), "#hedgewars".into(), msg_str.into()]);
+ let r = c.send(m).unwrap();
+}
+
+fn handle_page(url: &str, data: &[u8]) -> Result<usize, WriteError> {
+ let page = str::from_utf8(data).unwrap();
+ let document = Html::parse_document(page);
+
+ let title_selector = Selector::parse("title").unwrap();
+ let mut titles = document.select(&title_selector);
+
+ if let Some(title_str) = titles.next() {
+ let t = &title_str.inner_html();
+ let title = &t[..t.len() - 12];
+ //info!("Topic is '{}'", title);
+
+ 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();
+ let mut authors = document.select(&author_selector);
+
+ if let Some(author_name) = authors.next() {
+ let author = &author_name.inner_html();
+ //info!("Author is '{}'", author);
+
+ inform(url, title, &author[1..author.len() - 1]);
+ } else {
+ warn!("Author not found");
+ }
+ } else {
+ warn!("No title found");
+ }
+
+ Ok(data.len())
+}
+
+fn query(url: &str) -> Result<(), Error> {
+ let mut easy = Easy::new();
+
+ easy.url(url)?;
+ easy.fail_on_error(true);
+
+ let mut transfer = easy.transfer();
+ transfer.write_function(|data| handle_page(url, data))?;
+ transfer.perform()
+}
+
+fn main() {
+ stderrlog::new()
+ .verbosity(3)
+ .timestamp(stderrlog::Timestamp::Second)
+ .module(module_path!())
+ .init()
+ .unwrap();
+
+ let short_delay = time::Duration::from_secs(3);
+ let long_delay = time::Duration::from_secs(7 * 60);
+ let file_name = "/usr/home/unC0Rr/.local/unC0Rr/forumchecker/node.txt";
+ let mut node_id: u32 = fs::read_to_string(file_name).unwrap().parse().unwrap();
+
+ info!("Starting from node id {}", node_id);
+
+ loop {
+ debug!("Quering node id {}", node_id);
+
+ let res = query(&format!("https://www.hedgewars.org/node/{}", node_id));
+
+ if let Ok(_) = res {
+ node_id += 1;
+ fs::write(file_name, node_id.to_string()).unwrap();
+ thread::sleep(short_delay);
+ } else {
+ thread::sleep(long_delay);
+ }
+ }
+}