Poll fetching

This commit is contained in:
Natty 2023-11-02 00:22:04 +01:00
parent 5b9b813037
commit cf04146d2f
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
8 changed files with 108 additions and 14 deletions

View File

@ -1,5 +1,6 @@
pub mod emoji;
pub mod note_model;
pub mod poll;
pub use ck;
use ck::*;

View File

@ -0,0 +1,33 @@
use crate::{CalckeyDbError, CalckeyModel};
use ck::{poll, poll_vote};
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
pub struct PollResolver(CalckeyModel);
impl PollResolver {
pub fn new(db: CalckeyModel) -> Self {
PollResolver(db)
}
pub async fn get_poll(&self, note_id: &str) -> Result<Option<poll::Model>, CalckeyDbError> {
Ok(poll::Entity::find()
.filter(poll::Column::NoteId.eq(note_id))
.one(self.0.inner())
.await?)
}
pub async fn get_poll_votes_by(
&self,
note_id: &str,
user_id: &str,
) -> Result<Vec<poll_vote::Model>, CalckeyDbError> {
Ok(poll_vote::Entity::find()
.filter(
poll_vote::Column::NoteId
.eq(note_id)
.and(poll_vote::Column::UserId.eq(user_id)),
)
.all(self.0.inner())
.await?)
}
}

View File

@ -33,13 +33,13 @@ pub enum NoteVisibility {
pub struct PollChoice {
pub title: String,
pub votes_count: u64,
pub voted: bool,
pub voted: Option<bool>,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct PollBase {
pub expires_at: DateTime<Utc>,
pub expires_at: Option<DateTime<Utc>>,
pub expired: bool,
pub multiple_choice: bool,
pub options: Vec<PollChoice>,

View File

@ -17,3 +17,9 @@ macro_rules! impl_id {
impl_id!(ck::emoji::Model);
impl_id!(ck::user::Model);
impl_id!(ck::note::Model);
impl BaseId for ck::poll::Model {
fn get_id(&self) -> &str {
&self.note_id
}
}

View File

@ -2,4 +2,5 @@ pub mod drive;
pub mod emoji;
pub mod id;
pub mod note;
pub mod poll;
pub mod user;

27
src/model/data/poll.rs Normal file
View File

@ -0,0 +1,27 @@
use crate::model::{PackType, PackingContext};
use chrono::{DateTime, Utc};
use magnetar_calckey_model::ck;
use magnetar_sdk::types::note::{PollBase, PollChoice};
pub type PollPackInput<'a> = (&'a ck::poll::Model, Option<&'a [ck::poll_vote::Model]>);
impl PackType<PollPackInput<'_>> for PollBase {
fn extract(_context: &PackingContext, (poll, votes): PollPackInput<'_>) -> Self {
PollBase {
expires_at: poll.expires_at.map(DateTime::<Utc>::from),
expired: poll.expires_at.is_some_and(|e| e < Utc::now()),
multiple_choice: poll.multiple,
options: poll
.choices
.iter()
.zip(poll.votes.iter())
.enumerate()
.map(|(i, (name, count))| PollChoice {
title: name.to_string(),
votes_count: *count as u64,
voted: votes.map(|v| v.iter().any(|v| v.choice as usize == i)),
})
.collect(),
}
}
}

View File

@ -85,12 +85,8 @@ impl PackingContext {
return Ok(false);
};
self.is_relationship_between(
Either::Right(self_user.into()),
Either::Right(user.into()),
rel_type,
)
.await
self.is_relationship_between(Either::Right(self_user), Either::Right(user), rel_type)
.await
}
async fn is_relationship_between(

View File

@ -13,6 +13,7 @@ use magnetar_calckey_model::emoji::EmojiTag;
use magnetar_calckey_model::note_model::{
NoteData, NoteResolveOptions, NoteVisibilityFilterFactory,
};
use magnetar_calckey_model::poll::PollResolver;
use magnetar_calckey_model::sea_orm::prelude::Expr;
use magnetar_calckey_model::sea_orm::sea_query::{Alias, IntoIden, PgFunc, Query, SimpleExpr};
use magnetar_calckey_model::sea_orm::{ActiveEnum, ColumnTrait, IntoSimpleExpr};
@ -23,7 +24,7 @@ use magnetar_sdk::types::drive::PackDriveFileBase;
use magnetar_sdk::types::emoji::EmojiContext;
use magnetar_sdk::types::note::{
NoteAttachmentExt, NoteBase, NoteDetailExt, NoteSelfContextExt, PackNoteBase,
PackNoteMaybeAttachments, PackNoteMaybeFull, Reaction, ReactionPair,
PackNoteMaybeAttachments, PackNoteMaybeFull, PackPollBase, PollBase, Reaction, ReactionPair,
};
use magnetar_sdk::types::{Id, MmXml};
use magnetar_sdk::{mmm, Packed, Required};
@ -368,15 +369,44 @@ impl NoteModel {
Ok(None)
}
async fn extract_poll(
&self,
ctx: &PackingContext,
as_user: Option<&ck::user::Model>,
note: &ck::note::Model,
) -> PackResult<Option<PackPollBase>> {
if !note.has_poll {
return Ok(None);
}
let poll_resolver = PollResolver::new(ctx.service.db.clone());
let Some(poll) = poll_resolver.get_poll(&note.id).await? else {
return Ok(None);
};
let votes = match as_user {
Some(u) => Some(poll_resolver.get_poll_votes_by(&note.id, &u.id).await?),
None => None,
};
Ok(Some(PackPollBase::pack_from((
Required(Id::from(poll.get_id())),
Required(PollBase::extract(ctx, (&poll, votes.as_deref()))),
))))
}
async fn pack_single_attachments(
&self,
ctx: &PackingContext,
drive_model: &DriveModel,
as_user: Option<&ck::user::Model>,
note_data: &NoteData,
) -> PackResult<PackNoteMaybeAttachments> {
let (PackNoteBase { id, note }, attachments_pack) = try_join!(
let (PackNoteBase { id, note }, attachments_pack, poll_pack) = try_join!(
self.extract_base(ctx, note_data),
self.extract_attachments(ctx, drive_model, &note_data.note),
self.extract_poll(ctx, as_user, &note_data.note)
)?;
Ok(PackNoteMaybeAttachments::pack_from((
@ -388,7 +418,7 @@ impl NoteModel {
ctx,
NoteAttachmentSource {
attachments: &attachments,
poll: None, // TODO
poll: poll_pack.as_ref(),
},
)
}),
@ -428,7 +458,7 @@ impl NoteModel {
let reply_target = async {
match note.reply.as_ref() {
Some(r) if self.with_context => self
.pack_single_attachments(ctx, &drive_model, r)
.pack_single_attachments(ctx, &drive_model, as_user, r)
.await
.map(Some),
_ => Ok(None),
@ -438,7 +468,7 @@ impl NoteModel {
let renote_target = async {
match note.renote.as_ref() {
Some(r) if self.with_context => self
.pack_single_attachments(ctx, &drive_model, r)
.pack_single_attachments(ctx, &drive_model, as_user, r)
.await
.map(Some),
_ => Ok(None),
@ -455,7 +485,7 @@ impl NoteModel {
reply_target_pack,
renote_target_pack,
) = try_join!(
self.pack_single_attachments(ctx, &drive_model, &note),
self.pack_single_attachments(ctx, &drive_model, as_user, &note),
reply_target,
renote_target
)?;