Add social credit system
This commit is contained in:
parent
32fa1a11d1
commit
6b2d4641cc
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1093,7 +1093,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fren"
|
name = "fren"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum 0.8.1",
|
"axum 0.8.1",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fren"
|
name = "fren"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@ -7,8 +7,10 @@ use crate::models::lil_fren::{
|
|||||||
draw_resonance_cascade, draw_sick, draw_sleep, draw_standing, draw_tax_fraud,
|
draw_resonance_cascade, draw_sick, draw_sleep, draw_standing, draw_tax_fraud,
|
||||||
};
|
};
|
||||||
use crate::models::managed_roles::ManagedRole;
|
use crate::models::managed_roles::ManagedRole;
|
||||||
|
use crate::models::social_credit::SocialCreditPhrase;
|
||||||
use crate::models::task::Task;
|
use crate::models::task::Task;
|
||||||
use crate::user::User;
|
use crate::user::User;
|
||||||
|
use j_db::model::JdbModel;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use log::info;
|
use log::info;
|
||||||
use poise::serenity_prelude::{
|
use poise::serenity_prelude::{
|
||||||
@ -263,3 +265,66 @@ pub async fn remove_role(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a phrase to check for social credit
|
||||||
|
#[poise::command(prefix_command, category = "Admin", check = "is_admin")]
|
||||||
|
pub async fn add_social_credit_phrase(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "Phrase to look for, wrap in \"s if you want multiple words"] phrase: String,
|
||||||
|
#[description = "Upper limit of points to add/take away"] upper_limit: i64,
|
||||||
|
#[description = "Lower limit of points to take away"] lower_limit: i64,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let social_credit_phrase =
|
||||||
|
SocialCreditPhrase::add_new_phrase(&ctx.data().db, phrase, upper_limit, lower_limit)?;
|
||||||
|
|
||||||
|
ctx.reply(format!(
|
||||||
|
"Added new phrase '{}' with id `{}`",
|
||||||
|
social_credit_phrase.phrase,
|
||||||
|
social_credit_phrase.id().unwrap()
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a social credit phrase
|
||||||
|
#[poise::command(prefix_command, category = "Admin", check = "is_admin")]
|
||||||
|
pub async fn remove_social_credit_phrase(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "ID of the phrase to remove"] id: u64,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let social_credit_phrase = ctx.data().db.remove::<SocialCreditPhrase>(id)?;
|
||||||
|
|
||||||
|
ctx.reply(format!(
|
||||||
|
"Removed phrase '{}' with id `{}`",
|
||||||
|
social_credit_phrase.phrase,
|
||||||
|
social_credit_phrase.id().unwrap()
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List social credit phrases
|
||||||
|
#[poise::command(prefix_command, category = "Admin", check = "is_admin")]
|
||||||
|
pub async fn list_social_credit_phrases(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
let social_credit_phrase = SocialCreditPhrase::get_phrases(&ctx.data().db)?;
|
||||||
|
|
||||||
|
let mut list = MessageBuilder::new();
|
||||||
|
|
||||||
|
list.push_line("The following phrases are EXAMINED for their value for the state:");
|
||||||
|
|
||||||
|
for phrase in &social_credit_phrase {
|
||||||
|
list.push_line(format!(
|
||||||
|
"* id={} phrase={} upper_bound={} lower_bound={}",
|
||||||
|
phrase.id().unwrap(),
|
||||||
|
phrase.phrase,
|
||||||
|
phrase.upper_bound,
|
||||||
|
phrase.lower_bound
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reply(list.build()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@ -64,6 +64,51 @@ pub async fn gift(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find your social worth in the eyes of the glorious part
|
||||||
|
#[poise::command(prefix_command, category = "Fren Coin")]
|
||||||
|
pub async fn social_credit(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "User to get the social credit of"] user: Option<poise::serenity_prelude::User>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let user_id = user.map(|u| u.id).unwrap_or(ctx.author().id);
|
||||||
|
|
||||||
|
let user = User::get_user(&ctx.data().db, user_id)?;
|
||||||
|
|
||||||
|
let msg = if user.social_credit < -2000 {
|
||||||
|
"||REDACTED||"
|
||||||
|
} else if user.social_credit < -1000 {
|
||||||
|
"Very bad person they are!"
|
||||||
|
} else if user.social_credit < -500 {
|
||||||
|
"Likely a capitalist!"
|
||||||
|
} else if user.social_credit < -100 {
|
||||||
|
"Tread carefully..."
|
||||||
|
} else if user.social_credit < 0 {
|
||||||
|
"There is always a chance, before its too late..."
|
||||||
|
} else if user.social_credit < 100 {
|
||||||
|
"Okay, but be cautious with your words."
|
||||||
|
} else if user.social_credit < 500 {
|
||||||
|
"There is only winners and losers."
|
||||||
|
} else if user.social_credit < 1000 {
|
||||||
|
"On the up and up!"
|
||||||
|
} else if user.social_credit < 2000 {
|
||||||
|
"A great member of our glorious society!"
|
||||||
|
} else if user.social_credit >= 2000 {
|
||||||
|
"Perfect in every way, may your deeds shine light in our world!!!"
|
||||||
|
} else {
|
||||||
|
"There is no god for you."
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.reply(format!(
|
||||||
|
"{}'s social credit is {}. {}",
|
||||||
|
user_id.mention(),
|
||||||
|
user.social_credit,
|
||||||
|
msg
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn give_coin(
|
pub async fn give_coin(
|
||||||
db: &Database,
|
db: &Database,
|
||||||
user: UserId,
|
user: UserId,
|
||||||
|
|||||||
@ -18,12 +18,14 @@ use crate::discord::fren_coin::give_coin;
|
|||||||
use crate::discord::joke::random;
|
use crate::discord::joke::random;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::models::lil_fren::lil_fren_task;
|
use crate::models::lil_fren::lil_fren_task;
|
||||||
|
use crate::models::social_credit::SocialCreditPhrase;
|
||||||
use crate::models::task::Task;
|
use crate::models::task::Task;
|
||||||
use log::{error, info};
|
use crate::user::User;
|
||||||
|
use log::{debug, error, info};
|
||||||
use poise::serenity_prelude::{GuildId, Http, Message, MessageBuilder, ReactionType, RoleId};
|
use poise::serenity_prelude::{GuildId, Http, Message, MessageBuilder, ReactionType, RoleId};
|
||||||
use poise::{FrameworkOptions, find_command, serenity_prelude as serenity};
|
use poise::{FrameworkOptions, find_command, serenity_prelude as serenity};
|
||||||
use rand::prelude::IteratorRandom;
|
use rand::prelude::IteratorRandom;
|
||||||
use rand::rng;
|
use rand::{Rng, rng};
|
||||||
use songbird::SerenityInit;
|
use songbird::SerenityInit;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -81,6 +83,18 @@ async fn handle_message(
|
|||||||
data: &Arc<GlobalData>,
|
data: &Arc<GlobalData>,
|
||||||
new_message: &Message,
|
new_message: &Message,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
if new_message.content.eq_ignore_ascii_case("yes")
|
||||||
|
|| new_message.content.eq_ignore_ascii_case("mhmm")
|
||||||
|
{
|
||||||
|
let mut bot_state = data.bot_state.lock().await;
|
||||||
|
if let Some(u) = bot_state.accepted_nsfw {
|
||||||
|
if new_message.author.id == u {
|
||||||
|
new_message.reply(&ctx.http, "||https://cdn.discordapp.com/attachments/614891432079130625/1041545254362423368/unknown.png||").await.unwrap();
|
||||||
|
bot_state.accepted_nsfw = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if new_message.content.to_lowercase().contains("good bot") {
|
if new_message.content.to_lowercase().contains("good bot") {
|
||||||
let recv_coin = give_coin(&data.db, new_message.author.id, 0.50, 25).await?;
|
let recv_coin = give_coin(&data.db, new_message.author.id, 0.50, 25).await?;
|
||||||
|
|
||||||
@ -113,6 +127,18 @@ async fn handle_message(
|
|||||||
|
|
||||||
give_coin(&data.db, new_message.author.id, 0.05, 10).await?;
|
give_coin(&data.db, new_message.author.id, 0.05, 10).await?;
|
||||||
|
|
||||||
|
if let Some(phrase) = SocialCreditPhrase::check_if_match(&data.db, &new_message.content)? {
|
||||||
|
debug!(
|
||||||
|
"{} matched phrase '{}' for social credit checking",
|
||||||
|
new_message.author.name, phrase.phrase
|
||||||
|
);
|
||||||
|
|
||||||
|
let social_credit_change =
|
||||||
|
rand::rng().random_range(phrase.lower_bound..=phrase.upper_bound);
|
||||||
|
|
||||||
|
User::update_social_credit(&data.db, new_message.author.id, social_credit_change)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,6 +301,9 @@ pub async fn run_bot(global_data: GlobalData) {
|
|||||||
admin::list_tasks(),
|
admin::list_tasks(),
|
||||||
admin::add_role(),
|
admin::add_role(),
|
||||||
admin::remove_role(),
|
admin::remove_role(),
|
||||||
|
admin::add_social_credit_phrase(),
|
||||||
|
admin::remove_social_credit_phrase(),
|
||||||
|
admin::list_social_credit_phrases(),
|
||||||
album::add_image(),
|
album::add_image(),
|
||||||
album::list_albums(),
|
album::list_albums(),
|
||||||
birthday::add_birthday(),
|
birthday::add_birthday(),
|
||||||
@ -289,6 +318,7 @@ pub async fn run_bot(global_data: GlobalData) {
|
|||||||
emoji_race::start_race(),
|
emoji_race::start_race(),
|
||||||
fren_coin::balance(),
|
fren_coin::balance(),
|
||||||
fren_coin::gift(),
|
fren_coin::gift(),
|
||||||
|
fren_coin::social_credit(),
|
||||||
joke::add_random(),
|
joke::add_random(),
|
||||||
joke::dad_joke(),
|
joke::dad_joke(),
|
||||||
joke::bad_apple(),
|
joke::bad_apple(),
|
||||||
|
|||||||
30
src/migrations/migration_6_add_social_credit.rs
Normal file
30
src/migrations/migration_6_add_social_credit.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use j_db::database::Database;
|
||||||
|
use j_db::migration::Migration;
|
||||||
|
|
||||||
|
pub struct Migration6AddSocialCredit {}
|
||||||
|
|
||||||
|
impl Migration for Migration6AddSocialCredit {
|
||||||
|
fn up(&self, db: &Database) -> j_db::error::Result<()> {
|
||||||
|
let tree = db.db.open_tree("Users")?;
|
||||||
|
|
||||||
|
for user_entry in tree.iter() {
|
||||||
|
let (id, user) = user_entry?;
|
||||||
|
|
||||||
|
let mut user = json::parse(std::str::from_utf8(&user).unwrap()).unwrap();
|
||||||
|
|
||||||
|
user["social_credit"] = json::JsonValue::Number(json::number::Number::from(1000));
|
||||||
|
|
||||||
|
tree.insert(id, user.to_string().as_bytes())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn down(&self, _db: &Database) -> j_db::error::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version(&self) -> u64 {
|
||||||
|
6
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
use crate::migrations::migration_4_update_random::Migration4UpdateRandoms;
|
use crate::migrations::migration_4_update_random::Migration4UpdateRandoms;
|
||||||
use crate::migrations::migration_5_update_motivation::Migration5UpdateMotivation;
|
use crate::migrations::migration_5_update_motivation::Migration5UpdateMotivation;
|
||||||
|
use crate::migrations::migration_6_add_social_credit::Migration6AddSocialCredit;
|
||||||
use crate::migrations::migration2_remove_imgur::Migration2RemoveImgur;
|
use crate::migrations::migration2_remove_imgur::Migration2RemoveImgur;
|
||||||
use crate::migrations::migration3_remove_img::Migration3RemoveImage;
|
use crate::migrations::migration3_remove_img::Migration3RemoveImage;
|
||||||
use j_db::database::Database;
|
use j_db::database::Database;
|
||||||
@ -10,8 +11,9 @@ mod migration2_remove_imgur;
|
|||||||
mod migration3_remove_img;
|
mod migration3_remove_img;
|
||||||
mod migration_4_update_random;
|
mod migration_4_update_random;
|
||||||
mod migration_5_update_motivation;
|
mod migration_5_update_motivation;
|
||||||
|
mod migration_6_add_social_credit;
|
||||||
|
|
||||||
pub const CURRENT_DB_VERSION: u64 = 5;
|
pub const CURRENT_DB_VERSION: u64 = 6;
|
||||||
|
|
||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
pub fn do_migration(db: &Database) {
|
pub fn do_migration(db: &Database) {
|
||||||
@ -48,6 +50,12 @@ pub fn do_migration(db: &Database) {
|
|||||||
Direction::Up,
|
Direction::Up,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
6 => migration::do_migration::<Migration6AddSocialCredit>(
|
||||||
|
db,
|
||||||
|
Migration6AddSocialCredit {},
|
||||||
|
Direction::Up,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,4 +6,5 @@ pub mod managed_roles;
|
|||||||
pub mod motivation;
|
pub mod motivation;
|
||||||
pub mod race;
|
pub mod race;
|
||||||
pub mod random;
|
pub mod random;
|
||||||
|
pub mod social_credit;
|
||||||
pub mod task;
|
pub mod task;
|
||||||
|
|||||||
62
src/models/social_credit.rs
Normal file
62
src/models/social_credit.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
use crate::error::Error;
|
||||||
|
use j_db::database::Database;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
|
pub struct SocialCreditPhrase {
|
||||||
|
id: Option<u64>,
|
||||||
|
pub phrase: String,
|
||||||
|
pub lower_bound: i64,
|
||||||
|
pub upper_bound: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl j_db::model::JdbModel for SocialCreditPhrase {
|
||||||
|
fn id(&self) -> Option<u64> {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_id(&mut self, id: u64) {
|
||||||
|
self.id = Some(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree() -> String {
|
||||||
|
"SocialCreditPhrase".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_unique(&self, other: &Self) -> bool {
|
||||||
|
other.phrase.to_lowercase() == self.phrase.to_lowercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SocialCreditPhrase {
|
||||||
|
pub fn check_if_match(db: &Database, msg: &str) -> Result<Option<Self>, Error> {
|
||||||
|
let lowercase_msg = msg.to_lowercase();
|
||||||
|
let matches = db
|
||||||
|
.filter(|_, phrase: &Self| lowercase_msg.contains(&phrase.phrase.to_lowercase()))?
|
||||||
|
.next();
|
||||||
|
|
||||||
|
Ok(matches)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_new_phrase(
|
||||||
|
db: &Database,
|
||||||
|
phrase: String,
|
||||||
|
lower_bound: i64,
|
||||||
|
upper_bound: i64,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let new_phrase = db.insert(Self {
|
||||||
|
id: None,
|
||||||
|
phrase,
|
||||||
|
lower_bound,
|
||||||
|
upper_bound,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(new_phrase)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_phrases(db: &Database) -> Result<Vec<Self>, Error> {
|
||||||
|
let phrases = db.filter(|_, _phrase: &Self| true)?.collect();
|
||||||
|
|
||||||
|
Ok(phrases)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,7 @@ pub struct User {
|
|||||||
pub id: Option<u64>,
|
pub id: Option<u64>,
|
||||||
pub user_id: UserId,
|
pub user_id: UserId,
|
||||||
pub coin_count: i64,
|
pub coin_count: i64,
|
||||||
|
pub social_credit: i64,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub inventory: InventoryManager,
|
pub inventory: InventoryManager,
|
||||||
}
|
}
|
||||||
@ -46,6 +47,7 @@ impl User {
|
|||||||
id: None,
|
id: None,
|
||||||
user_id,
|
user_id,
|
||||||
coin_count: 0,
|
coin_count: 0,
|
||||||
|
social_credit: 1000,
|
||||||
inventory: Default::default(),
|
inventory: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,6 +203,15 @@ impl User {
|
|||||||
db.insert::<User>(buyer)?;
|
db.insert::<User>(buyer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_social_credit(db: &Database, user: UserId, amount: i64) -> Result<(), Error> {
|
||||||
|
let mut user = User::get_user(db, user)?;
|
||||||
|
|
||||||
|
user.social_credit += amount;
|
||||||
|
|
||||||
|
db.insert::<User>(user)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JdbModel for User {
|
impl JdbModel for User {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user