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]
|
[package]
|
||||||
name = "REPO-NAME"
|
name = "discord_egress"
|
||||||
authors = ["Oliver", "Oliver"]
|
authors = ["Oliver", "Oliver"]
|
||||||
description = "egress a discord server"
|
description = "egress a discord server"
|
||||||
repository = "https://git.oliveratkinson.net/Oliver/discord-egress.git"
|
repository = "https://git.oliveratkinson.net/Oliver/discord-egress.git"
|
||||||
@ -11,9 +11,6 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
||||||
# songbird = { version = "0.3.2", features = ["yt-dlp"] }
|
# 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"
|
dotenv = "0.15.0"
|
||||||
anyhow = "1.0.75"
|
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=""
|
ENV RUSTFLAGS=""
|
||||||
|
|
||||||
WORKDIR /bot
|
WORKDIR /bot
|
||||||
# RUN apt-get update && apt-get upgrade -y
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN cargo build --release
|
RUN cargo build --release
|
||||||
|
|
||||||
# Now make the runtime container
|
# Now make the runtime container
|
||||||
FROM debian:bookworm-slim
|
FROM debian:bookworm-slim
|
||||||
|
|
||||||
RUN apt-get update && apt-get upgrade -y && apt-get clean
|
COPY --from=builder /bot/target/release/discord_egress /usr/local/bin/discord_egress
|
||||||
COPY --from=builder /bot/target/release/REPO-NAME /usr/local/bin/REPO-NAME
|
|
||||||
COPY Cargo.lock /
|
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 std::fmt::Display;
|
||||||
use anyhow::Error;
|
|
||||||
use crate::Context;
|
|
||||||
|
|
||||||
// NOTE!!! Make sure these names in quotes are lowercase!
|
use crate::Context;
|
||||||
#[poise::command(slash_command, rename = "cmd_name", guild_only)]
|
use anyhow::Error;
|
||||||
pub async fn example(
|
use poise::serenity_prelude::{ChannelId, ChannelType, GuildChannel};
|
||||||
ctx: Context<'_>,
|
|
||||||
#[description = "cmd_desc"]
|
struct Server {
|
||||||
input: String
|
channels: Vec<Channel>,
|
||||||
) -> Result<(), Error> {
|
orphanage: Vec<GuildChannel>,
|
||||||
// Do something...
|
needs_clean: bool,
|
||||||
black_box(ctx);
|
|
||||||
black_box(input);
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
// Generate sick text like this:
|
||||||
// http://www.patorjk.com/software/taag/#p=testall&f=Graffiti&t=hello%20world
|
// http://www.patorjk.com/software/taag/#p=testall&f=Graffiti&t=hello%20world
|
||||||
println!(r#"
|
println!(r#"
|
||||||
/$$$$$$$$ /$$ /$$ /$$$$$$$ /$$
|
|
||||||
|__ $$__/ | $$ | $$ | $$__ $$ | $$
|
|
||||||
| $$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ | $$ /$$$$$$ /$$$$$$ /$$$$$$ | $$ \ $$ /$$$$$$ /$$$$$$
|
|
||||||
| $$ /$$__ $$| $$_ $$_ $$ /$$__ $$| $$ |____ $$|_ $$_/ /$$__ $$ | $$$$$$$ /$$__ $$|_ $$_/
|
|
||||||
| $$| $$$$$$$$| $$ \ $$ \ $$| $$ \ $$| $$ /$$$$$$$ | $$ | $$$$$$$$ | $$__ $$| $$ \ $$ | $$
|
|
||||||
| $$| $$_____/| $$ | $$ | $$| $$ | $$| $$ /$$__ $$ | $$ /$$| $$_____/ | $$ \ $$| $$ | $$ | $$ /$$
|
|
||||||
| $$| $$$$$$$| $$ | $$ | $$| $$$$$$$/| $$| $$$$$$$ | $$$$/| $$$$$$$ | $$$$$$$/| $$$$$$/ | $$$$/
|
|
||||||
|__/ \_______/|__/ |__/ |__/| $$____/ |__/ \_______/ \___/ \_______/ |_______/ \______/ \___/
|
|
||||||
| $$
|
|
||||||
| $$
|
|
||||||
|__/
|
|
||||||
|
|
||||||
Template Bot.
|
|
||||||
Invite this bot with:
|
Invite this bot with:
|
||||||
|
|
||||||
"#);
|
"#);
|
||||||
println!("https://discord.com/api/oauth2/authorize?client_id={}&permissions={}&scope=bot",
|
println!("https://discord.com/api/oauth2/authorize?client_id={}&permissions={}&scope=bot",
|
||||||
env.id,
|
env.id,
|
||||||
env.intents.bits(),
|
env.intents.bits(),
|
||||||
);
|
);
|
||||||
|
print!("\n");
|
||||||
|
|
||||||
|
// Setup framework
|
||||||
let framework = poise::Framework::builder()
|
let framework = poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions {
|
.options(poise::FrameworkOptions {
|
||||||
commands: vec![
|
commands: vec![
|
||||||
command::example(),
|
command::index(),
|
||||||
],
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
// un-comment songbird from Cargo.toml first.
|
|
||||||
//.client_settings(songbird::register)
|
|
||||||
.token(env.token)
|
|
||||||
.intents(env.intents)
|
|
||||||
.setup(|ctx, _ready, framework| {
|
.setup(|ctx, _ready, framework| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
poise::builtins::register_globally(
|
||||||
|
ctx,
|
||||||
|
&framework.options().commands
|
||||||
|
).await?;
|
||||||
Ok(Data {})
|
Ok(Data {})
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
// Start the Bot.
|
.build();
|
||||||
// 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),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(error) = err {
|
// Start the Bot.
|
||||||
match error {
|
let client = serenity::ClientBuilder::new(env.token, env.intents)
|
||||||
serenity::Error::Gateway(e)=>{
|
.framework(framework)
|
||||||
match e {
|
.await;
|
||||||
serenity::GatewayError::InvalidAuthentication => println!("ERROR: Authentication Invalid, check your bot token."),
|
|
||||||
err_no_var=>println!("ERROR: {}",err_no_var.to_string()),
|
client.unwrap().start().await.unwrap();
|
||||||
}
|
|
||||||
},
|
|
||||||
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!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BotEnv {
|
struct BotEnv {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user