about summary refs log tree commit diff
path: root/src/brain.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/brain.rs')
-rw-r--r--src/brain.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/brain.rs b/src/brain.rs
new file mode 100644
index 0000000..0ec6a59
--- /dev/null
+++ b/src/brain.rs
@@ -0,0 +1,125 @@
+use crate::database::Database;
+
+use twilight_cache_inmemory::DefaultInMemoryCache;
+use twilight_gateway::Event;
+use twilight_http::{Client as HttpClient, client::InteractionClient};
+use twilight_model::{
+	channel::message::Embed,
+	gateway::payload::incoming::InteractionCreate,
+	http::interaction::{InteractionResponse, InteractionResponseData, InteractionResponseType},
+	id::{
+		Id,
+		marker::{ChannelMarker, GuildMarker, MessageMarker, UserMarker},
+	},
+};
+const PROD_APP_ID: u64 = 1363055126264283136;
+const DEV_APP_ID: u64 = 1363494986699771984;
+const APP_ID: u64 = PROD_APP_ID;
+
+// A Absolutely Remarkably Terrible Thing
+macro_rules! aumau {
+	($meow:expr) => {
+		$meow.await.unwrap().model().await.unwrap()
+	};
+}
+
+pub struct Brain {
+	pub db: Database,
+	http: HttpClient,
+	cache: DefaultInMemoryCache,
+}
+
+impl Brain {
+	pub fn new(db: Database, http: HttpClient, cache: DefaultInMemoryCache) -> Self {
+		Self { db, http, cache }
+	}
+
+	pub fn update_cache(&self, event: &Event) {
+		self.cache.update(event);
+	}
+
+	/// Get the interaction client. Used for responding to interactions
+	pub fn interaction(&self) -> InteractionClient<'_> {
+		self.http.interaction(Id::new(APP_ID))
+	}
+
+	/// Respond to the interaction indicated by `create`. This method will
+	/// respond as an `InteractionResponseType::ChannelMessageWithSource`
+	pub async fn interaction_respond(
+		&self,
+		create: &InteractionCreate,
+		data: InteractionResponseData,
+	) {
+		self.interaction()
+			.create_response(
+				create.id,
+				&create.token,
+				&InteractionResponse {
+					kind: InteractionResponseType::ChannelMessageWithSource,
+					data: Some(data),
+				},
+			)
+			.await
+			.unwrap();
+	}
+
+	pub async fn send_message_with_embed<S: AsRef<str>>(
+		&self,
+		channel: Id<ChannelMarker>,
+		msg: S,
+		embed: Embed,
+	) -> Id<MessageMarker> {
+		aumau!(
+			self.http
+				.create_message(channel)
+				.embeds(&[embed])
+				.content(msg.as_ref())
+		)
+		.id
+	}
+
+	/// Retrieve information about a member of a guild. This method checks the
+	/// cache first, and then makes a request if it isn't there
+	pub async fn guild_member(&self, guild_id: Id<GuildMarker>, user_id: Id<UserMarker>) -> Member {
+		let user = self.cache.user(user_id);
+		let member = self.cache.member(guild_id, user_id);
+
+		match user.zip(member) {
+			Some((user, member)) => Member {
+				id: user_id,
+				handle: user.name.clone(),
+				global_name: user.global_name.clone(),
+				nick: member.nick().map(<_>::to_owned),
+			},
+			None => {
+				let member = aumau!(self.http.guild_member(guild_id, user_id));
+
+				Member {
+					id: user_id,
+					handle: member.user.name,
+					global_name: member.user.global_name,
+					nick: member.nick,
+				}
+			}
+		}
+	}
+
+	/// Check the database for a leaderboard belonging to this guild. If it
+	/// does not exist, create one. Returns whether or not one existed before
+	/// this function was called
+	pub fn create_leaderboard_if_not_exists(&self, guild: Id<GuildMarker>) -> bool {
+		if !self.db.leaderboard_exits(guild.get()) {
+			self.db.create_leaderboard(guild.get()).unwrap();
+			false
+		} else {
+			true
+		}
+	}
+}
+
+pub struct Member {
+	pub id: Id<UserMarker>,
+	pub handle: String,
+	pub global_name: Option<String>,
+	pub nick: Option<String>,
+}