use redis::AsyncCommands; use sqlx::{query, query_as, types::Json}; use super::models::{Banner, File}; use crate::{ctx::Ctx, NekrochanError}; impl Banner { pub async fn create(ctx: &Ctx, banner: File) -> Result { let banner: Self = query_as("INSERT INTO banners (banner) VALUES ($1) RETURNING *") .bind(Json(banner)) .fetch_one(ctx.db()) .await?; ctx.cache() .zadd("banners", serde_json::to_string(&banner)?, banner.id) .await?; Ok(banner) } pub async fn read(ctx: &Ctx, id: i32) -> Result, NekrochanError> { let banners: Vec = ctx.cache().zrangebyscore("banners", id, id).await?; let json = banners.first(); let banner = match json { Some(json) => Some(serde_json::from_str(json)?), None => None, }; Ok(banner) } pub async fn read_all(ctx: &Ctx) -> Result, NekrochanError> { let banners_str: Vec = ctx.cache().zrange("banners", 0, -1).await?; let banners_json = format!("[{}]", banners_str.join(",")); // If it works, it works let banners = serde_json::from_str(&banners_json)?; Ok(banners) } pub async fn read_random(ctx: &Ctx) -> Result, NekrochanError> { let banner: Option = ctx.cache().zrandmember("banners", None).await?; let banner = match banner { Some(json) => Some(serde_json::from_str(&json)?), None => None, }; Ok(banner) } pub async fn remove(&self, ctx: &Ctx) -> Result<(), NekrochanError> { self.banner.delete().await; query("DELETE FROM banners WHERE id = $1") .bind(self.id) .execute(ctx.db()) .await?; ctx.cache().zrembyscore("banners", self.id, self.id).await?; Ok(()) } }