forum_notifier/src/main.rs
author unC0Rr
Sun, 07 Apr 2019 23:20:41 +0200
changeset 0 5696442fee1c
child 1 52bbcfcbd850
permissions -rw-r--r--
Add new forum topics notificator

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);
        }
    }
}