chore: clean up some rust code

This commit is contained in:
alyssa 2025-12-20 22:55:25 -05:00
parent b19c900cc3
commit 578c09c216
15 changed files with 63 additions and 207 deletions

View file

@ -83,8 +83,8 @@ pub async fn discord_callback(
.expect("error making client"); .expect("error making client");
let reqbody = serde_urlencoded::to_string(&CallbackDiscordData { let reqbody = serde_urlencoded::to_string(&CallbackDiscordData {
client_id: config.discord.as_ref().unwrap().client_id.get().to_string(), client_id: config.discord().client_id.get().to_string(),
client_secret: config.discord.as_ref().unwrap().client_secret.clone(), client_secret: config.discord().client_secret.clone(),
grant_type: "authorization_code".to_string(), grant_type: "authorization_code".to_string(),
redirect_uri: request_data.redirect_domain, // change this! redirect_uri: request_data.redirect_domain, // change this!
code: request_data.code, code: request_data.code,

View file

@ -11,7 +11,8 @@ use hyper_util::{
client::legacy::{Client, connect::HttpConnector}, client::legacy::{Client, connect::HttpConnector},
rt::TokioExecutor, rt::TokioExecutor,
}; };
use tracing::info; use libpk::config;
use tracing::{info, warn};
use pk_macros::api_endpoint; use pk_macros::api_endpoint;
@ -128,7 +129,15 @@ fn router(ctx: ApiContext) -> Router {
.route("/v2/members/{member_id}/oembed.json", get(rproxy)) .route("/v2/members/{member_id}/oembed.json", get(rproxy))
.route("/v2/groups/{group_id}/oembed.json", get(rproxy)) .route("/v2/groups/{group_id}/oembed.json", get(rproxy))
.layer(middleware::ratelimit::ratelimiter(middleware::ratelimit::do_request_ratelimited)) // this sucks .layer(axum::middleware::from_fn_with_state(
if config.api().use_ratelimiter {
Some(ctx.redis.clone())
} else {
warn!("running without request rate limiting!");
None
},
middleware::ratelimit::do_request_ratelimited)
)
.layer(axum::middleware::from_fn(middleware::ignore_invalid_routes::ignore_invalid_routes)) .layer(axum::middleware::from_fn(middleware::ignore_invalid_routes::ignore_invalid_routes))
.layer(axum::middleware::from_fn_with_state(ctx.clone(), middleware::params::params)) .layer(axum::middleware::from_fn_with_state(ctx.clone(), middleware::params::params))
.layer(axum::middleware::from_fn_with_state(ctx.clone(), middleware::auth::auth)) .layer(axum::middleware::from_fn_with_state(ctx.clone(), middleware::auth::auth))
@ -146,14 +155,7 @@ async fn main() -> anyhow::Result<()> {
let db = libpk::db::init_data_db().await?; let db = libpk::db::init_data_db().await?;
let redis = libpk::db::init_redis().await?; let redis = libpk::db::init_redis().await?;
let rproxy_uri = Uri::from_static( let rproxy_uri = Uri::from_static(&libpk::config.api().remote_url).to_string();
&libpk::config
.api
.as_ref()
.expect("missing api config")
.remote_url,
)
.to_string();
let rproxy_client = hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new()) let rproxy_client = hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new())
.build(HttpConnector::new()); .build(HttpConnector::new());
@ -167,12 +169,7 @@ async fn main() -> anyhow::Result<()> {
let app = router(ctx); let app = router(ctx);
let addr: &str = libpk::config let addr: &str = libpk::config.api().addr.as_ref();
.api
.as_ref()
.expect("missing api config")
.addr
.as_ref();
let listener = tokio::net::TcpListener::bind(addr).await?; let listener = tokio::net::TcpListener::bind(addr).await?;
info!("listening on {}", addr); info!("listening on {}", addr);

View file

@ -44,12 +44,7 @@ pub async fn auth(State(ctx): State<ApiContext>, mut req: Request, next: Next) -
.get("x-pluralkit-app") .get("x-pluralkit-app")
.map(|h| h.to_str().ok()) .map(|h| h.to_str().ok())
.flatten() .flatten()
&& let Some(config_token2) = libpk::config && let Some(config_token2) = libpk::config.api().temp_token2.as_ref()
.api
.as_ref()
.expect("missing api config")
.temp_token2
.as_ref()
&& app_auth_header && app_auth_header
.as_bytes() .as_bytes()
.ct_eq(config_token2.as_bytes()) .ct_eq(config_token2.as_bytes())

View file

@ -3,12 +3,12 @@ use std::time::{Duration, SystemTime};
use axum::{ use axum::{
extract::{MatchedPath, Request, State}, extract::{MatchedPath, Request, State},
http::{HeaderValue, Method, StatusCode}, http::{HeaderValue, Method, StatusCode},
middleware::{FromFnLayer, Next}, middleware::Next,
response::Response, response::Response,
}; };
use fred::{clients::RedisPool, interfaces::ClientLike, prelude::LuaInterface, util::sha1_hash}; use fred::{clients::RedisPool, prelude::LuaInterface, util::sha1_hash};
use metrics::counter; use metrics::counter;
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info};
use crate::{ use crate::{
auth::AuthState, auth::AuthState,
@ -21,40 +21,6 @@ lazy_static::lazy_static! {
static ref LUA_SCRIPT_SHA: String = sha1_hash(LUA_SCRIPT); static ref LUA_SCRIPT_SHA: String = sha1_hash(LUA_SCRIPT);
} }
// this is awful but it works
pub fn ratelimiter<F, T>(f: F) -> FromFnLayer<F, Option<RedisPool>, T> {
let redis = libpk::config
.api
.as_ref()
.expect("missing api config")
.ratelimit_redis_addr
.as_ref()
.map(|val| {
// todo: this should probably use the global pool
let r = RedisPool::new(
fred::types::RedisConfig::from_url_centralized(val.as_ref())
.expect("redis url is invalid"),
None,
None,
Some(Default::default()),
10,
)
.expect("failed to connect to redis");
let handle = r.connect();
tokio::spawn(async move { handle });
r
});
if redis.is_none() {
warn!("running without request rate limiting!");
}
axum::middleware::from_fn_with_state(redis, f)
}
enum RatelimitType { enum RatelimitType {
GenericGet, GenericGet,
GenericUpdate, GenericUpdate,

View file

@ -1,30 +1,14 @@
use twilight_model::{ use twilight_model::application::command::CommandType;
application::command::{Command, CommandType},
guild::IntegrationApplication,
};
use twilight_util::builder::command::CommandBuilder; use twilight_util::builder::command::CommandBuilder;
#[libpk::main] #[libpk::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let discord = twilight_http::Client::builder() let discord = twilight_http::Client::builder()
.token( .token(libpk::config.discord().bot_token.clone())
libpk::config
.discord
.as_ref()
.expect("missing discord config")
.bot_token
.clone(),
)
.build(); .build();
let interaction = discord.interaction(twilight_model::id::Id::new( let interaction = discord.interaction(twilight_model::id::Id::new(
libpk::config libpk::config.discord().client_id.clone().get(),
.discord
.as_ref()
.expect("missing discord config")
.client_id
.clone()
.get(),
)); ));
let commands = vec![ let commands = vec![

View file

@ -6,10 +6,7 @@ use tracing::{error, info};
#[libpk::main] #[libpk::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let config = libpk::config let config = libpk::config.avatars();
.avatars
.as_ref()
.expect("missing avatar service config");
let bucket = { let bucket = {
let region = s3::Region::Custom { let region = s3::Region::Custom {
@ -83,10 +80,7 @@ async fn cleanup_job(pool: sqlx::PgPool, bucket: Arc<s3::Bucket>) -> anyhow::Res
} }
let image_data = image_data.unwrap(); let image_data = image_data.unwrap();
let config = libpk::config let config = libpk::config.avatars();
.avatars
.as_ref()
.expect("missing avatar service config");
let path = image_data let path = image_data
.url .url

View file

@ -172,10 +172,7 @@ pub struct AppState {
#[libpk::main] #[libpk::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let config = libpk::config let config = libpk::config.avatars();
.avatars
.as_ref()
.expect("missing avatar service config");
let bucket = { let bucket = {
let region = s3::Region::Custom { let region = s3::Region::Custom {

View file

@ -45,7 +45,7 @@ pub async fn run_server(cache: Arc<DiscordCache>, shard_state: Arc<ShardStateMan
.route( .route(
"/guilds/{guild_id}/members/@me", "/guilds/{guild_id}/members/@me",
get(|State(cache): State<Arc<DiscordCache>>, Path(guild_id): Path<u64>| async move { get(|State(cache): State<Arc<DiscordCache>>, Path(guild_id): Path<u64>| async move {
match cache.0.member(Id::new(guild_id), libpk::config.discord.as_ref().expect("missing discord config").client_id) { match cache.0.member(Id::new(guild_id), libpk::config.discord().client_id) {
Some(member) => status_code(StatusCode::FOUND, to_string(member.value()).unwrap()), Some(member) => status_code(StatusCode::FOUND, to_string(member.value()).unwrap()),
None => status_code(StatusCode::NOT_FOUND, "".to_string()), None => status_code(StatusCode::NOT_FOUND, "".to_string()),
} }
@ -54,7 +54,7 @@ pub async fn run_server(cache: Arc<DiscordCache>, shard_state: Arc<ShardStateMan
.route( .route(
"/guilds/{guild_id}/permissions/@me", "/guilds/{guild_id}/permissions/@me",
get(|State(cache): State<Arc<DiscordCache>>, Path(guild_id): Path<u64>| async move { get(|State(cache): State<Arc<DiscordCache>>, Path(guild_id): Path<u64>| async move {
match cache.guild_permissions(Id::new(guild_id), libpk::config.discord.as_ref().expect("missing discord config").client_id).await { match cache.guild_permissions(Id::new(guild_id), libpk::config.discord().client_id).await {
Ok(val) => { Ok(val) => {
status_code(StatusCode::FOUND, to_string(&val.bits()).unwrap()) status_code(StatusCode::FOUND, to_string(&val.bits()).unwrap())
}, },
@ -122,7 +122,7 @@ pub async fn run_server(cache: Arc<DiscordCache>, shard_state: Arc<ShardStateMan
if guild_id == 0 { if guild_id == 0 {
return status_code(StatusCode::FOUND, to_string(&*DM_PERMISSIONS).unwrap()); return status_code(StatusCode::FOUND, to_string(&*DM_PERMISSIONS).unwrap());
} }
match cache.channel_permissions(Id::new(channel_id), libpk::config.discord.as_ref().expect("missing discord config").client_id).await { match cache.channel_permissions(Id::new(channel_id), libpk::config.discord().client_id).await {
Ok(val) => status_code(StatusCode::FOUND, to_string(&val).unwrap()), Ok(val) => status_code(StatusCode::FOUND, to_string(&val).unwrap()),
Err(err) => { Err(err) => {
error!(?err, ?channel_id, ?guild_id, "failed to get own channelpermissions"); error!(?err, ?channel_id, ?guild_id, "failed to get own channelpermissions");
@ -219,7 +219,7 @@ pub async fn run_server(cache: Arc<DiscordCache>, shard_state: Arc<ShardStateMan
.layer(axum::middleware::from_fn(crate::logger::logger)) .layer(axum::middleware::from_fn(crate::logger::logger))
.with_state(cache); .with_state(cache);
let addr: &str = libpk::config.discord.as_ref().expect("missing discord config").cache_api_addr.as_ref(); let addr: &str = libpk::config.discord().cache_api_addr.as_ref();
let listener = tokio::net::TcpListener::bind(addr).await?; let listener = tokio::net::TcpListener::bind(addr).await?;
info!("listening on {}", addr); info!("listening on {}", addr);
axum::serve(listener, app.into_make_service_with_connect_info::<SocketAddr>()).await?; axum::serve(listener, app.into_make_service_with_connect_info::<SocketAddr>()).await?;

View file

@ -91,22 +91,10 @@ fn member_to_cached_member(item: Member, id: Id<UserMarker>) -> CachedMember {
} }
pub fn new() -> DiscordCache { pub fn new() -> DiscordCache {
let mut client_builder = twilight_http::Client::builder().token( let mut client_builder =
libpk::config twilight_http::Client::builder().token(libpk::config.discord().bot_token.clone());
.discord
.as_ref()
.expect("missing discord config")
.bot_token
.clone(),
);
if let Some(base_url) = libpk::config if let Some(base_url) = libpk::config.discord().api_base_url.clone() {
.discord
.as_ref()
.expect("missing discord config")
.api_base_url
.clone()
{
client_builder = client_builder.proxy(base_url, true).ratelimiter(None); client_builder = client_builder.proxy(base_url, true).ratelimiter(None);
} }
@ -268,13 +256,7 @@ impl DiscordCache {
return Ok(Permissions::all()); return Ok(Permissions::all());
} }
let member = if user_id let member = if user_id == libpk::config.discord().client_id {
== libpk::config
.discord
.as_ref()
.expect("missing discord config")
.client_id
{
self.0 self.0
.member(guild_id, user_id) .member(guild_id, user_id)
.ok_or(format_err!("self member not found"))? .ok_or(format_err!("self member not found"))?
@ -340,13 +322,7 @@ impl DiscordCache {
return Ok(Permissions::all()); return Ok(Permissions::all());
} }
let member = if user_id let member = if user_id == libpk::config.discord().client_id {
== libpk::config
.discord
.as_ref()
.expect("missing discord config")
.client_id
{
self.0 self.0
.member(guild_id, user_id) .member(guild_id, user_id)
.ok_or_else(|| { .ok_or_else(|| {

View file

@ -23,9 +23,7 @@ use super::cache::DiscordCache;
pub fn cluster_config() -> ClusterSettings { pub fn cluster_config() -> ClusterSettings {
libpk::config libpk::config
.discord .discord()
.as_ref()
.expect("missing discord config")
.cluster .cluster
.clone() .clone()
.unwrap_or(libpk::_config::ClusterSettings { .unwrap_or(libpk::_config::ClusterSettings {
@ -63,25 +61,12 @@ pub fn create_shards(redis: fred::clients::RedisPool) -> anyhow::Result<Vec<Shar
) )
}; };
let prefix = libpk::config let prefix = libpk::config.discord().bot_prefix_for_gateway.clone();
.discord
.as_ref()
.expect("missing discord config")
.bot_prefix_for_gateway
.clone();
let shards = create_iterator( let shards = create_iterator(
start_shard..end_shard + 1, start_shard..end_shard + 1,
cluster_settings.total_shards, cluster_settings.total_shards,
ConfigBuilder::new( ConfigBuilder::new(libpk::config.discord().bot_token.to_owned(), intents)
libpk::config
.discord
.as_ref()
.expect("missing discord config")
.bot_token
.to_owned(),
intents,
)
.presence(presence(format!("{prefix}help").as_str(), false)) .presence(presence(format!("{prefix}help").as_str(), false))
.queue(queue.clone()) .queue(queue.clone())
.build(), .build(),
@ -105,11 +90,7 @@ pub async fn runner(
// let _span = info_span!("shard_runner", shard_id = shard.id().number()).entered(); // let _span = info_span!("shard_runner", shard_id = shard.id().number()).entered();
let shard_id = shard.id().number(); let shard_id = shard.id().number();
let our_user_id = libpk::config let our_user_id = libpk::config.discord().client_id;
.discord
.as_ref()
.expect("missing discord config")
.client_id;
info!("waiting for events"); info!("waiting for events");
while let Some(item) = shard.next().await { while let Some(item) = shard.next().await {

View file

@ -13,11 +13,7 @@ use twilight_gateway::queue::Queue;
pub fn new(redis: RedisPool) -> RedisQueue { pub fn new(redis: RedisPool) -> RedisQueue {
RedisQueue { RedisQueue {
redis, redis,
concurrency: libpk::config concurrency: libpk::config.discord().max_concurrency,
.discord
.as_ref()
.expect("missing discord config")
.max_concurrency,
} }
} }

View file

@ -41,13 +41,7 @@ async fn main() -> anyhow::Result<()> {
); );
// hacky, but needed for selfhost for now // hacky, but needed for selfhost for now
if let Some(target) = libpk::config if let Some(target) = libpk::config.discord().gateway_target.clone() {
.discord
.as_ref()
.unwrap()
.gateway_target
.clone()
{
runtime_config runtime_config
.set(RUNTIME_CONFIG_KEY_EVENT_TARGET.to_string(), target) .set(RUNTIME_CONFIG_KEY_EVENT_TARGET.to_string(), target)
.await?; .await?;
@ -237,12 +231,7 @@ async fn main() -> anyhow::Result<()> {
} }
async fn scheduled_task(redis: RedisPool, senders: Vec<(ShardId, MessageSender)>) { async fn scheduled_task(redis: RedisPool, senders: Vec<(ShardId, MessageSender)>) {
let prefix = libpk::config let prefix = libpk::config.discord().bot_prefix_for_gateway.clone();
.discord
.as_ref()
.expect("missing discord config")
.bot_prefix_for_gateway
.clone();
println!("{prefix}"); println!("{prefix}");

View file

@ -14,23 +14,10 @@ async fn main() -> anyhow::Result<()> {
let db = libpk::db::init_messages_db().await?; let db = libpk::db::init_messages_db().await?;
let mut client_builder = twilight_http::Client::builder() let mut client_builder = twilight_http::Client::builder()
.token( .token(libpk::config.discord().bot_token.clone())
libpk::config
.discord
.as_ref()
.expect("missing discord config")
.bot_token
.clone(),
)
.timeout(Duration::from_secs(30)); .timeout(Duration::from_secs(30));
if let Some(base_url) = libpk::config if let Some(base_url) = libpk::config.discord().api_base_url.clone() {
.discord
.as_ref()
.expect("missing discord config")
.api_base_url
.clone()
{
client_builder = client_builder.proxy(base_url, true).ratelimiter(None); client_builder = client_builder.proxy(base_url, true).ratelimiter(None);
} }

View file

@ -56,7 +56,7 @@ pub struct ApiConfig {
pub addr: String, pub addr: String,
#[serde(default)] #[serde(default)]
pub ratelimit_redis_addr: Option<String>, pub use_ratelimiter: bool,
pub remote_url: String, pub remote_url: String,
@ -109,11 +109,11 @@ pub struct PKConfig {
pub db: DatabaseConfig, pub db: DatabaseConfig,
#[serde(default)] #[serde(default)]
pub discord: Option<DiscordConfig>, discord: Option<DiscordConfig>,
#[serde(default)] #[serde(default)]
pub api: Option<ApiConfig>, api: Option<ApiConfig>,
#[serde(default)] #[serde(default)]
pub avatars: Option<AvatarsConfig>, avatars: Option<AvatarsConfig>,
#[serde(default)] #[serde(default)]
pub scheduled_tasks: Option<ScheduledTasksConfig>, pub scheduled_tasks: Option<ScheduledTasksConfig>,
@ -134,12 +134,18 @@ pub struct PKConfig {
} }
impl PKConfig { impl PKConfig {
pub fn api(self) -> ApiConfig { pub fn api(&self) -> &ApiConfig {
self.api.expect("missing api config") self.api.as_ref().expect("missing api config")
} }
pub fn discord_config(self) -> DiscordConfig { pub fn discord(&self) -> &DiscordConfig {
self.discord.expect("missing discord config") self.discord.as_ref().expect("missing discord config")
}
pub fn avatars(&self) -> &AvatarsConfig {
self.avatars
.as_ref()
.expect("missing avatar service config")
} }
} }

View file

@ -22,22 +22,10 @@ pub struct AppCtx {
#[libpk::main] #[libpk::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let mut client_builder = twilight_http::Client::builder().token( let mut client_builder =
libpk::config twilight_http::Client::builder().token(libpk::config.discord().bot_token.clone());
.discord
.as_ref()
.expect("missing discord config")
.bot_token
.clone(),
);
if let Some(base_url) = libpk::config if let Some(base_url) = libpk::config.discord().api_base_url.clone() {
.discord
.as_ref()
.expect("missing discord config")
.api_base_url
.clone()
{
client_builder = client_builder.proxy(base_url, true).ratelimiter(None); client_builder = client_builder.proxy(base_url, true).ratelimiter(None);
} }