SQLite not working, send help

This commit is contained in:
Ladislav Hano 2024-02-14 13:22:29 +01:00
parent 6abc80a8a7
commit b3c3c8cfb0
11 changed files with 989 additions and 368 deletions

984
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -8,13 +8,19 @@ edition = "2021"
[dependencies] [dependencies]
rand = "0.8.5" rand = "0.8.5"
anyhow = "1.0.71" anyhow = "1.0.71"
# cron = "0.12.0" # tokio-cron-scheduler = "0.9.4"
tokio_schedule = "0.3.1"
dotenv = "0.15.0" dotenv = "0.15.0"
# mongodb = "2.6.0"
# poise = "0.5.5" # poise = "0.5.5"
serenity = { version = "0.11.6", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http"] } serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] }
serenity_utils = "0.7.0" serenity_utils = "0.7.0"
tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread"] }
rand = "0.8.4"
regex = "1.9.0" regex = "1.9.0"
url = "2.4.0" # sqlite = "0.32.0"
# async-sqlite = { version = "0.2.1", default-features = false }
async-rusqlite = "0.4.0"
chrono = "0.4.31"
[features]
DEBUG = []
RELEASE = []

12
makefile Normal file
View file

@ -0,0 +1,12 @@
dev:
cargo build --features DEBUG
release:
cargo build --release --features RELEASE
run:
cargo build --features DEBUG
./target/debug/moover_rust
run_release:
./target/release/moover_rust

View file

@ -1,74 +1,78 @@
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use anyhow::{self, Context}; use anyhow::Context;
use poise::serenity_prelude::AttachmentType; use serenity::builder::{CreateAttachment, CreateEmbed, CreateMessage};
use serenity::builder::CreateEmbed;
use serenity::http::Http; use serenity::http::Http;
use serenity::model::channel::Message; use serenity::model::channel::Message;
use tokio::time::sleep; use tokio::time::sleep;
use url::Url;
use regex::Regex; use regex::Regex;
use serenity::model::id::ChannelId;
// Checks if the message should be mooved // Checks if the message should be mooved
// If the message should be mooved, try to move it and return Ok if mooved succesfully // If the message should be mooved, try to move it and return Ok if mooved succesfully
// else returns Err() // else returns Err()
pub enum MooveResult { pub async fn moove_check(msg: &Message) -> Option<u64> {
Mooved,
NotMooveRequest
}
pub async fn moove(http: Arc<Http>, msg: Message) -> anyhow::Result<MooveResult> {
let word_count = msg.content.trim().split_whitespace().count(); let word_count = msg.content.trim().split_whitespace().count();
let re = Regex::new(r"<#[0-9]*>$").unwrap(); let re = Regex::new(r"<#[0-9]*>$").unwrap();
if word_count != 1 || re.captures(&msg.content).is_none() { if word_count != 1 || re.captures(&msg.content).is_none() {
return Ok(MooveResult::NotMooveRequest); return None
} }
let msg_to_moove = msg.clone().referenced_message.context("no message present")?; let channel_id = match msg.content[2..msg.content.len() - 1].parse::<u64>() {
Ok(val) => val,
Err(_) => return None
};
let mentioned_channel = http.get_channel( return Some(channel_id);
msg.content[2..msg.content.len() - 1].parse::<u64>() }
.unwrap()).await?.id();
pub async fn moove(http: Arc<Http>, msg: Message, m_channel_id: u64) -> anyhow::Result<()> {
// this should be in moove_check, but I need to find a good way to return in with channel_id
let msg_to_moove = msg.clone().referenced_message.context("Referenced message not found")?;
//steals all attachments, but sets all of them as Image urls, so rip actual docs etc //steals all attachments, but sets all of them as Image urls, so rip actual docs etc
let attachments = msg_to_moove let mut attachments: Vec<CreateAttachment> = Vec::new();
.attachments.clone() for attachment in msg_to_moove.attachments.clone() {
.into_iter() let data = attachment.download().await?;
.map(|att| AttachmentType::Image(Url::parse(att.url.as_str()).unwrap())); attachments.push(CreateAttachment::bytes(data, attachment.filename));
}
//steals all the embeds //steals all the embeds
let embeds: Vec<CreateEmbed> = msg_to_moove let embeds: Vec<CreateEmbed> = msg_to_moove
.embeds.clone() .embeds.clone()
.into_iter() .into_iter()
.map(|em| CreateEmbed::from(em)) .map(| embed | CreateEmbed::from(embed))
.collect(); .collect();
let mut new_content = format!("Sent by {}\n mooved {}\n", msg_to_moove.author, msg.author);
let mut new_content = format!("Sent by {}\n mooved {}\n", msg_to_moove.author, msg.author);
let mut new_msg = CreateMessage::new();
// Either copy all the attachments and embeds and create a new message that contains them all
if attachments.len() > 0 || embeds.len() > 0 { if attachments.len() > 0 || embeds.len() > 0 {
new_content += format!("Message:\n{}", msg_to_moove.content).as_str(); new_content += format!("Message:\n{}", msg_to_moove.content).as_str();
mentioned_channel.send_message(http.clone(), |m| {
m.content(new_content) new_msg = new_msg.content(new_content)
.add_embeds(embeds) .add_embeds(embeds)
.add_files(attachments) .add_files(attachments);
}).await?;
} }
else if !msg_to_moove.content.is_empty() { // or create a new embed with the content of the mooved message as one of the fields
mentioned_channel.send_message(http.clone(), |m| { else {
m.add_embed(|e| { let embed = CreateEmbed::new()
e.field("MOO", new_content, false) .field("MOO", new_content, false)
.field("Message:\n", msg_to_moove.content.clone(), false) .field("Message:\n", msg_to_moove.content.clone(), false);
})
}).await?; new_msg = new_msg.add_embed(embed);
} }
ChannelId::new(m_channel_id).send_message(http.clone(), new_msg).await?;
sleep(Duration::from_secs(2)).await; sleep(Duration::from_secs(2)).await;
msg_to_moove.delete(http.clone()).await?; msg_to_moove.delete(http.clone()).await?;
msg.delete(http).await?; msg.delete(http).await?;
Ok(MooveResult::Mooved) Ok(())
} }

View file

@ -1,17 +1,27 @@
use rand::random; use std::sync::atomic::AtomicUsize;
use chrono::Utc;
use serenity::async_trait; use serenity::async_trait;
use serenity::model::channel::Message; use serenity::model::channel::Message;
use serenity::model::gateway::Ready; use serenity::model::gateway::Ready;
use serenity::prelude::*; use serenity::prelude::*;
use serenity::client::Context;
// use tokio_cron_scheduler::{JobScheduler, JobToRun, Job};
use tokio_schedule::{every, EveryDay, Job};
use util::security::dotenv_var; use util::security::dotenv_var;
use other::msg::hello;
use std::sync::Arc;
mod message_handler; mod message_handler;
use message_handler::handle; use message_handler::handle;
mod commands; mod commands;
mod util; mod util;
use util::debug::send_error;
mod other; mod other;
use other::notice;
struct Handler; struct Handler;
@ -23,39 +33,46 @@ impl EventHandler for Handler {
async fn ready(&self, ctx: Context, ready: Ready) { async fn ready(&self, ctx: Context, ready: Ready) {
println!("{} is connected!", ready.user.name); println!("{} is connected!", ready.user.name);
let debug = match dotenv_var("DEBUG") {
Some(v) => v,
None => "OFF".to_string(),
};
if debug != "ON" {
let messages = [
"AAAAAAAAAAAAAAAAAAAA",
"Henlooo",
"Good day y'all!",
"May have crashed...",
"MOOOooo",
"Heyyyyy!",
"I'm baaaaack!",
"Whom'st have summoned the ancient one?",
];
let rand_num = random::<usize>() % messages.len();
let channel = ctx.http.get_channel(780439236867653635).await.unwrap().id(); // use util::debug::hello;
match channel.say(&ctx.http, messages[rand_num]).await { // hello(ctx.http.clone()).await;
Err(e) => println!("Something went wrong: {e}"),
Ok(_) => return, notice::notice_wrapper(ctx).await;
};
} // let scheduler = every(1).day().at(13, 30, 0)
// if ready.user.name != "MOOver Debug" { // .perform(|| async {
hello(ctx.http).await; // notice::notice_wrapper(ctx.clone()).await
// }).await;
// let mut scheduler = JobScheduler::new().await;
// scheduler.
// scheduler.add(match Job::new_async("5 * * * * * *", |uuid, mut l| Box::pin( async {
// notice::notice(ctx.clone()).await;
// })) {
// Ok(_) => {}
// Err(e) => {
// send_error(ctx.http.clone(), e.to_string());
// panic!()
// } // }
// });
// scheduler.add(Job::new(daily("22"), move || {
// notice::notice(ctx.clone())
// }));
} }
} }
#[tokio::main] #[tokio::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
use anyhow::Context; use anyhow::Context;
let token = dotenv_var("TOKEN").context("No TOKEN in env")?;
let token_str = "TOKEN";
#[cfg(feature="DEBUG")]
let token_str = "DEBUGTOKEN";
let token = dotenv_var(token_str).context("No TOKEN in env")?;
let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT; let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT;
let mut client = Client::builder(&token, intents) let mut client = Client::builder(&token, intents)

View file

@ -1,11 +1,75 @@
use serenity::client::Context; use rand::random;
use serenity::{client::Context, http::Http};
use serenity::model::channel::Message; use serenity::model::channel::Message;
use std::sync::Arc;
use crate::commands::moove::moove; use crate::util::debug::send_error;
use crate::commands::moove::{moove, moove_check};
pub async fn handle(ctx: Context, msg: Message) { pub async fn handle(ctx: Context, msg: Message) {
match moove(ctx.http, msg).await { if msg.author.bot {
return
}
let lower_case_content = msg.content.to_lowercase();
let bot_id = ctx.cache.current_user().id;
if msg.mentions_user_id(bot_id) || lower_case_content.contains("moover") {
if !response(ctx.http.clone(), msg.clone()).await {
// NOTE maybe should exit here instead since there is something very wrong if I can't reply
return
}
}
else if lower_case_content.contains("henlo") {
if !henlo(ctx.http.clone(), msg.clone()).await {
// NOTE same as above
return
}
}
let channel_id = match moove_check(&msg).await {
Some(val) => val,
None => return
};
match moove(ctx.http, msg, channel_id).await {
Ok(_) => return, Ok(_) => return,
Err(e) => println!("ERROR: {e}") Err(e) => println!("ERROR: {e}")
}; };
} }
async fn response(http: Arc<Http>, msg: Message) -> bool {
// NOTE probably not clever to do it this way
const RESPONSES: [&str; 4] = [
"To som jaaa",
"Henloooo",
"Čo môj?",
"Hm?"
];
let num = random::<usize>() % RESPONSES.len();
match msg.reply(http.clone(), RESPONSES[num]).await {
Ok(_) => { return true }
Err(e) => {
send_error(http, e.to_string()).await;
return false
}
};
}
async fn henlo(http: Arc<Http>, msg: Message) -> bool {
const EMOJIS: [&str; 7] = ["🥰", "🐄", "🐮", "❤️", "👋", "🤠", "😊"];
let num = random::<usize>() % EMOJIS.len();
let response = format!("Henlooo {} {}", msg.author.name, EMOJIS[num]);
match msg.reply(http.clone(), response).await {
Ok(_) => { return true }
Err(e) => {
send_error(http, e.to_string()).await;
return false
}
};
}

View file

@ -1 +1 @@
pub mod msg; pub mod notice;

View file

@ -1,23 +0,0 @@
use serenity::http::Http;
use std::sync::Arc;
pub async fn hello(http: Arc<Http>) {
let messages = [
"AAAAAAAAAAAAAAAAAAAA",
"Henlooo",
"Good day y'all!",
"May have crashed...",
"MOOOooo",
"Heyyyyy!",
"I'm baaaaack!",
"Whom'st have summoned the ancient one?",
];
let channel = http.get_channel(780439236867653635).await.unwrap();
let num = rand::random::<usize>() % messages.len();
if let Err(why) = channel.id().say(http, messages[num]).await {
print!("Error sending message: {:?}", why);
};
}

67
src/other/notice.rs Normal file
View file

@ -0,0 +1,67 @@
use serenity::prelude::*;
use chrono::{Local, Datelike};
// use async_sqlite::{rusqlite::{Rows, Statement}, ClientBuilder, JournalMode};
use crate::util::debug::send_error;
use anyhow::Result;
use async_rusqlite::Connection;
pub async fn notice_wrapper(ctx: Context) {
match notice(ctx.clone()).await {
Ok(_) => return,
Err(e) => {
send_error(ctx.http.clone(), e.to_string()).await;
return
}
}
}
struct BirtdayRow {
day: u8,
month: u8,
nick: String
}
async fn notice(ctx: Context) -> anyhow::Result<()> {
let local = Local::now();
let day = local.day();
let month = local.month();
let conn = Connection::open("my.db").await?;
let stmt = conn.call(move |conn| {
conn.prepare("SELECT * FROM birthdays WHERE day=6 AND month=3;")
}).await?;
// let result = Vec::new();
// let stmt = client.conn(|conn| {
// // conn.prepare(format!("SELECT * FROM {db} WHERE day={day} AND month={month};").as_str());
// conn.prepare("SELECT * FROM birthdays WHERE day=6 AND month=3;")
// }).await?;
let rows = stmt.query([])?;
let result: Vec<BirtdayRow> = Vec::new();
while let Some(row) = rows.next()? {
let bd = BirtdayRow {
day: row.get(1)?,
month: row.get(2)?,
nick: row.get(3)?
};
result.push(bd);
}
println!("VALUE: {:?}", result[0].day);
// for db in ["birthdays", "events"] {
// // let mut stmt = client.conn(|conn| {
// // conn.
// // }).await;
// }
Ok(())
}

33
src/util/debug.rs Normal file
View file

@ -0,0 +1,33 @@
use serenity::{all::ChannelId, builder::CreateMessage, http::Http};
use std::{process::exit, sync::Arc};
pub async fn send_error(http: Arc<Http>, msg: String) {
println!("ERROR: {msg}");
#[cfg(feature="RELEASE")]
match ChannelId::new(1199495008416440491)
.send_message(http, CreateMessage::new().content(msg)).await {
Ok(_) => { return; }
Err(_) => { exit(-1) }
};
}
pub async fn hello(http: Arc<Http>) {
let messages = [
"AAAAAAAAAAAAAAAAAAAA",
"Henlooo",
"Good day y'all!",
"May have crashed...",
"MOOOooo",
"Heyyyyy!",
"I'm baaaaack!",
"Whom'st have summoned the ancient one?",
];
let num = rand::random::<usize>() % messages.len();
let channel = ChannelId::new(780439236867653635);
if let Err(why) = channel.say(http, messages[num]).await {
print!("Error sending message: {:?}", why);
};
}

View file

@ -1 +1,2 @@
pub mod security; pub mod security;
pub mod debug;