M .gitignore => .gitignore +1 -0
@@ 1,1 1,2 @@
/target
+.env
M Cargo.lock => Cargo.lock +16 -0
@@ 18,6 18,12 @@ dependencies = [
]
[[package]]
+name = "anyhow"
+version = "1.0.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
+
+[[package]]
name = "async-trait"
version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 206,6 212,12 @@ dependencies = [
]
[[package]]
+name = "dotenv"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
+
+[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1125,8 1137,12 @@ dependencies = [
name = "sistemer-bot"
version = "0.1.0"
dependencies = [
+ "anyhow",
+ "dotenv",
"log",
"pretty_env_logger",
+ "regex",
+ "reqwest",
"teloxide",
"tokio",
]
M Cargo.toml => Cargo.toml +4 -0
@@ 10,3 10,7 @@ teloxide = { version = "0.5", features = ["auto-send", "macros"] }
log = "0.4"
pretty_env_logger = "0.4.0"
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
+dotenv = "0.15"
+reqwest = "0.11"
+anyhow = "1.0"
+regex = "1.5"
M flake.nix => flake.nix +10 -6
@@ 12,19 12,21 @@
outputs = { self, nixpkgs, flake-utils, naersk }:
flake-utils.lib.eachDefaultSystem (system:
let
+ name = "sistemer-bot";
pkgs = nixpkgs.legacyPackages.${system};
naersk-lib = naersk.lib."${system}";
in rec {
- packages.backend-uget = naersk-lib.buildPackage {
- pname = "sistemerb-bot";
+ packages.${name} = naersk-lib.buildPackage {
+ pname = name;
+ buildInputs = with pkgs; [ openssl pkg-config ];
root = ./.;
};
- defaultPackage = packages.sistemer-bot;
+ defaultPackage = packages.${name};
- apps.backend-uget = flake-utils.lib.mkApp {
- drv = packages.sistemer-bot;
+ apps.${name} = flake-utils.lib.mkApp {
+ drv = packages.${name};
};
- defaultApp = apps.sistemer-bot;
+ defaultApp = apps.${name};
devShell = pkgs.mkShell {
buildInputs = with pkgs;
@@ 34,6 36,8 @@
rust-analyzer
rustfmt
clippy
+ pkgconfig
+ openssl
];
};
});
A src/disciplina.rs => src/disciplina.rs +53 -0
@@ 0,0 1,53 @@
+use anyhow::Result;
+use regex::Regex;
+
+fn sanitize_line(line: &str) -> Result<String> {
+ log::info!("Transformando {:?}", line);
+
+ let line = format!("{}\n", line);
+ // Replace headers with <b>
+ let line = Regex::new("h\\d")?.replace_all(&line, "b");
+ // Remove <ul> entire lines
+ let line = Regex::new("^ *</?ul>\n")?.replace_all(&line, "");
+ let line = Regex::new("</?ul>")?.replace_all(&line, "");
+ // Remove <li>
+ let line = Regex::new("^ *</?li>\n")?.replace_all(&line, "");
+ let line = Regex::new("</?li>")?.replace_all(&line, "");
+ // Remove <p>
+ let line = Regex::new("</?p>")?.replace_all(&line, "");
+ // Remove email links
+ let line = Regex::new("<a href=\"mailto:.*>(.*)</a>")?.replace(&line, "$1");
+
+ log::info!("Em: {:?}", line);
+
+ Ok(line.into())
+}
+
+pub async fn get_disciplina(disciplina: &str) -> Result<String> {
+ let fulltext = reqwest::get("https://misterio.me/notes/bsi/disciplinas-2021-2.html")
+ .await?
+ .text()
+ .await?;
+
+ let start_pattern = Regex::new(&format!("<h2.*>.*{}.*</h2>", disciplina))?;
+ let stop_pattern = Regex::new("<hr />")?;
+
+ let mut output: String = "".into();
+ let mut adding = false;
+ for line in fulltext.lines() {
+ if start_pattern.is_match(line) {
+ log::info!("Iniciando escrita");
+ output.push_str(&sanitize_line(line)?);
+ adding = true;
+ } else if adding {
+ if stop_pattern.is_match(line) {
+ log::info!("Finalizando escrita:\n{}", output);
+ return Ok(output);
+ } else {
+ output.push_str(&sanitize_line(line)?);
+ }
+ }
+ }
+
+ Ok("Disciplina não encontrada!".into())
+}
A src/lib.rs => src/lib.rs +1 -0
@@ 0,0 1,1 @@
+pub mod disciplina;
M src/main.rs => src/main.rs +44 -2
@@ 1,3 1,45 @@
-fn main() {
- println!("Hello, world!");
+use teloxide::prelude::*;
+use teloxide::types::ParseMode::Html;
+use teloxide::utils::command::BotCommand;
+
+use anyhow::Result;
+use dotenv::dotenv;
+
+use sistemer_bot::disciplina;
+
+#[derive(BotCommand)]
+#[command(rename = "lowercase", description = "These commands are supported:")]
+enum Command {
+ #[command(description = "exibe essa ajuda.")]
+ Help,
+ #[command(description = "mostra info de uma disciplina.")]
+ Disciplina(String),
+}
+
+async fn answer(cx: UpdateWithCx<AutoSend<Bot>, Message>, command: Command) -> Result<()> {
+ match command {
+ Command::Help => cx.answer(Command::descriptions()).await?,
+ Command::Disciplina(disciplina) => {
+ cx.answer(disciplina::get_disciplina(&disciplina).await?)
+ .parse_mode(Html)
+ .await?
+ }
+ };
+
+ Ok(())
+}
+
+async fn run() {
+ teloxide::enable_logging!();
+
+ let bot = Bot::from_env().auto_send();
+ let bot_name: String = "Sistemer Bot".into();
+
+ teloxide::commands_repl(bot, bot_name, answer).await;
+}
+
+#[tokio::main]
+async fn main() {
+ dotenv().ok();
+ run().await;
}