feat: now store the roles and channel ids in teh database
This commit is contained in:
parent
6a5f651ba2
commit
555e38ee26
3 changed files with 209 additions and 83 deletions
10
db/migrations/10_member_committee-roles.sql
Normal file
10
db/migrations/10_member_committee-roles.sql
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS committee_roles (
|
||||||
|
id_wolves integer PRIMARY KEY,
|
||||||
|
id_role integer DEFAULT 1,
|
||||||
|
id_channel integer DEFAULT 1,
|
||||||
|
-- not strictly required but for readability and debugging
|
||||||
|
name_role text NOT NULL DEFAULT '',
|
||||||
|
name_channel text NOT NULL DEFAULT '',
|
||||||
|
count integer DEFAULT 0
|
||||||
|
);
|
|
@ -190,14 +190,28 @@ impl<'r> FromRow<'r, SqliteRow> for RoleAdder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_role_from_row(row: &SqliteRow, col: &str) -> RoleId {
|
pub(crate) fn get_role_from_row(row: &SqliteRow, col: &str) -> RoleId {
|
||||||
match row.try_get(col) {
|
let id = match row.try_get(col) {
|
||||||
Ok(x) => {
|
Ok(x) => {
|
||||||
let tmp: i64 = x;
|
let tmp: i64 = x;
|
||||||
RoleId::new(tmp as u64)
|
tmp as u64
|
||||||
}
|
}
|
||||||
_ => RoleId::from(0u64),
|
_ => 0,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
RoleId::from(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_channel_from_row(row: &SqliteRow, col: &str) -> ChannelId {
|
||||||
|
let id = match row.try_get(col) {
|
||||||
|
Ok(x) => {
|
||||||
|
let tmp: i64 = x;
|
||||||
|
tmp as u64
|
||||||
|
}
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
ChannelId::from(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn db_init(config: &Config) -> Result<Pool<Sqlite>, Error> {
|
pub async fn db_init(config: &Config) -> Result<Pool<Sqlite>, Error> {
|
||||||
|
|
|
@ -131,9 +131,10 @@ pub mod normal {
|
||||||
|
|
||||||
// for updating committee members
|
// for updating committee members
|
||||||
pub mod committee {
|
pub mod committee {
|
||||||
use crate::common::database::{DataBase, Wolves};
|
use crate::common::database::{get_channel_from_row, get_role_from_row, DataBase, Wolves};
|
||||||
use crate::common::wolves::committees::Committees;
|
use crate::common::wolves::committees::Committees;
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::all::EditRole;
|
use serenity::all::EditRole;
|
||||||
use serenity::builder::CreateChannel;
|
use serenity::builder::CreateChannel;
|
||||||
use serenity::client::Context;
|
use serenity::client::Context;
|
||||||
|
@ -141,7 +142,8 @@ pub mod committee {
|
||||||
use serenity::model::guild::Member;
|
use serenity::model::guild::Member;
|
||||||
use serenity::model::id::ChannelId;
|
use serenity::model::id::ChannelId;
|
||||||
use serenity::model::prelude::RoleId;
|
use serenity::model::prelude::RoleId;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::sqlite::SqliteRow;
|
||||||
|
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -174,8 +176,7 @@ pub mod committee {
|
||||||
let server = config.committee_server;
|
let server = config.committee_server;
|
||||||
let committee_member = RoleId::new(1226602779968274573);
|
let committee_member = RoleId::new(1226602779968274573);
|
||||||
let committees = get_committees(db).await;
|
let committees = get_committees(db).await;
|
||||||
let categories = vec![
|
let categories = [
|
||||||
// C&S Chats 1
|
|
||||||
ChannelId::new(1226606560973815839),
|
ChannelId::new(1226606560973815839),
|
||||||
// C&S Chats 2
|
// C&S Chats 2
|
||||||
ChannelId::new(1341457244973305927),
|
ChannelId::new(1341457244973305927),
|
||||||
|
@ -184,35 +185,30 @@ pub mod committee {
|
||||||
];
|
];
|
||||||
|
|
||||||
// information about the server
|
// information about the server
|
||||||
let roles = server.roles(&ctx).await.unwrap_or_default();
|
let mut roles_db = HashMap::new();
|
||||||
let channels = server.channels(&ctx).await.unwrap_or_default();
|
for role in db_roles_get(db).await {
|
||||||
|
roles_db.insert(
|
||||||
// make a hashmap of the nameof roles to quickly get them out again
|
role.id_wolves,
|
||||||
let mut roles_name = HashMap::new();
|
CommitteeRoles {
|
||||||
for role in roles.values() {
|
id_wolves: role.id_wolves,
|
||||||
roles_name.insert(role.name.to_owned(), role.to_owned());
|
id_role: role.id_role,
|
||||||
|
id_channel: role.id_channel,
|
||||||
|
name_role: role.name_role,
|
||||||
|
name_channel: role.name_channel,
|
||||||
|
// always start at 0
|
||||||
|
count: 0,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut channels_name = HashMap::new();
|
let mut channels = server.channels(&ctx).await.unwrap_or_default();
|
||||||
for channel in channels.values() {
|
|
||||||
// we only care about teh channels in teh category
|
|
||||||
if let Some(x) = channel.parent_id {
|
|
||||||
for category in &categories {
|
|
||||||
if x.eq(category) {
|
|
||||||
channels_name.insert(channel.name.to_owned(), channel.to_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// a map of users and the roles they are goign to be getting
|
// a map of users and the roles they are goign to be getting
|
||||||
let mut users_roles = HashMap::new();
|
let mut users_roles = HashMap::new();
|
||||||
|
|
||||||
// a list of all the roles that can be removed from folks who should have them
|
let mut re_order = false;
|
||||||
let mut committee_roles = vec![committee_member];
|
// we need to create roles and channels if tehy dont already exist
|
||||||
|
|
||||||
let mut category_index = 0;
|
let mut category_index = 0;
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
if i >= committees.len() {
|
if i >= committees.len() {
|
||||||
|
@ -220,24 +216,17 @@ pub mod committee {
|
||||||
}
|
}
|
||||||
let committee = &committees[i];
|
let committee = &committees[i];
|
||||||
|
|
||||||
// get the role for this committee/club/soc
|
// if a club/soc ever changes their name
|
||||||
let role = match roles_name.get(&committee.name_full) {
|
if let Some(x) = roles_db.get_mut(&committee.id) {
|
||||||
Some(x) => Some(x.to_owned()),
|
x.name_role = committee.name_full.to_owned();
|
||||||
None => {
|
x.name_channel = committee.name_profile.to_owned();
|
||||||
// create teh role if it does not exist
|
}
|
||||||
match server
|
|
||||||
.create_role(&ctx, EditRole::new().name(&committee.name_full).hoist(false).mentionable(true))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(x) => Some(x),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// create teh channel if it does nto exist
|
// handle new clubs/socs
|
||||||
if !channels_name.contains_key(&committee.name_profile) {
|
if let std::collections::hash_map::Entry::Vacant(e) = roles_db.entry(committee.id) {
|
||||||
match server
|
// create channel
|
||||||
|
// channel is first as the categories can only contain 50 channels
|
||||||
|
let channel = match server
|
||||||
.create_channel(
|
.create_channel(
|
||||||
&ctx,
|
&ctx,
|
||||||
CreateChannel::new(&committee.name_profile)
|
CreateChannel::new(&committee.name_profile)
|
||||||
|
@ -247,40 +236,72 @@ pub mod committee {
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(x) => {
|
Ok(x) => {
|
||||||
// update teh channels name list
|
|
||||||
channels_name.insert(x.name.to_owned(), x.to_owned());
|
|
||||||
|
|
||||||
println!("Created channel: {}", &committee.name_profile);
|
println!("Created channel: {}", &committee.name_profile);
|
||||||
|
|
||||||
|
x.id
|
||||||
}
|
}
|
||||||
Err(x) => {
|
Err(x) => {
|
||||||
let tmp = x.to_string();
|
let tmp = x.to_string();
|
||||||
|
dbg!("Unable to create channel: ", &tmp, &tmp.contains("Maximum number of channels in category reached (50)"));
|
||||||
if x.to_string().contains("Maximum number of channels in category reached (50)") {
|
if x.to_string().contains("Maximum number of channels in category reached (50)") {
|
||||||
category_index += 1;
|
category_index += 1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dbg!("Unable to create channel: ", &tmp, &tmp.contains("Maximum number of channels in category reached (50)"));
|
ChannelId::new(1)
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// create role
|
||||||
|
let role = match server
|
||||||
|
.create_role(&ctx, EditRole::new().name(&committee.name_full).hoist(false).mentionable(true))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(x) => x.id,
|
||||||
|
Err(_) => RoleId::new(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
let tmp = CommitteeRoles {
|
||||||
|
id_wolves: committee.id,
|
||||||
|
id_role: role,
|
||||||
|
id_channel: channel,
|
||||||
|
name_role: committee.name_full.to_owned(),
|
||||||
|
name_channel: committee.name_profile.to_owned(),
|
||||||
|
count: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// save it to the db in case of crash or error
|
||||||
|
db_role_set(db, &tmp).await;
|
||||||
|
|
||||||
|
// insert it into teh local cache
|
||||||
|
e.insert(tmp);
|
||||||
|
|
||||||
|
re_order = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for committee in &committees {
|
||||||
|
let r = if let Some(x) = roles_db.get(&committee.id) {
|
||||||
|
x.id_role
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// so if the role exists
|
for id_wolves in &committee.committee {
|
||||||
if let Some(r) = role {
|
// ID in this is the wolves ID, so we need to get a matching discord ID (if one exists)
|
||||||
committee_roles.push(r.id);
|
if let Some(x) = get_server_member_discord(db, id_wolves).await {
|
||||||
|
if let Some(member_tmp) = x.discord {
|
||||||
|
let values = users_roles.entry(member_tmp).or_insert(vec![]);
|
||||||
|
values.push(r);
|
||||||
|
|
||||||
for id_wolves in &committee.committee {
|
if let Some(x) = roles_db.get_mut(&committee.id) {
|
||||||
// ID in this is the wolves ID, so we need to get a matching discord ID (if one exists)
|
x.count += 1;
|
||||||
if let Some(x) = get_server_member_discord(db, id_wolves).await {
|
|
||||||
if let Some(member_tmp) = x.discord {
|
|
||||||
let values = users_roles.entry(member_tmp).or_insert(vec![]);
|
|
||||||
values.push(r.id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we have a map of all users that should get roles time to go through all the folks on teh server
|
// now we have a map of all users that should get roles time to go through all the folks on teh server
|
||||||
|
@ -315,6 +336,10 @@ pub mod committee {
|
||||||
if !roles_required.is_empty() {
|
if !roles_required.is_empty() {
|
||||||
// if there are committee roles then give the general purporse role
|
// if there are committee roles then give the general purporse role
|
||||||
roles_add.push(committee_member);
|
roles_add.push(committee_member);
|
||||||
|
|
||||||
|
if let Some(x) = roles_db.get_mut(&0) {
|
||||||
|
x.count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for role in &roles_required {
|
for role in &roles_required {
|
||||||
|
@ -335,33 +360,110 @@ pub mod committee {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally re-order teh channels to make them visually apealing
|
let mut channel_names = vec![];
|
||||||
let mut channel_names = channels_name.clone().into_keys().collect::<Vec<String>>();
|
for role in roles_db.values() {
|
||||||
channel_names.sort();
|
// save these to db
|
||||||
|
db_role_set(db, role).await;
|
||||||
|
|
||||||
// get a list of all teh new positions
|
// pull out teh channel names
|
||||||
let mut new_positions = vec![];
|
if re_order {
|
||||||
for (i, name) in channel_names.iter().enumerate() {
|
channel_names.push((role.name_channel.to_owned(), role.id_channel));
|
||||||
if let Some(channel) = channels_name.get_mut(name) {
|
|
||||||
let position_new = i as u64;
|
|
||||||
if position_new != channel.position as u64 {
|
|
||||||
new_positions.push((channel.id.to_owned(), position_new));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !new_positions.is_empty() {
|
if re_order {
|
||||||
match server.reorder_channels(&ctx, new_positions).await {
|
channel_names.sort_by_key(|(name, _)| name.to_owned());
|
||||||
Ok(_) => {
|
|
||||||
println!("Successfully re-orderd the committee category");
|
// get a list of all teh new positions
|
||||||
|
let mut new_positions = vec![];
|
||||||
|
for (i, (_, id)) in channel_names.iter().enumerate() {
|
||||||
|
if let Some(channel) = channels.get_mut(id) {
|
||||||
|
let position_new = i as u64;
|
||||||
|
if position_new != channel.position as u64 {
|
||||||
|
new_positions.push((channel.id.to_owned(), position_new));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
}
|
||||||
dbg!("Failed to re-order ", e);
|
|
||||||
|
if !new_positions.is_empty() {
|
||||||
|
match server.reorder_channels(&ctx, new_positions).await {
|
||||||
|
Ok(_) => {
|
||||||
|
println!("Successfully re-orderd the committee category");
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
dbg!("Failed to re-order ", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
struct CommitteeRoles {
|
||||||
|
id_wolves: i64,
|
||||||
|
id_role: RoleId,
|
||||||
|
id_channel: ChannelId,
|
||||||
|
name_role: String,
|
||||||
|
name_channel: String,
|
||||||
|
count: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'r> FromRow<'r, SqliteRow> for CommitteeRoles {
|
||||||
|
fn from_row(row: &'r SqliteRow) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
id_wolves: row.try_get("id_wolves")?,
|
||||||
|
id_role: get_role_from_row(row, "id_role"),
|
||||||
|
id_channel: get_channel_from_row(row, "id_channel"),
|
||||||
|
name_role: row.try_get("name_role")?,
|
||||||
|
name_channel: row.try_get("name_channel")?,
|
||||||
|
count: row.try_get("count")?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn db_role_set(db: &Pool<Sqlite>, role: &CommitteeRoles) {
|
||||||
|
// expiry
|
||||||
|
match sqlx::query_as::<_, CommitteeRoles>(
|
||||||
|
"
|
||||||
|
INSERT INTO committee_roles (id_wolves, id_role, id_channel, name_role, name_channel, count)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
|
ON CONFLICT(id_wolves) DO UPDATE SET name_role = $4, name_channel = $4, count = $6
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.bind(role.id_wolves)
|
||||||
|
.bind(role.id_role.get() as i64)
|
||||||
|
.bind(role.id_channel.get() as i64)
|
||||||
|
.bind(&role.name_role)
|
||||||
|
.bind(&role.name_channel)
|
||||||
|
.bind(role.count)
|
||||||
|
.fetch_optional(db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failure to insert into Wolves {:?}", role);
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn db_roles_get(db: &Pool<Sqlite>) -> Vec<CommitteeRoles> {
|
||||||
|
// expiry
|
||||||
|
sqlx::query_as::<_, CommitteeRoles>(
|
||||||
|
"
|
||||||
|
SELECT *
|
||||||
|
FROM committee_roles
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.fetch_all(db)
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
println!("Failure to get Roles from committee_roles");
|
||||||
|
println!("{:?}", e);
|
||||||
|
vec![]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_committees(db: &Pool<Sqlite>) -> Vec<Committees> {
|
async fn get_committees(db: &Pool<Sqlite>) -> Vec<Committees> {
|
||||||
sqlx::query_as::<_, Committees>(
|
sqlx::query_as::<_, Committees>(
|
||||||
r#"
|
r#"
|
||||||
|
|
Loading…
Add table
Reference in a new issue