Poll fetching
This commit is contained in:
parent
5b9b813037
commit
cf04146d2f
|
@ -1,5 +1,6 @@
|
||||||
pub mod emoji;
|
pub mod emoji;
|
||||||
pub mod note_model;
|
pub mod note_model;
|
||||||
|
pub mod poll;
|
||||||
|
|
||||||
pub use ck;
|
pub use ck;
|
||||||
use ck::*;
|
use ck::*;
|
||||||
|
|
|
@ -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?)
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,13 +33,13 @@ pub enum NoteVisibility {
|
||||||
pub struct PollChoice {
|
pub struct PollChoice {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub votes_count: u64,
|
pub votes_count: u64,
|
||||||
pub voted: bool,
|
pub voted: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct PollBase {
|
pub struct PollBase {
|
||||||
pub expires_at: DateTime<Utc>,
|
pub expires_at: Option<DateTime<Utc>>,
|
||||||
pub expired: bool,
|
pub expired: bool,
|
||||||
pub multiple_choice: bool,
|
pub multiple_choice: bool,
|
||||||
pub options: Vec<PollChoice>,
|
pub options: Vec<PollChoice>,
|
||||||
|
|
|
@ -17,3 +17,9 @@ macro_rules! impl_id {
|
||||||
impl_id!(ck::emoji::Model);
|
impl_id!(ck::emoji::Model);
|
||||||
impl_id!(ck::user::Model);
|
impl_id!(ck::user::Model);
|
||||||
impl_id!(ck::note::Model);
|
impl_id!(ck::note::Model);
|
||||||
|
|
||||||
|
impl BaseId for ck::poll::Model {
|
||||||
|
fn get_id(&self) -> &str {
|
||||||
|
&self.note_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,4 +2,5 @@ pub mod drive;
|
||||||
pub mod emoji;
|
pub mod emoji;
|
||||||
pub mod id;
|
pub mod id;
|
||||||
pub mod note;
|
pub mod note;
|
||||||
|
pub mod poll;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
|
@ -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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,12 +85,8 @@ impl PackingContext {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.is_relationship_between(
|
self.is_relationship_between(Either::Right(self_user), Either::Right(user), rel_type)
|
||||||
Either::Right(self_user.into()),
|
.await
|
||||||
Either::Right(user.into()),
|
|
||||||
rel_type,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_relationship_between(
|
async fn is_relationship_between(
|
||||||
|
|
|
@ -13,6 +13,7 @@ use magnetar_calckey_model::emoji::EmojiTag;
|
||||||
use magnetar_calckey_model::note_model::{
|
use magnetar_calckey_model::note_model::{
|
||||||
NoteData, NoteResolveOptions, NoteVisibilityFilterFactory,
|
NoteData, NoteResolveOptions, NoteVisibilityFilterFactory,
|
||||||
};
|
};
|
||||||
|
use magnetar_calckey_model::poll::PollResolver;
|
||||||
use magnetar_calckey_model::sea_orm::prelude::Expr;
|
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::sea_query::{Alias, IntoIden, PgFunc, Query, SimpleExpr};
|
||||||
use magnetar_calckey_model::sea_orm::{ActiveEnum, ColumnTrait, IntoSimpleExpr};
|
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::emoji::EmojiContext;
|
||||||
use magnetar_sdk::types::note::{
|
use magnetar_sdk::types::note::{
|
||||||
NoteAttachmentExt, NoteBase, NoteDetailExt, NoteSelfContextExt, PackNoteBase,
|
NoteAttachmentExt, NoteBase, NoteDetailExt, NoteSelfContextExt, PackNoteBase,
|
||||||
PackNoteMaybeAttachments, PackNoteMaybeFull, Reaction, ReactionPair,
|
PackNoteMaybeAttachments, PackNoteMaybeFull, PackPollBase, PollBase, Reaction, ReactionPair,
|
||||||
};
|
};
|
||||||
use magnetar_sdk::types::{Id, MmXml};
|
use magnetar_sdk::types::{Id, MmXml};
|
||||||
use magnetar_sdk::{mmm, Packed, Required};
|
use magnetar_sdk::{mmm, Packed, Required};
|
||||||
|
@ -368,15 +369,44 @@ impl NoteModel {
|
||||||
Ok(None)
|
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(¬e.id).await? else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let votes = match as_user {
|
||||||
|
Some(u) => Some(poll_resolver.get_poll_votes_by(¬e.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(
|
async fn pack_single_attachments(
|
||||||
&self,
|
&self,
|
||||||
ctx: &PackingContext,
|
ctx: &PackingContext,
|
||||||
drive_model: &DriveModel,
|
drive_model: &DriveModel,
|
||||||
|
as_user: Option<&ck::user::Model>,
|
||||||
note_data: &NoteData,
|
note_data: &NoteData,
|
||||||
) -> PackResult<PackNoteMaybeAttachments> {
|
) -> 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_base(ctx, note_data),
|
||||||
self.extract_attachments(ctx, drive_model, ¬e_data.note),
|
self.extract_attachments(ctx, drive_model, ¬e_data.note),
|
||||||
|
self.extract_poll(ctx, as_user, ¬e_data.note)
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(PackNoteMaybeAttachments::pack_from((
|
Ok(PackNoteMaybeAttachments::pack_from((
|
||||||
|
@ -388,7 +418,7 @@ impl NoteModel {
|
||||||
ctx,
|
ctx,
|
||||||
NoteAttachmentSource {
|
NoteAttachmentSource {
|
||||||
attachments: &attachments,
|
attachments: &attachments,
|
||||||
poll: None, // TODO
|
poll: poll_pack.as_ref(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
@ -428,7 +458,7 @@ impl NoteModel {
|
||||||
let reply_target = async {
|
let reply_target = async {
|
||||||
match note.reply.as_ref() {
|
match note.reply.as_ref() {
|
||||||
Some(r) if self.with_context => self
|
Some(r) if self.with_context => self
|
||||||
.pack_single_attachments(ctx, &drive_model, r)
|
.pack_single_attachments(ctx, &drive_model, as_user, r)
|
||||||
.await
|
.await
|
||||||
.map(Some),
|
.map(Some),
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
|
@ -438,7 +468,7 @@ impl NoteModel {
|
||||||
let renote_target = async {
|
let renote_target = async {
|
||||||
match note.renote.as_ref() {
|
match note.renote.as_ref() {
|
||||||
Some(r) if self.with_context => self
|
Some(r) if self.with_context => self
|
||||||
.pack_single_attachments(ctx, &drive_model, r)
|
.pack_single_attachments(ctx, &drive_model, as_user, r)
|
||||||
.await
|
.await
|
||||||
.map(Some),
|
.map(Some),
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
|
@ -455,7 +485,7 @@ impl NoteModel {
|
||||||
reply_target_pack,
|
reply_target_pack,
|
||||||
renote_target_pack,
|
renote_target_pack,
|
||||||
) = try_join!(
|
) = try_join!(
|
||||||
self.pack_single_attachments(ctx, &drive_model, ¬e),
|
self.pack_single_attachments(ctx, &drive_model, as_user, ¬e),
|
||||||
reply_target,
|
reply_target,
|
||||||
renote_target
|
renote_target
|
||||||
)?;
|
)?;
|
||||||
|
|
Loading…
Reference in New Issue