mirror of
https://github.com/house-of-vanity/desubot.git
synced 2025-07-08 04:54:08 +00:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
7432ce6398 | |||
0831e3f503 | |||
a0f4c40be0 | |||
1facef6897 | |||
428416a2a3 | |||
77dec205f1 | |||
6c761d7576 | |||
865fd3bbe4 | |||
30bdb23a32 | |||
f97562e9b7 | |||
2d000101c2 | |||
a26d227190 | |||
cc44f0e23b | |||
96df636195 | |||
36660d384d | |||
788c2cbbd4 | |||
9d5e5a3217 | |||
945da05794 | |||
3085d4c450 |
27
.github/workflows/automerge.yml
vendored
Normal file
27
.github/workflows/automerge.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: automerge
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- labeled
|
||||||
|
- unlabeled
|
||||||
|
- synchronize
|
||||||
|
- opened
|
||||||
|
- edited
|
||||||
|
- ready_for_review
|
||||||
|
- reopened
|
||||||
|
- unlocked
|
||||||
|
pull_request_review:
|
||||||
|
types:
|
||||||
|
- submitted
|
||||||
|
check_suite:
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
status: {}
|
||||||
|
jobs:
|
||||||
|
automerge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: automerge
|
||||||
|
uses: "pascalgn/automerge-action@v0.13.0"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
82
Cargo.toml
82
Cargo.toml
@ -1,41 +1,41 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "desubot"
|
name = "desubot"
|
||||||
version = "0.5.1"
|
version = "0.5.5"
|
||||||
authors = ["AB <ab@hexor.ru>"]
|
authors = ["AB <ab@hexor.ru>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = "0.5"
|
bytes = "0.5"
|
||||||
tokio = { version = "0.2", features = ["full"]}
|
tokio = { version = "1.10.0", features = ["full"]}
|
||||||
tracing = "0.1.9"
|
tracing = "0.1.9"
|
||||||
tracing-futures = "0.2"
|
tracing-futures = "0.2"
|
||||||
multipart = { version = "0.16", default-features = false, features = ["client"] }
|
multipart = { version = "0.16", default-features = false, features = ["client"] }
|
||||||
telegram-bot = "0.8.0"
|
telegram-bot = "0.8.0"
|
||||||
silicon = "0.4.0"
|
silicon = "0.4.0"
|
||||||
hyper = "0.13"
|
hyper = "0.14"
|
||||||
hyper-tls = { version = "0.4", optional = true }
|
hyper-tls = { version = "0.4", optional = true }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
hyper-rustls = { version = "0.19", optional = true }
|
hyper-rustls = { version = "0.19", optional = true }
|
||||||
rusqlite = { version = "0.24.2", features = ["bundled"]}
|
rusqlite = { version = "0.24.2", features = ["bundled"]}
|
||||||
html-escape = "0.2"
|
html-escape = "0.2"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
reqwest = "0.10.9"
|
reqwest = "0.11.4"
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
sha1 = "0.6.0"
|
sha1 = "0.6.0"
|
||||||
env_logger = "0.7"
|
env_logger = "0.9.0"
|
||||||
log = { version = "^0.4.5", features = ["std"] }
|
log = { version = "^0.4.5", features = ["std"] }
|
||||||
subprocess = "0.2.6"
|
subprocess = "0.2.6"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
markov = "1.1.0"
|
markov = "1.1.0"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
mystem = "^0.2"
|
mystem = "^0.2"
|
||||||
#mystem = { path = "../mystem-rs" }
|
#mystem = { path = "../mystem-rs" }
|
||||||
async-trait = "0.1.42"
|
async-trait = "0.1.42"
|
||||||
sqlparser = "0.7.0"
|
sqlparser = "0.9.0"
|
||||||
|
|
||||||
[dependencies.syntect]
|
[dependencies.syntect]
|
||||||
version = "4.4"
|
version = "4.4"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["parsing", "dump-load", "regex-onig"]
|
features = ["parsing", "dump-load", "regex-onig"]
|
||||||
|
4
README
4
README
@ -7,10 +7,8 @@ Telegram bot with light group statistic and heavy spy features.
|
|||||||
* /here command to mention all members.
|
* /here command to mention all members.
|
||||||
* Alongside with saving whole message bot perform blacklist filter and stemming for every word (only Russian). "Красивую собаку мыли негры" -> "красивый собака мыть негр"
|
* Alongside with saving whole message bot perform blacklist filter and stemming for every word (only Russian). "Красивую собаку мыли негры" -> "красивый собака мыть негр"
|
||||||
* Generate sentences using Markov Chains trained on history with /markov_all.
|
* Generate sentences using Markov Chains trained on history with /markov_all.
|
||||||
|
|
||||||
== TODO ==
|
|
||||||
* Syntax highlighting for CODE exported to image.
|
* Syntax highlighting for CODE exported to image.
|
||||||
|
|
||||||
== Important ==
|
== Important ==
|
||||||
* Desubot uses MyStem by Yandex for word stemming and assume that mystem binary is available in PATH.
|
* Desubot uses MyStem by Yandex for word stemming and assume that mystem binary is available in PATH.
|
||||||
On Windows it may be placed on working directory. Both Linux and Windows mystem binary is in repo.
|
On Windows it may be placed on working directory. Both Linux and Windows mystem binary is in repo.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
static CODE_HELP: &str = "<b>Code highlighter</b>
|
static CODE_HELP: &str = "<b>Code highlighter</b>
|
||||||
|
|
||||||
<i>Usage</i>
|
<i>Usage</i>
|
||||||
<pre>/CODE
|
<pre>/code
|
||||||
<CODE>
|
<CODE>
|
||||||
#<lang - JS by default> #<theme - Dracula by default></pre>
|
#<lang - JS by default> #<theme - Dracula by default></pre>
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ use syntect::highlighting::Theme;
|
|||||||
use syntect::parsing::SyntaxReference;
|
use syntect::parsing::SyntaxReference;
|
||||||
use syntect::util::LinesWithEndings;
|
use syntect::util::LinesWithEndings;
|
||||||
use telegram_bot::prelude::*;
|
use telegram_bot::prelude::*;
|
||||||
use telegram_bot::{Api, Message, ParseMode};
|
use telegram_bot::{Api, Message, ParseMode, UserId};
|
||||||
|
|
||||||
include!("../assets/help_text.rs");
|
include!("../assets/help_text.rs");
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ impl Execute for Sql {
|
|||||||
let mut sql = self.data.clone();
|
let mut sql = self.data.clone();
|
||||||
debug!("PIZDA - {}", sql);
|
debug!("PIZDA - {}", sql);
|
||||||
if sql == "/sql" || sql == "/sql-" {
|
if sql == "/sql" || sql == "/sql-" {
|
||||||
return Ok(SQL_HELP.to_string())
|
return Ok(SQL_HELP.to_string());
|
||||||
}
|
}
|
||||||
let is_head = if sql.starts_with('-') {
|
let is_head = if sql.starts_with('-') {
|
||||||
sql = sql.replacen("-", "", 1);
|
sql = sql.replacen("-", "", 1);
|
||||||
@ -192,7 +192,15 @@ impl Execute for Sql {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Execute for Here {
|
impl Execute for Here {
|
||||||
async fn exec(&self, api: &Api, message: &Message) -> Result<(), Error> {
|
async fn exec(&self, api: &Api, message: &Message) -> Result<(), Error> {
|
||||||
let members: Vec<telegram_bot::User> = db::get_members(message.chat.id()).unwrap();
|
let members: Vec<telegram_bot::User> =
|
||||||
|
db::get_members(message.chat.id(), 60).unwrap_or(vec![telegram_bot::User {
|
||||||
|
id: UserId::new(124317807),
|
||||||
|
first_name: "Ultradesu".to_string(),
|
||||||
|
last_name: None,
|
||||||
|
username: None,
|
||||||
|
is_bot: false,
|
||||||
|
language_code: None,
|
||||||
|
}]);
|
||||||
for u in &members {
|
for u in &members {
|
||||||
debug!("Found user {:?} in chat {}", u, message.chat.id());
|
debug!("Found user {:?} in chat {}", u, message.chat.id());
|
||||||
}
|
}
|
||||||
|
28
src/db.rs
28
src/db.rs
@ -180,18 +180,29 @@ pub(crate) async fn get_messages_user_all(
|
|||||||
Ok(messages)
|
Ok(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_members(id: telegram_bot::ChatId) -> Result<Vec<telegram_bot::User>> {
|
pub(crate) fn get_members(id: telegram_bot::ChatId, limit: u32) -> Result<Vec<telegram_bot::User>> {
|
||||||
|
let where_statement = if limit > 0 {
|
||||||
|
format!("and days_seen <= {}", limit)
|
||||||
|
} else {
|
||||||
|
"".into()
|
||||||
|
};
|
||||||
|
debug!("{}", where_statement);
|
||||||
let conn = open()?;
|
let conn = open()?;
|
||||||
let mut stmt = conn.prepare_cached(
|
let mut stmt = conn.prepare_cached(&format!(
|
||||||
"
|
"
|
||||||
SELECT DISTINCT(u.username), u.id, u.first_name, u.last_name, u.date
|
SELECT DISTINCT(u.username), u.id, u.first_name, u.last_name, u.date,
|
||||||
|
(strftime('%s','now')-r.date)/60/60/24 as days_seen
|
||||||
FROM relations r
|
FROM relations r
|
||||||
JOIN user u
|
JOIN user u
|
||||||
ON u.id = r.user_id
|
ON u.id = r.user_id
|
||||||
LEFT JOIN conf c
|
LEFT JOIN conf c
|
||||||
ON r.conf_id = c.id
|
ON r.conf_id = c.id
|
||||||
WHERE c.id = :id",
|
WHERE c.id = :id
|
||||||
)?;
|
{}
|
||||||
|
GROUP BY u.id
|
||||||
|
ORDER BY r.date DESC",
|
||||||
|
where_statement
|
||||||
|
))?;
|
||||||
let mut rows = stmt.query_named(&[(":id", &id.to_string())])?;
|
let mut rows = stmt.query_named(&[(":id", &id.to_string())])?;
|
||||||
let mut users = Vec::new();
|
let mut users = Vec::new();
|
||||||
|
|
||||||
@ -283,7 +294,11 @@ pub(crate) async fn add_user(message: Message) -> Result<(), Error> {
|
|||||||
(":first_name", &update.first_name),
|
(":first_name", &update.first_name),
|
||||||
(":last_name", &update.last_name),
|
(":last_name", &update.last_name),
|
||||||
])?;
|
])?;
|
||||||
debug!("User {} updated: {:?}", update.first_name, get_user(update.id));
|
debug!(
|
||||||
|
"User {} updated: {:?}",
|
||||||
|
update.first_name,
|
||||||
|
get_user(update.id)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let unix_time = SystemTime::now()
|
let unix_time = SystemTime::now()
|
||||||
@ -417,6 +432,7 @@ pub(crate) async fn add_sentence(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Save stemmed words
|
// Save stemmed words
|
||||||
|
debug!("Going to stem: {}", text);
|
||||||
let words = mystem.stemming(text)?;
|
let words = mystem.stemming(text)?;
|
||||||
conn.execute("BEGIN TRANSACTION", params![]);
|
conn.execute("BEGIN TRANSACTION", params![]);
|
||||||
for word in words {
|
for word in words {
|
||||||
|
@ -53,7 +53,7 @@ pub async fn handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s if s.contains("/here") => {
|
s if s.contains("/here") || s.contains("@here") || s.contains("/хере") || s.contains("@хере") || s.contains("\"хере") => {
|
||||||
db::add_sentence(&message, mystem).await?;
|
db::add_sentence(&message, mystem).await?;
|
||||||
Here {
|
Here {
|
||||||
data: "".to_string(),
|
data: "".to_string(),
|
||||||
@ -118,9 +118,7 @@ pub async fn handler(
|
|||||||
.exec_mystem(&api, &message, mystem)
|
.exec_mystem(&api, &message, mystem)
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
_ => {
|
_ => db::add_sentence(&message, mystem).await?,
|
||||||
db::add_sentence(&message, mystem).await?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageKind::Photo { ref caption, .. } => {
|
MessageKind::Photo { ref caption, .. } => {
|
||||||
|
25
src/main.rs
25
src/main.rs
@ -1,3 +1,4 @@
|
|||||||
|
#![allow(unreachable_code)]
|
||||||
use std::{env, process};
|
use std::{env, process};
|
||||||
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
@ -16,7 +17,7 @@ use mystem::MyStem;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), errors::Error> {
|
async fn main() -> Result<(), errors::Error> {
|
||||||
env_logger::from_env(Env::default().default_filter_or("info")).init();
|
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||||
let mut mystem = match MyStem::new() {
|
let mut mystem = match MyStem::new() {
|
||||||
Ok(mystem) => mystem,
|
Ok(mystem) => mystem,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -44,16 +45,18 @@ async fn main() -> Result<(), errors::Error> {
|
|||||||
me.first_name,
|
me.first_name,
|
||||||
me.id
|
me.id
|
||||||
);
|
);
|
||||||
while let Some(update) = stream.next().await {
|
loop {
|
||||||
let update = update?;
|
while let Some(update) = stream.next().await {
|
||||||
if let UpdateKind::Message(message) = update.kind {
|
let update = update?;
|
||||||
db::add_conf(message.clone()).await?;
|
if let UpdateKind::Message(message) = update.kind {
|
||||||
db::add_user(message.clone()).await?;
|
db::add_conf(message.clone()).await?;
|
||||||
match handlers::handler(api.clone(), message, token.clone(), &mut mystem, me.clone())
|
db::add_user(message.clone()).await?;
|
||||||
.await
|
match handlers::handler(api.clone(), message, token.clone(), &mut mystem, me.clone())
|
||||||
{
|
.await
|
||||||
Ok(_) => {}
|
{
|
||||||
Err(e) => warn!("An error occurred handling command. {:?}", e),
|
Ok(_) => {}
|
||||||
|
Err(e) => warn!("An error occurred handling command. {:?}", e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user