generated from Oliver/discord-bot-template
map of server
This commit is contained in:
parent
e0a9f957a5
commit
67ee89bad9
1153
Cargo.lock
generated
1153
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "REPO-NAME"
|
||||
name = "discord_egress"
|
||||
authors = ["Oliver", "Oliver"]
|
||||
description = "egress a discord server"
|
||||
repository = "https://git.oliveratkinson.net/Oliver/discord-egress.git"
|
||||
@ -11,9 +11,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
||||
# songbird = { version = "0.3.2", features = ["yt-dlp"] }
|
||||
poise = { version = "0.5.7", features = ["cache"] }
|
||||
poise = { version = "0.6", features = ["cache"] }
|
||||
dotenv = "0.15.0"
|
||||
anyhow = "1.0.75"
|
||||
url = "2.4.1"
|
||||
async-recursion = "1.0.5"
|
||||
|
||||
|
@ -3,15 +3,13 @@ FROM rustlang/rust:nightly as builder
|
||||
ENV RUSTFLAGS=""
|
||||
|
||||
WORKDIR /bot
|
||||
# RUN apt-get update && apt-get upgrade -y
|
||||
COPY . .
|
||||
RUN cargo build --release
|
||||
|
||||
# Now make the runtime container
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get clean
|
||||
COPY --from=builder /bot/target/release/REPO-NAME /usr/local/bin/REPO-NAME
|
||||
COPY --from=builder /bot/target/release/discord_egress /usr/local/bin/discord_egress
|
||||
COPY Cargo.lock /
|
||||
|
||||
CMD ["/usr/local/bin/REPO-NAME"]
|
||||
CMD ["/usr/local/bin/discord_egress"]
|
182
src/command.rs
182
src/command.rs
@ -1,17 +1,171 @@
|
||||
use std::hint::black_box;
|
||||
use anyhow::Error;
|
||||
use crate::Context;
|
||||
use std::fmt::Display;
|
||||
|
||||
// NOTE!!! Make sure these names in quotes are lowercase!
|
||||
#[poise::command(slash_command, rename = "cmd_name", guild_only)]
|
||||
pub async fn example(
|
||||
ctx: Context<'_>,
|
||||
#[description = "cmd_desc"]
|
||||
input: String
|
||||
) -> Result<(), Error> {
|
||||
// Do something...
|
||||
black_box(ctx);
|
||||
black_box(input);
|
||||
Ok(())
|
||||
use crate::Context;
|
||||
use anyhow::Error;
|
||||
use poise::serenity_prelude::{ChannelId, ChannelType, GuildChannel};
|
||||
|
||||
struct Server {
|
||||
channels: Vec<Channel>,
|
||||
orphanage: Vec<GuildChannel>,
|
||||
needs_clean: bool,
|
||||
}
|
||||
|
||||
struct Channel {
|
||||
this: GuildChannel,
|
||||
children: Vec<Channel>
|
||||
}
|
||||
|
||||
impl Display for Server {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
||||
fn print(f: &mut std::fmt::Formatter<'_>, tab: usize, channel: &Vec<Channel>) {
|
||||
for i in channel {
|
||||
for _ in 0..tab { let _ = write!(f, "\t"); }
|
||||
let _ = writeln!(f, "{} {}", prefix(i.this.kind),i.this.name);
|
||||
print(f, tab+1, &i.children);
|
||||
}
|
||||
}
|
||||
|
||||
fn prefix(kind: ChannelType) -> &'static str {
|
||||
match kind {
|
||||
poise::serenity_prelude::ChannelType::Text => "💬",
|
||||
poise::serenity_prelude::ChannelType::Private => "🕵️",
|
||||
poise::serenity_prelude::ChannelType::Voice => "🔊",
|
||||
poise::serenity_prelude::ChannelType::GroupDm => "👨👦👦",
|
||||
poise::serenity_prelude::ChannelType::Category => "📁",
|
||||
poise::serenity_prelude::ChannelType::News => "📢",
|
||||
poise::serenity_prelude::ChannelType::NewsThread => "📢🧵",
|
||||
poise::serenity_prelude::ChannelType::PublicThread => "🧵",
|
||||
poise::serenity_prelude::ChannelType::PrivateThread => "🕵️🧵",
|
||||
poise::serenity_prelude::ChannelType::Stage => "🎙️",
|
||||
poise::serenity_prelude::ChannelType::Directory => "📒",
|
||||
poise::serenity_prelude::ChannelType::Forum => "🗣️",
|
||||
_ => "?",
|
||||
}
|
||||
}
|
||||
|
||||
print(f, 0, &self.channels);
|
||||
|
||||
|
||||
if self.needs_clean {
|
||||
let _ = writeln!(f, "Orphans: (please clean() before displaying...)");
|
||||
for i in &self.orphanage {
|
||||
let _ = write!(f, "{} {},", prefix(i.kind),i.name);
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
|
||||
impl Server {
|
||||
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
channels: Vec::new(),
|
||||
orphanage: Vec::new(),
|
||||
needs_clean: false
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this might be broken
|
||||
fn search<'a>(target: &'a mut Vec<Channel>, find: &ChannelId) -> Option<&'a mut Channel> {
|
||||
for child in target {
|
||||
if child.this.id == *find {
|
||||
return Some(child);
|
||||
}
|
||||
match Self::search(&mut child.children, find) {
|
||||
Some(x) => return Some(x),
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn add(&mut self, insert: GuildChannel) {
|
||||
// make sure the new item wants a parent
|
||||
if let Some(parent_id) = &insert.parent_id {
|
||||
// find the parent (needs to go thru all nodes)
|
||||
|
||||
match Self::search(&mut self.channels, &parent_id) {
|
||||
Some(parent_node) => {
|
||||
parent_node.children.push(Channel { this: insert, children: Vec::new() });
|
||||
},
|
||||
None => {
|
||||
// couldn't find parent, store somewhere else until it's parent is added...
|
||||
self.orphanage.push(insert);
|
||||
self.needs_clean = true;
|
||||
},
|
||||
}
|
||||
} else {
|
||||
self.channels.push(Channel { this: insert, children: Vec::new() })
|
||||
}
|
||||
}
|
||||
|
||||
fn clean(&mut self) {
|
||||
if !self.needs_clean {return;}
|
||||
|
||||
// Look thru the orphanage and try to find parents
|
||||
for orphan in &self.orphanage {
|
||||
if let Some(parent_id) = orphan.parent_id {
|
||||
if let Some(found) = Self::search(&mut self.channels, &parent_id) {
|
||||
found.children.push(Channel { this: orphan.clone(), children: Vec::new() });
|
||||
} else {
|
||||
panic!("⚠️ Couldn't find parent for orphan!");
|
||||
}
|
||||
} else {
|
||||
panic!("⚠️ All orphans should want a parent node!");
|
||||
}
|
||||
}
|
||||
self.orphanage.clear();
|
||||
self.needs_clean = false;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE!!! Make sure these names in quotes are lowercase!
|
||||
#[poise::command(slash_command, rename = "index", guild_only)]
|
||||
pub async fn index(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
let guild = ctx.guild_id().unwrap().to_partial_guild(ctx.serenity_context()).await.unwrap();
|
||||
match guild.channels(ctx.http()).await {
|
||||
Ok(ok) => {
|
||||
|
||||
let mut server = Server::new();
|
||||
|
||||
// iterate thru all channels
|
||||
ok.into_iter().for_each(|(_id, current)| {
|
||||
match current.kind {
|
||||
poise::serenity_prelude::ChannelType::Text => {
|
||||
server.add(current);
|
||||
// current.position,
|
||||
},
|
||||
poise::serenity_prelude::ChannelType::Private => todo!(),
|
||||
poise::serenity_prelude::ChannelType::Voice => {
|
||||
server.add(current);
|
||||
// current.user_limit,
|
||||
// current.parent_id,
|
||||
},
|
||||
poise::serenity_prelude::ChannelType::GroupDm => todo!(),
|
||||
poise::serenity_prelude::ChannelType::Category => {
|
||||
server.add(current);
|
||||
},
|
||||
poise::serenity_prelude::ChannelType::News => todo!(),
|
||||
poise::serenity_prelude::ChannelType::NewsThread => todo!(),
|
||||
poise::serenity_prelude::ChannelType::PublicThread => todo!(),
|
||||
poise::serenity_prelude::ChannelType::PrivateThread => todo!(),
|
||||
poise::serenity_prelude::ChannelType::Stage => todo!(),
|
||||
poise::serenity_prelude::ChannelType::Directory => todo!(),
|
||||
poise::serenity_prelude::ChannelType::Forum => todo!(),
|
||||
poise::serenity_prelude::ChannelType::Unknown(_) => todo!(),
|
||||
_ => todo!(),
|
||||
}
|
||||
});
|
||||
|
||||
server.clean();
|
||||
println!("{}", server);
|
||||
|
||||
},
|
||||
Err(_) => todo!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
72
src/main.rs
72
src/main.rs
@ -10,81 +10,39 @@ async fn main() {
|
||||
// Generate sick text like this:
|
||||
// http://www.patorjk.com/software/taag/#p=testall&f=Graffiti&t=hello%20world
|
||||
println!(r#"
|
||||
/$$$$$$$$ /$$ /$$ /$$$$$$$ /$$
|
||||
|__ $$__/ | $$ | $$ | $$__ $$ | $$
|
||||
| $$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ | $$ /$$$$$$ /$$$$$$ /$$$$$$ | $$ \ $$ /$$$$$$ /$$$$$$
|
||||
| $$ /$$__ $$| $$_ $$_ $$ /$$__ $$| $$ |____ $$|_ $$_/ /$$__ $$ | $$$$$$$ /$$__ $$|_ $$_/
|
||||
| $$| $$$$$$$$| $$ \ $$ \ $$| $$ \ $$| $$ /$$$$$$$ | $$ | $$$$$$$$ | $$__ $$| $$ \ $$ | $$
|
||||
| $$| $$_____/| $$ | $$ | $$| $$ | $$| $$ /$$__ $$ | $$ /$$| $$_____/ | $$ \ $$| $$ | $$ | $$ /$$
|
||||
| $$| $$$$$$$| $$ | $$ | $$| $$$$$$$/| $$| $$$$$$$ | $$$$/| $$$$$$$ | $$$$$$$/| $$$$$$/ | $$$$/
|
||||
|__/ \_______/|__/ |__/ |__/| $$____/ |__/ \_______/ \___/ \_______/ |_______/ \______/ \___/
|
||||
| $$
|
||||
| $$
|
||||
|__/
|
||||
|
||||
Template Bot.
|
||||
Invite this bot with:
|
||||
|
||||
"#);
|
||||
println!("https://discord.com/api/oauth2/authorize?client_id={}&permissions={}&scope=bot",
|
||||
env.id,
|
||||
env.intents.bits(),
|
||||
);
|
||||
print!("\n");
|
||||
|
||||
// Setup framework
|
||||
let framework = poise::Framework::builder()
|
||||
.options(poise::FrameworkOptions {
|
||||
commands: vec![
|
||||
command::example(),
|
||||
command::index(),
|
||||
],
|
||||
..Default::default()
|
||||
})
|
||||
// un-comment songbird from Cargo.toml first.
|
||||
//.client_settings(songbird::register)
|
||||
.token(env.token)
|
||||
.intents(env.intents)
|
||||
.setup(|ctx, _ready, framework| {
|
||||
Box::pin(async move {
|
||||
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
||||
poise::builtins::register_globally(
|
||||
ctx,
|
||||
&framework.options().commands
|
||||
).await?;
|
||||
Ok(Data {})
|
||||
})
|
||||
});
|
||||
// Start the Bot.
|
||||
// Collect all the errors into one variable, that way we can match it
|
||||
// all at once.
|
||||
let err: Result<(), serenity::Error> = match framework.build().await {
|
||||
Ok(ok) => {
|
||||
match ok.start().await {
|
||||
Ok(_start) => Ok(()),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
};
|
||||
})
|
||||
.build();
|
||||
|
||||
if let Err(error) = err {
|
||||
match error {
|
||||
serenity::Error::Gateway(e)=>{
|
||||
match e {
|
||||
serenity::GatewayError::InvalidAuthentication => println!("ERROR: Authentication Invalid, check your bot token."),
|
||||
err_no_var=>println!("ERROR: {}",err_no_var.to_string()),
|
||||
}
|
||||
},
|
||||
serenity::Error::Decode(_, _) => println!("ERROR: Decode"),
|
||||
serenity::Error::Format(_) => println!("ERROR: Format"),
|
||||
serenity::Error::Io(_) => println!("ERROR: IO"),
|
||||
serenity::Error::Json(_) => println!("ERROR: Json"),
|
||||
serenity::Error::Model(_) => println!("ERROR: Model"),
|
||||
serenity::Error::ExceededLimit(_, _) => println!("ERROR: ExceededLimit"),
|
||||
serenity::Error::NotInRange(_, _, _, _) => println!("ERROR: NotInRange"),
|
||||
serenity::Error::Other(_) => println!("ERROR: Other"),
|
||||
serenity::Error::Url(_) => println!("ERROR: Url"),
|
||||
serenity::Error::Client(_) => println!("ERROR: Client"),
|
||||
serenity::Error::Collector(_) => println!("ERROR: Collector"),
|
||||
serenity::Error::Http(_) => println!("ERROR: Http"),
|
||||
serenity::Error::Tungstenite(_) => println!("ERROR: Tungstenite"),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
// Start the Bot.
|
||||
let client = serenity::ClientBuilder::new(env.token, env.intents)
|
||||
.framework(framework)
|
||||
.await;
|
||||
|
||||
client.unwrap().start().await.unwrap();
|
||||
}
|
||||
|
||||
struct BotEnv {
|
||||
|
Loading…
Reference in New Issue
Block a user