From 83f5f89df516a6b0a8135518a4969032dd00048a Mon Sep 17 00:00:00 2001 From: Namekuji Date: Fri, 18 Aug 2023 00:24:24 -0400 Subject: [PATCH] fix poll --- .../cql/1689400417034_timeline/up.cql | 4 +- .../scylla-migration/src/setup.rs | 10 ++-- .../backend/src/models/repositories/note.ts | 50 ++++++++++++++++++- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql b/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql index 6bc105f5d5..6be4bc2fbe 100644 --- a/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql +++ b/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql @@ -56,7 +56,7 @@ CREATE TABLE IF NOT EXISTS note ( -- Store all posts "emojis" set, "tags" set, "hasPoll" boolean, - "poll" poll, + "poll" frozen, "threadId" ascii, "channelId" ascii, -- Channel "userId" ascii, -- User @@ -179,7 +179,7 @@ CREATE TABLE IF NOT EXISTS home_timeline ( "emojis" set, "tags" set, "hasPoll" boolean, - "poll" poll, + "poll" frozen, "threadId" ascii, "channelId" ascii, -- Channel "userId" ascii, -- User diff --git a/packages/backend/native-utils/scylla-migration/src/setup.rs b/packages/backend/native-utils/scylla-migration/src/setup.rs index 196258c712..d1b98c908c 100644 --- a/packages/backend/native-utils/scylla-migration/src/setup.rs +++ b/packages/backend/native-utils/scylla-migration/src/setup.rs @@ -38,8 +38,6 @@ impl Initializer { } pub(crate) async fn setup(&self) -> Result<(), Error> { - const DROP_CONSTRAINT: &str = "ALTER TABLE ? DROP CONSTRAINT ?"; - let pairs = vec![ ("channel_note_pining", "FK_10b19ef67d297ea9de325cd4502"), ("clip_note", "FK_a012eaf5c87c65da1deb5fdbfa3"), @@ -47,16 +45,18 @@ impl Initializer { ("note_edit", "FK_702ad5ae993a672e4fbffbcd38c"), ("note_favorite", "FK_0e00498f180193423c992bc4370"), ("note_unread", "FK_e637cba4dc4410218c4251260e4"), - ("note_wathing", "FK_03e7028ab8388a3f5e3ce2a8619"), + ("note_watching", "FK_03e7028ab8388a3f5e3ce2a8619"), ("promo_note", "FK_e263909ca4fe5d57f8d4230dd5c"), ("promo_read", "FK_a46a1a603ecee695d7db26da5f4"), - ("user_note_pining", "FK_68881008f7c3588ad7ecae471cf") + ("user_note_pining", "FK_68881008f7c3588ad7ecae471cf"), ]; let mut conn = PgConnection::connect(&self.postgres_url).await?; for (table, fk) in pairs { - sqlx::query(DROP_CONSTRAINT).bind(table).bind(fk).execute(&mut conn).await?; + sqlx::query(&format!("ALTER TABLE {} DROP CONSTRAINT \"{}\"", table, fk)) + .execute(&mut conn) + .await?; } Ok(()) diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index 5e8b5ca480..d1ef7ffcb0 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -34,11 +34,59 @@ import { scyllaClient, parseScyllaReaction, getScyllaDrivePublicUrl, + parseScyllaPollVote, } from "@/db/scylla.js"; import { LocalFollowingsCache } from "@/misc/cache.js"; import { userByIdCache } from "@/services/user-cache.js"; -export async function populatePoll(note: Note, meId: User["id"] | null) { +export async function populatePoll( + note: Note | ScyllaNote, + meId: User["id"] | null, +) { + if (scyllaClient) { + const sNote = note as ScyllaNote; + + if (sNote.poll) { + const votes = await scyllaClient + .execute(prepared.poll.select, [note.id], { prepare: true }) + .then((result) => result.rows.map(parseScyllaPollVote)); + const options = new Map( + Array.from(sNote.poll.choices.keys()).map( + (key) => [key, 0] as [number, number], + ), + ); + + for (const vote of votes) { + for (const choice of vote.choice) { + const count = options.get(choice); + if (count) { + options.set(choice, count + 1); + } + } + } + + const choices: { text: string; votes: number; isVoted: boolean }[] = []; + for (const [index, text] of sNote.poll.choices.entries()) { + const count = options.get(index); + if (count) { + choices.push({ + text, + votes: count, + isVoted: votes.some( + (v) => v.noteId === meId && v.choice.has(index), + ), + }); + } + } + + return { + multiple: sNote.poll.multiple, + expiresAt: sNote.poll.expiresAt, + choices, + }; + } + } + const poll = await Polls.findOneByOrFail({ noteId: note.id }); const choices = poll.choices.map((c) => ({ text: c,