workout tips functions etc
This commit is contained in:
parent
59cfc7660b
commit
28d684da73
@ -15,25 +15,6 @@ export default {
|
||||
}
|
||||
|
||||
return me.name?.toUpperCase() === name?.toUpperCase() || !(await models.user.findUnique({ where: { name } }))
|
||||
},
|
||||
recentlyStacked: async (parent, args, { models, me }) => {
|
||||
if (!me) {
|
||||
throw new AuthenticationError('you must be logged in')
|
||||
}
|
||||
|
||||
const user = await models.user.findUnique({ where: { id: me.id } })
|
||||
|
||||
const [{ sum }] = await models.$queryRaw(`
|
||||
SELECT sum("Vote".sats)
|
||||
FROM "Vote"
|
||||
JOIN "Item" on "Vote"."itemId" = "Item".id
|
||||
WHERE "Vote"."userId" <> $1
|
||||
AND ("Vote".created_at > $2 OR $2 IS NULL)
|
||||
AND "Vote".boost = false
|
||||
AND "Item"."userId" = $1`, user.id, user.checkedNotesAt)
|
||||
|
||||
await models.user.update({ where: { id: me.id }, data: { checkedNotesAt: new Date() } })
|
||||
return sum || 0
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -6,7 +6,6 @@ export default gql`
|
||||
user(name: String!): User
|
||||
users: [User!]
|
||||
nameAvailable(name: String!): Boolean!
|
||||
recentlyStacked: Int!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
|
135
prisma/migrations/20210908193444_tips/migration.sql
Normal file
135
prisma/migrations/20210908193444_tips/migration.sql
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `Vote` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ItemAct" AS ENUM ('VOTE', 'BOOST', 'TIP');
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Vote" DROP CONSTRAINT "Vote_itemId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Vote" DROP CONSTRAINT "Vote_userId_fkey";
|
||||
|
||||
ALTER TABLE "Vote" RENAME TO "ItemAct";
|
||||
|
||||
ALTER TABLE "ItemAct" RENAME COLUMN "boost" TO "act";
|
||||
|
||||
ALTER TABLE "ItemAct"
|
||||
ALTER COLUMN "act" DROP DEFAULT,
|
||||
ALTER COLUMN "act" SET DATA TYPE "ItemActType"
|
||||
USING (
|
||||
CASE
|
||||
WHEN "act" THEN 'VOTE'
|
||||
ELSE 'BOOST'
|
||||
END
|
||||
)::"ItemActType";
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ItemAct.itemId_index" ON "ItemAct"("itemId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ItemAct.userId_index" ON "ItemAct"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ItemAct.act_index" ON "ItemAct"("act");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ItemAct" ADD FOREIGN KEY ("itemId") REFERENCES "Item"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ItemAct" ADD FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION item_act(item_id INTEGER, user_id INTEGER, act "ItemActType", act_sats INTEGER)
|
||||
RETURNS INTEGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
user_sats INTEGER;
|
||||
BEGIN
|
||||
PERFORM ASSERT_SERIALIZED();
|
||||
|
||||
SELECT (msats / 1000) INTO user_sats FROM users WHERE id = user_id;
|
||||
IF act_sats > user_sats THEN
|
||||
RAISE EXCEPTION 'SN_INSUFFICIENT_FUNDS';
|
||||
END IF;
|
||||
|
||||
UPDATE users SET msats = msats - (act_sats * 1000) WHERE id = user_id;
|
||||
|
||||
CASE act
|
||||
when 'VOTE', 'BOOST' then
|
||||
-- if we've already voted, then this is boost (doing this here prevents any potential
|
||||
-- race)
|
||||
IF EXISTS (SELECT 1 FROM "ItemAct" WHERE "itemId" = item_id AND "userId" = user_id) THEN
|
||||
INSERT INTO "ItemAct" (sats, "itemId", "userId", act, created_at, updated_at)
|
||||
VALUES (act_sats, item_id, user_id, 'BOOST', now_utc(), now_utc());
|
||||
|
||||
-- this is a vote
|
||||
ELSE
|
||||
-- only 1 sat votes are allowed
|
||||
IF act_sats > 1 THEN
|
||||
RAISE EXCEPTION 'SN_EXCEEDS_ACT_SAT_LIMIT';
|
||||
END IF;
|
||||
|
||||
INSERT INTO "ItemAct" (sats, "itemId", "userId", act, created_at, updated_at)
|
||||
VALUES (1, item_id, user_id, 'VOTE', now_utc(), now_utc());
|
||||
|
||||
-- give the item's user 1 sat
|
||||
UPDATE users SET msats = msats + 1000 WHERE id = (SELECT "userId" FROM "Item" WHERE id = item_id);
|
||||
END IF;
|
||||
when 'TIP' then
|
||||
INSERT INTO "ItemAct" (sats, "itemId", "userId", act, created_at, updated_at)
|
||||
VALUES (act_sats, item_id, user_id, 'TIP', now_utc(), now_utc());
|
||||
-- give the item's user act_sats
|
||||
UPDATE users SET msats = msats + (act_sats * 1000) WHERE id = (SELECT "userId" FROM "Item" WHERE id = item_id);
|
||||
END case;
|
||||
|
||||
RETURN act_sats;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- if user has free comments or posts, use that
|
||||
CREATE OR REPLACE FUNCTION create_item(title TEXT, url TEXT, text TEXT, parent_id INTEGER, user_id INTEGER)
|
||||
RETURNS "Item"
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
user_sats INTEGER;
|
||||
free_posts INTEGER;
|
||||
free_comments INTEGER;
|
||||
freebie BOOLEAN;
|
||||
item "Item";
|
||||
BEGIN
|
||||
PERFORM ASSERT_SERIALIZED();
|
||||
|
||||
SELECT (msats / 1000), "freePosts", "freeComments"
|
||||
INTO user_sats, free_posts, free_comments
|
||||
FROM users WHERE id = user_id;
|
||||
|
||||
freebie := (parent_id IS NULL AND free_posts > 0) OR (parent_id IS NOT NULL AND free_comments > 0);
|
||||
|
||||
IF NOT freebie AND 1 > user_sats THEN
|
||||
RAISE EXCEPTION 'SN_INSUFFICIENT_FUNDS';
|
||||
END IF;
|
||||
|
||||
INSERT INTO "Item" (title, url, text, "userId", "parentId", created_at, updated_at)
|
||||
VALUES (title, url, text, user_id, parent_id, now_utc(), now_utc()) RETURNING * INTO item;
|
||||
|
||||
IF freebie THEN
|
||||
IF parent_id IS NULL THEN
|
||||
UPDATE users SET "freePosts" = "freePosts" - 1 WHERE id = user_id;
|
||||
ELSE
|
||||
UPDATE users SET "freeComments" = "freeComments" - 1 WHERE id = user_id;
|
||||
END IF;
|
||||
ELSE
|
||||
UPDATE users SET msats = msats - 1000 WHERE id = user_id;
|
||||
|
||||
INSERT INTO "ItemAct" (sats, "itemId", "userId", act, created_at, updated_at)
|
||||
VALUES (1, item.id, user_id, 'VOTE', now_utc(), now_utc());
|
||||
END IF;
|
||||
|
||||
RETURN item;
|
||||
END;
|
||||
$$;
|
@ -1,65 +0,0 @@
|
||||
WITH RECURSIVE base AS (
|
||||
SELECT "Item".id, "Item".created_at as "createdAt", "Item".updated_at as "updatedAt", "Item".title,
|
||||
"Item".text, "Item".url, "Item"."userId", "Item"."parentId", ltree2text("Item"."path") AS "path",
|
||||
ARRAY[row_number() OVER (ORDER BY (x.sats-1)/POWER(EXTRACT(EPOCH FROM ((NOW() AT TIME ZONE 'UTC') - "Item".created_at))/3600+2, 1.5) DESC NULLS LAST, "Item"."path")] AS sort_path
|
||||
FROM "Item"
|
||||
LEFT JOIN (SELECT i.id, SUM("Vote".sats) as sats
|
||||
FROM "Item" i
|
||||
JOIN "Vote" ON i.id = "Vote"."itemId"
|
||||
WHERE i."parentId" IS NULL
|
||||
GROUP BY i.id) x ON "Item".id = x.id
|
||||
WHERE "parentId" IS NULL
|
||||
UNION ALL
|
||||
SELECT "Item".id, "Item".created_at as "createdAt", "Item".updated_at as "updatedAt", "Item".title,
|
||||
"Item".text, "Item".url, "Item"."userId", "Item"."parentId", ltree2text("Item"."path") AS "path",
|
||||
p.sort_path || row_number() OVER (ORDER BY (x.sats-1)/POWER(EXTRACT(EPOCH FROM ((NOW() AT TIME ZONE 'UTC') - "Item".created_at))/3600+2, 1.5) DESC NULLS LAST, "Item"."path")
|
||||
FROM base p
|
||||
JOIN "Item" ON ltree2text(subpath("Item"."path", 0, -1)) = p."path"
|
||||
LEFT JOIN (SELECT i.id, SUM("Vote".sats) as sats
|
||||
FROM "Item" i
|
||||
JOIN "Vote" ON i.id = "Vote"."itemId"
|
||||
WHERE i."parentId" IS NULL
|
||||
GROUP BY i.id) x ON "Item".id = x.id
|
||||
)
|
||||
select * from base order by sort_path;
|
||||
|
||||
WITH RECURSIVE base AS (
|
||||
SELECT "Item".id, "Item".created_at as "createdAt", "Item".updated_at as "updatedAt", "Item".title,
|
||||
"Item".text, "Item".url, "Item"."userId", "Item"."parentId", ltree2text("Item"."path") AS "path",
|
||||
ARRAY[row_number() OVER (ORDER BY "Item".created_at, "Item"."path")] AS sort_path
|
||||
FROM "Item"
|
||||
WHERE "parentId" IS NULL
|
||||
UNION ALL
|
||||
SELECT "Item".id, "Item".created_at as "createdAt", "Item".updated_at as "updatedAt", "Item".title,
|
||||
"Item".text, "Item".url, "Item"."userId", "Item"."parentId", ltree2text("Item"."path") AS "path",
|
||||
p.sort_path || row_number() OVER (ORDER BY "Item".created_at, "Item"."path")
|
||||
FROM base p
|
||||
JOIN "Item" ON ltree2text(subpath("Item"."path", 0, -1)) = p."path"
|
||||
)
|
||||
select * from base order by sort_path;
|
||||
|
||||
CREATE OR REPLACE FUNCTION vote(item_id INTEGER, username TEXT, vote_sats INTEGER)
|
||||
RETURNS INTEGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
user_id INTEGER
|
||||
user_sats INTEGER
|
||||
BEGIN
|
||||
SELECT sats, id INTO user_sats, user_id FROM "User" WHERE name = username;
|
||||
IF vote_sats > user_sats THEN
|
||||
RAISE EXCEPTION 'insufficient funds';
|
||||
END IF;
|
||||
|
||||
UPDATE "User" SET sats = sats - vote_sats WHERE id = user_id;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM "Vote" WHERE "itemId" = item_id AND "userId" = user_id) THEN
|
||||
INSERT INTO "Vote" (sats, "itemId", "userId") VALUES (vote_sats, item_id, user_id);
|
||||
UPDATE "User" SET sats = sats + vote_sats WHERE id = (SELECT "userId" FROM "Item" WHERE id = item_id);
|
||||
ELSE
|
||||
INSERT INTO "Vote" (sats, "itemId", "userId", boost) VALUES (vote_sats, item_id, user_id, true);
|
||||
END IF;
|
||||
|
||||
RETURN sats
|
||||
END;
|
||||
$$;
|
@ -11,24 +11,24 @@ generator client {
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
|
||||
name String? @unique @db.Citext
|
||||
email String? @unique
|
||||
emailVerified DateTime? @map(name: "email_verified")
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
|
||||
name String? @unique @db.Citext
|
||||
email String? @unique
|
||||
emailVerified DateTime? @map(name: "email_verified")
|
||||
image String?
|
||||
items Item[]
|
||||
mentions Mention[]
|
||||
messages Message[]
|
||||
votes Vote[]
|
||||
itemActions ItemAction[]
|
||||
invoices Invoice[]
|
||||
withdrawls Withdrawl[]
|
||||
msats Int @default(0)
|
||||
freeComments Int @default(5)
|
||||
freePosts Int @default(2)
|
||||
msats Int @default(0)
|
||||
freeComments Int @default(5)
|
||||
freePosts Int @default(2)
|
||||
checkedNotesAt DateTime?
|
||||
pubkey String? @unique
|
||||
pubkey String? @unique
|
||||
|
||||
@@map(name: "users")
|
||||
}
|
||||
@ -60,7 +60,7 @@ model Item {
|
||||
parent Item? @relation("ParentChildren", fields: [parentId], references: [id])
|
||||
parentId Int?
|
||||
children Item[] @relation("ParentChildren")
|
||||
votes Vote[]
|
||||
actions ItemAction[]
|
||||
mentions Mention[]
|
||||
path Unsupported("LTREE")?
|
||||
|
||||
@ -68,19 +68,26 @@ model Item {
|
||||
@@index([parentId])
|
||||
}
|
||||
|
||||
model Vote {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
||||
sats Int @default(1)
|
||||
boost Boolean @default(false)
|
||||
item Item @relation(fields: [itemId], references: [id])
|
||||
enum ItemActionType {
|
||||
VOTE
|
||||
BOOST
|
||||
TIP
|
||||
}
|
||||
|
||||
model ItemAction {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
||||
sats Int @default(1)
|
||||
action ItemActionType @default(VOTE)
|
||||
item Item @relation(fields: [itemId], references: [id])
|
||||
itemId Int
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
||||
@@index([itemId])
|
||||
@@index([userId])
|
||||
@@index([action])
|
||||
}
|
||||
|
||||
model Mention {
|
||||
|
Loading…
x
Reference in New Issue
Block a user