generated from Oliver/discord-bot-template
surreal v1
This commit is contained in:
parent
8e53f2a234
commit
a701716958
2051
Cargo.lock
generated
2051
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -18,3 +18,4 @@ tracing = "0.1.40"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
serde_json = "1.0.120"
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
surrealdb = "1.5.4"
|
||||
|
130
src/command.rs
130
src/command.rs
@ -1,9 +1,10 @@
|
||||
use std::{collections::HashMap, fmt::Display, fs, sync::Arc};
|
||||
use std::{collections::HashMap, fmt::Display, fs, hint::black_box, sync::Arc};
|
||||
|
||||
use crate::Context;
|
||||
use anyhow::Error;
|
||||
use poise::{serenity_prelude::{Cache, CacheHttp, ChannelId, ChannelType, GetMessages, GuildChannel, Http, Message}, CreateReply};
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use surrealdb::{engine::remote::ws::Ws, opt::auth::Root, sql::Thing, Surreal};
|
||||
use tokio::time::Instant;
|
||||
use tracing::{debug, error, info, trace};
|
||||
|
||||
@ -87,8 +88,9 @@ impl Display for Server {
|
||||
|
||||
impl Server {
|
||||
|
||||
fn new() -> Self {
|
||||
fn new(name: impl Into<String>) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
channels: Vec::new(),
|
||||
orphanage: Vec::new(),
|
||||
needs_clean: false
|
||||
@ -213,6 +215,87 @@ impl Server {
|
||||
walk(&self.channels)
|
||||
}
|
||||
|
||||
async fn to_surreal(&self) -> surrealdb::Result<()> {
|
||||
trace!("Connecting to surrealdb...");
|
||||
// Connect to the server
|
||||
let db = Surreal::new::<Ws>("127.0.0.1:8000").await?;
|
||||
db.signin(Root {
|
||||
username: "root",
|
||||
password: "root",
|
||||
}).await?;
|
||||
|
||||
db.use_ns("egress").use_db(self.name.clone()).await?;
|
||||
|
||||
// =========================================================
|
||||
// Ingress data
|
||||
trace!("Starting ingress...");
|
||||
for cat in self.channels.iter() {
|
||||
|
||||
// TODO learn why this is a vec
|
||||
// Do the first iteration of channels a bit different, so as to name it "category".
|
||||
let new_category: Vec<Thing> = db
|
||||
.create("category")
|
||||
.content(&cat.this)
|
||||
.await?;
|
||||
import_messages(&cat.messages, &new_category[0], &db).await?;
|
||||
|
||||
// Ok, now automatically recurse the rest of the structure and auto import as channels
|
||||
// and messages.
|
||||
import_channel(&cat.children, &new_category[0], &db).await?;
|
||||
}
|
||||
|
||||
async fn import_channel(channels: &Vec<Channel>, parent: &Thing, db: &Surreal<surrealdb::engine::remote::ws::Client>) -> surrealdb::Result<()> {
|
||||
for channel in channels.iter() {
|
||||
trace!("Importing channel \"{}\"", channel.this.name);
|
||||
#[derive(Serialize)]
|
||||
struct ChannelWrapper<'a, 'b> {
|
||||
channel: &'a GuildChannel,
|
||||
surreal_parent: &'b Thing,
|
||||
}
|
||||
let new_channel: Vec<Thing> = db
|
||||
.create("channel")
|
||||
.content(ChannelWrapper {
|
||||
channel: &channel.this,
|
||||
surreal_parent: &parent,
|
||||
})
|
||||
.await?;
|
||||
|
||||
import_messages(&channel.messages, &new_channel[0], &db).await?;
|
||||
// async recursion - thus box
|
||||
Box::pin(import_channel(&channel.children, &new_channel[0], &db)).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn import_messages(msgs: &Vec<Message>, parent: &Thing, db: &Surreal<surrealdb::engine::remote::ws::Client>) -> surrealdb::Result<()> {
|
||||
trace!("Importing {} messages...", msgs.len());
|
||||
for msg in msgs.iter() {
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct MessageWrapper<'a, 'b> {
|
||||
message: &'a Message,
|
||||
surreal_parent: &'b Thing
|
||||
}
|
||||
|
||||
let created: Vec<Thing> = db
|
||||
.create("message")
|
||||
.content(MessageWrapper {
|
||||
message: &msg,
|
||||
surreal_parent: &parent,
|
||||
})
|
||||
.await?;
|
||||
|
||||
trace!("Imported message {:?}", created);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Data is all in
|
||||
// =========================================================
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, rename = "scrape_all", guild_only, owners_only)]
|
||||
@ -227,7 +310,7 @@ pub async fn scrape_all(ctx: Context<'_>, pretty_print: bool) -> Result<(), Erro
|
||||
}
|
||||
|
||||
if let Ok(map) = guild.channels(ctx.http()).await {
|
||||
let mut server = index(map).await;
|
||||
let mut server = index(map, guild.name).await;
|
||||
match ctx.reply("Starting scrape...").await {
|
||||
Ok(ok) => {
|
||||
let start = Instant::now();
|
||||
@ -235,22 +318,26 @@ pub async fn scrape_all(ctx: Context<'_>, pretty_print: bool) -> Result<(), Erro
|
||||
let end = start.elapsed().as_millis();
|
||||
let msg_count = server.message_count();
|
||||
|
||||
let print = if pretty_print {
|
||||
serde_json::to_string_pretty(&server)
|
||||
} else {
|
||||
serde_json::to_string(&server)
|
||||
if let Err(e) = server.to_surreal().await {
|
||||
error!("{e}");
|
||||
};
|
||||
|
||||
match print {
|
||||
Ok(ok) => {
|
||||
if let Err(e) = fs::write("server.json", ok) {
|
||||
error!("Problem writing server to disk: {e}");
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Trying to serialize server: {err}");
|
||||
},
|
||||
}
|
||||
// let print = if pretty_print {
|
||||
// serde_json::to_string_pretty(&server)
|
||||
// } else {
|
||||
// serde_json::to_string(&server)
|
||||
// };
|
||||
|
||||
// match print {
|
||||
// Ok(ok) => {
|
||||
// if let Err(e) = fs::write("server.json", ok) {
|
||||
// error!("Problem writing server to disk: {e}");
|
||||
// }
|
||||
// },
|
||||
// Err(err) => {
|
||||
// error!("Trying to serialize server: {err}");
|
||||
// },
|
||||
// }
|
||||
|
||||
// Done. Print stats.
|
||||
let _ = ok.edit(ctx, CreateReply::default().content(
|
||||
@ -272,8 +359,8 @@ pub fn from_json() {
|
||||
}
|
||||
|
||||
/// Get server's topology (and runs clean)
|
||||
async fn index(map: HashMap<ChannelId, GuildChannel>) -> Server {
|
||||
let mut server = Server::new();
|
||||
async fn index(map: HashMap<ChannelId, GuildChannel>, name: impl Into<String>) -> Server {
|
||||
let mut server = Server::new(name);
|
||||
// iterate thru all channels
|
||||
map.into_iter().for_each(|(_id, current)| {
|
||||
// println!("{} {} {:?}", current.name, current.id, current.parent_id);
|
||||
@ -298,10 +385,11 @@ pub async fn index_cmd(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
match guild.channels(ctx.http()).await {
|
||||
Ok(ok) => {
|
||||
let server = index(ok).await;
|
||||
let server = index(ok, guild.name).await;
|
||||
let _ = ctx.reply(server.to_string()).await;
|
||||
},
|
||||
Err(_) => todo!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ static ENV: Lazy<BotEnv> = Lazy::new(|| {
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
command::from_json();
|
||||
|
||||
// Start the tracing subscriber
|
||||
let filter = EnvFilter::builder()
|
||||
|
Loading…
Reference in New Issue
Block a user