Word save feature.

This commit is contained in:
AB
2020-12-06 23:55:09 +03:00
parent b6f5228ce8
commit 7e57e8f706
11 changed files with 2252 additions and 116 deletions

BIN
..gitignore.un~ Normal file

Binary file not shown.

7
.gitignore~ Normal file
View File

@ -0,0 +1,7 @@
/target
memory.sqlite3
/doc
/photo
/sticker
/video
/voice

1975
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -28,4 +28,6 @@ uuid = { version = "0.8", features = ["v4"] }
sha1 = "*"
env_logger = "0.7"
log = { version = "^0.4.5", features = ["std"] }
subprocess = "0.2.6"
ascii = "1.0.0"
serde_json = "1.0"

View File

@ -1,51 +1,109 @@
CREATE TABLE `word` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`word` TEXT UNIQUE
--
-- File generated with SQLiteStudio v3.2.1 on Sun Dec 6 13:46:57 2020
--
-- Text encoding used: System
--
PRAGMA foreign_keys = off;
BEGIN TRANSACTION;
-- Table: alert
CREATE TABLE IF NOT EXISTS alert (
conf_id TEXT NOT NULL,
user_id TEXT NOT NULL,
created TEXT NOT NULL,
time TEXT NOT NULL,
message TEXT
);
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE `user` (
`id` INTEGER NOT NULL UNIQUE,
`username` TEXT NOT NULL,
`first_name` INTEGER NOT NULL,
`last_name` INTEGER NOT NULL,
`date` INTEGER NOT NULL,
PRIMARY KEY(`id`)
-- Table: conf
CREATE TABLE IF NOT EXISTS conf (
id NUMERIC NOT NULL
UNIQUE,
title TEXT,
date INTEGER NOT NULL,
PRIMARY KEY (
id
)
);
CREATE TABLE `conf` (
`id` NUMERIC NOT NULL UNIQUE,
`title` TEXT,
`date` INTEGER NOT NULL,
PRIMARY KEY(`id`)
-- Table: file
CREATE TABLE IF NOT EXISTS file (
path TEXT NOT NULL,
user_id TEXT NOT NULL,
conf_id TEXT NOT NULL,
file_id STRING PRIMARY KEY
);
CREATE TABLE `file` (
`path` TEXT NOT NULL UNIQUE,
`user_id` TEXT NOT NULL,
`conf_id` TEXT NOT NULL,
PRIMARY KEY(`path`)
-- Table: relations
CREATE TABLE IF NOT EXISTS relations (
id INTEGER NOT NULL
PRIMARY KEY AUTOINCREMENT,
word_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
conf_id INTEGER NOT NULL,
date INTEGER NOT NULL,
msg_id INTEGER,
FOREIGN KEY (
word_id
)
REFERENCES word (id) ON DELETE CASCADE,
FOREIGN KEY (
user_id
)
REFERENCES user (id),
FOREIGN KEY (
conf_id
)
REFERENCES conf (id)
);
CREATE TABLE IF NOT EXISTS "relations" (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`word_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL,
`conf_id` INTEGER NOT NULL,
`date` INTEGER NOT NULL, `msg_id` INTEGER NULL,
FOREIGN KEY(`word_id`) REFERENCES `word`(`id`) ON DELETE CASCADE,
FOREIGN KEY(`user_id`) REFERENCES `user`(`id`),
FOREIGN KEY(`conf_id`) REFERENCES `conf`(`id`)
-- Table: reset
CREATE TABLE IF NOT EXISTS reset (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
conf_id INTEGER,
date INTEGER,
relation_id INTEGER,
FOREIGN KEY (
user_id
)
REFERENCES user (id)
);
CREATE TABLE `reset` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`user_id` INTEGER,
`conf_id` INTEGER,
`date` INTEGER,
`relation_id` INTEGER,
FOREIGN KEY(`user_id`) REFERENCES `user`(`id`)
-- Table: user
CREATE TABLE IF NOT EXISTS user (
id INTEGER NOT NULL
UNIQUE,
username TEXT,
first_name INTEGER NOT NULL,
last_name INTEGER,
date INTEGER NOT NULL,
PRIMARY KEY (
id
)
ON CONFLICT REPLACE
);
CREATE TABLE `alert` (
`conf_id`TEXT NOT NULL,
`user_id`TEXT NOT NULL,
`created`TEXT NOT NULL,
`time`TEXT NOT NULL,
`message`TEXT
-- Table: word
CREATE TABLE IF NOT EXISTS word (
id INTEGER PRIMARY KEY AUTOINCREMENT,
word TEXT UNIQUE
);
CREATE TABLE `xxx_message` (`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `text`TEXT UNIQUE NULL);
-- Table: xxx_message
CREATE TABLE IF NOT EXISTS xxx_message (
id INTEGER NOT NULL
PRIMARY KEY AUTOINCREMENT,
text TEXT UNIQUE
);
COMMIT TRANSACTION;
PRAGMA foreign_keys = on;

BIN
mystem.exe Normal file

Binary file not shown.

View File

@ -7,7 +7,7 @@ use tokio::time::delay_for;
pub(crate) async fn here(api: Api, message: Message) -> Result<(), Error> {
let members: Vec<telegram_bot::User> = db::get_members(message.chat.id()).unwrap();
for u in &members {
println!("Found user {:?}", u);
debug!("Found user {:?}", u);
}
let mut msg = "<b>I summon you</b>, ".to_string();
for user in members {
@ -21,10 +21,11 @@ pub(crate) async fn here(api: Api, message: Message) -> Result<(), Error> {
};
msg = format!("{} {}", msg, mention);
}
println!("Message: {:?}", msg);
api.send(message.text_reply(msg).parse_mode(ParseMode::Html))
.await?;
match api.send(message.text_reply(msg).parse_mode(ParseMode::Html)).await {
Ok(_) => debug!("@here command sent to {}", message.from.id),
Err(_) => warn!("@here command sent failed to {}", message.from.id),
}
//api.send(message.chat.text("Text to message chat")).await?;
//api.send(message.from.text("Private text")).await?;
Ok(())

157
src/db.rs
View File

@ -272,60 +272,121 @@ pub(crate) async fn get_file(file_id: String) -> Result<(), errors::Error> {
}
async fn add_word(word: String) -> Result<(), errors::Error> {
let conn = open()?;
conn.execute_named("INSERT OR IGNORE INTO word('word') VALUES (:word)", &[(":word", &word)]);
debug!("Added word {}", word);
Ok(())
}
pub(crate) async fn add_sentence(message: &telegram_bot::Message) -> Result<(), errors::Error> {
let words = utils::stemming(message).await?;
//let conn = open()?;
for word in words {
add_word(word).await?;
}
Ok(())
}
// SCHEME
static scheme: &str = "
CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);
CREATE TABLE IF NOT EXISTS `word` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`word` TEXT UNIQUE
PRAGMA foreign_keys = off;
BEGIN TRANSACTION;
-- Table: alert
CREATE TABLE IF NOT EXISTS alert (
conf_id TEXT NOT NULL,
user_id TEXT NOT NULL,
created TEXT NOT NULL,
time TEXT NOT NULL,
message TEXT
);
CREATE TABLE IF NOT EXISTS user (
`id` INTEGER NOT NULL UNIQUE,
`username` TEXT NOT NULL,
`first_name` INTEGER NOT NULL,
`last_name` INTEGER NOT NULL,
`date` INTEGER NOT NULL,
PRIMARY KEY(`id`)
-- Table: conf
CREATE TABLE IF NOT EXISTS conf (
id NUMERIC NOT NULL
UNIQUE,
title TEXT,
date INTEGER NOT NULL,
PRIMARY KEY (
id
)
);
CREATE TABLE IF NOT EXISTS `conf` (
`id` NUMERIC NOT NULL UNIQUE,
`title` TEXT,
`date` INTEGER NOT NULL,
PRIMARY KEY(`id`)
);
CREATE TABLE IF NOT EXISTS `file` (
`path` TEXT NOT NULL UNIQUE,
`user_id` TEXT NOT NULL,
`conf_id` TEXT NOT NULL,
PRIMARY KEY(`path`)
-- Table: file
CREATE TABLE IF NOT EXISTS file (
path TEXT NOT NULL,
user_id TEXT NOT NULL,
conf_id TEXT NOT NULL,
file_id STRING PRIMARY KEY
);
-- Table: relations
CREATE TABLE IF NOT EXISTS relations (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`word_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL,
`conf_id` INTEGER NOT NULL,
`date` INTEGER NOT NULL, `msg_id` INTEGER NULL,
FOREIGN KEY(`word_id`) REFERENCES `word`(`id`) ON DELETE CASCADE,
FOREIGN KEY(`user_id`) REFERENCES `user`(`id`),
FOREIGN KEY(`conf_id`) REFERENCES `conf`(`id`)
id INTEGER NOT NULL
PRIMARY KEY AUTOINCREMENT,
word_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
conf_id INTEGER NOT NULL,
date INTEGER NOT NULL,
msg_id INTEGER,
FOREIGN KEY (
word_id
)
REFERENCES word (id) ON DELETE CASCADE,
FOREIGN KEY (
user_id
)
REFERENCES user (id),
FOREIGN KEY (
conf_id
)
REFERENCES conf (id)
);
CREATE TABLE IF NOT EXISTS `reset` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`user_id` INTEGER,
`conf_id` INTEGER,
`date` INTEGER,
`relation_id` INTEGER,
FOREIGN KEY(`user_id`) REFERENCES `user`(`id`)
-- Table: reset
CREATE TABLE IF NOT EXISTS reset (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
conf_id INTEGER,
date INTEGER,
relation_id INTEGER,
FOREIGN KEY (
user_id
)
REFERENCES user (id)
);
CREATE TABLE IF NOT EXISTS `alert` (
`conf_id`TEXT NOT NULL,
`user_id`TEXT NOT NULL,
`created`TEXT NOT NULL,
`time`TEXT NOT NULL,
`message`TEXT
-- Table: user
CREATE TABLE IF NOT EXISTS user (
id INTEGER NOT NULL
UNIQUE,
username TEXT,
first_name INTEGER NOT NULL,
last_name INTEGER,
date INTEGER NOT NULL,
PRIMARY KEY (
id
)
ON CONFLICT REPLACE
);
CREATE TABLE IF NOT EXISTS `xxx_message` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`text`TEXT UNIQUE NULL
);
";
-- Table: word
CREATE TABLE IF NOT EXISTS word (
id INTEGER PRIMARY KEY AUTOINCREMENT,
word TEXT UNIQUE
);
-- Table: xxx_message
CREATE TABLE IF NOT EXISTS xxx_message (
id INTEGER NOT NULL
PRIMARY KEY AUTOINCREMENT,
text TEXT UNIQUE
);
COMMIT TRANSACTION;
PRAGMA foreign_keys = on;
";

View File

@ -3,6 +3,7 @@ use rusqlite::Error as sqlite_error;
use rusqlite::{named_params, params, Connection, Result};
use std::{fmt, io, io::Error as io_error};
use telegram_bot::Error as tg_error;
use serde_json::Error as serde_error;
#[derive(Debug)]
pub(crate) enum Error {
@ -13,6 +14,7 @@ pub(crate) enum Error {
ConfNotFound,
IOError(io_error),
FileNotFound,
JsonParseError(serde_error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -42,4 +44,10 @@ impl From<io_error> for Error {
fn from(e: io_error) -> Error {
return Error::IOError(e);
}
}
}
impl From<serde_error> for Error {
fn from(e: serde_error) -> Error {
return Error::JsonParseError(e);
}
}

View File

@ -1,4 +1,4 @@
use std::{env,process};
use std::{env, process};
use futures::StreamExt;
use reqwest;
@ -17,7 +17,6 @@ async fn handler(api: Api, message: Message, token: String) -> Result<(), errors
match message.kind {
MessageKind::Text { ref data, .. } => {
let title = utils::get_title(&message);
info!(
"<{}({})>[{}({})]: {}",
&message.chat.id(),
@ -26,6 +25,7 @@ async fn handler(api: Api, message: Message, token: String) -> Result<(), errors
&message.from.first_name,
data
);
db::add_sentence(&message).await?;
match data.as_str() {
"/here" => commands::here(api, message).await?,
_ => (),
@ -58,14 +58,7 @@ async fn handler(api: Api, message: Message, token: String) -> Result<(), errors
&message.from.first_name,
caption.clone().unwrap_or("NO_TITLE".to_string())
);
/*match utils::get_files(api, message, token).await {
Ok(count) => println!("Got {} files successfully.", count),
Err(e) => println!("Couldn't get files: {:?}", e)
}
*/
utils::get_files(api, message, token).await?;
}
MessageKind::Sticker { ref data, .. } => {
@ -129,7 +122,7 @@ async fn main() -> Result<(), errors::Error> {
Err(_) => {
error!("TELEGRAM_BOT_TOKEN not set");
process::exit(0x0001);
},
}
};
let api = Api::new(token.clone());

View File

@ -1,6 +1,6 @@
use reqwest::Client;
use sha1::Sha1;
use std::fs::{File,create_dir as fs_create_dir};
use std::fs::{create_dir as fs_create_dir, File};
use std::io::prelude::*;
use std::path::Path;
use std::{env, io};
@ -10,6 +10,16 @@ use uuid::Uuid;
use crate::db;
use crate::errors;
extern crate reqwest;
use ascii::AsciiChar::{LineFeed, EOT};
use subprocess::{Exec, Popen, PopenConfig, Redirection};
use serde_json::Value;
//use serde::{Deserialize, Serialize};
//#[derive(Serialize, Deserialize)]
struct StemWord {
}
pub(crate) fn get_title(message: &Message) -> String {
match &message.chat {
@ -21,16 +31,12 @@ pub(crate) fn get_title(message: &Message) -> String {
}
pub(crate) async fn create_dir(dir: &String) -> () {
info!("Going to create dir");
match fs_create_dir(dir) {
Ok(_) => info!("Dir {} created.", dir),
Err(_) => info!("Dir {} create error.", dir),
Err(_) => (),
}
info!("Going to create dir");
}
pub(crate) async fn get_files(
api: Api,
message: Message,
@ -79,7 +85,7 @@ pub(crate) async fn get_files(
let file_hash = hasher.digest().to_string();
match db::get_file(file_hash.clone()).await {
Ok(_) => {
info!("File {} exist", file_hash);
debug!("File {} exist", file_hash);
}
Err(_) => {
let mut dest = File::create(path.clone())?;
@ -88,9 +94,34 @@ pub(crate) async fn get_files(
};
db::add_file(&message, path, file_hash).await?;
}
Err(e) => warn!("Couldn't get file: {}", e)
Err(e) => warn!("Couldn't get file: {}", e),
}
}
};
Ok(file_count)
}
pub(crate) async fn stemming(message: &Message) -> Result<Vec<String>, errors::Error> {
let mut words: Vec<String> = vec![];
let proc = Exec::shell("mystem -d --format json -l");
match proc
.stdin(message.text().unwrap().as_str())
.communicate()
.unwrap()
.read_string()
.unwrap()
.0
{
Some(line) => {
let mut v: Vec<Value> = serde_json::from_str(line.as_str())?;
for i in v {
words.push(i["analysis"][0]["lex"].to_string().replace("\"", ""));
}
words.retain(|x| x != "null");
info!("{:?}", words);
}
None => return Ok(vec![]),
};
Ok(words)
}