Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: comment fee control #1768

Merged
merged 8 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions api/paidAction/itemCreate.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,33 @@ export const paymentMethods = [
PAID_ACTION_PAYMENT_METHODS.PESSIMISTIC
]

export const DEFAULT_ITEM_COST = 1000n

export async function getBaseCost ({ models, bio, parentId, subName }) {
if (bio) return DEFAULT_ITEM_COST

if (parentId) {
// the subname is stored in the root item of the thread
const parent = await models.item.findFirst({
where: { id: Number(parentId) },
include: {
root: { include: { sub: true } },
sub: true
}
})

const root = parent.root ?? parent

if (!root.sub) return DEFAULT_ITEM_COST
return satsToMsats(root.sub.replyCost)
}

const sub = await models.sub.findUnique({ where: { name: subName } })
return satsToMsats(sub.baseCost)
}

export async function getCost ({ subName, parentId, uploadIds, boost = 0, bio }, { models, me }) {
const sub = (parentId || bio) ? null : await models.sub.findUnique({ where: { name: subName } })
const baseCost = sub ? satsToMsats(sub.baseCost) : 1000n
const baseCost = await getBaseCost({ models, bio, parentId, subName })

// cost = baseCost * 10^num_items_in_10m * 100 (anon) or 1 (user) + upload fees + boost
const [{ cost }] = await models.$queryRaw`
Expand Down
4 changes: 3 additions & 1 deletion api/typeDefs/sub.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default gql`

extend type Mutation {
upsertSub(oldName: String, name: String!, desc: String, baseCost: Int!,
replyCost: Int!,
postTypes: [String!]!,
billingType: String!, billingAutoRenew: Boolean!,
moderated: Boolean!, nsfw: Boolean!): SubPaidAction!
Expand All @@ -24,7 +25,7 @@ export default gql`
toggleSubSubscription(name: String!): Boolean!
transferTerritory(subName: String!, userName: String!): Sub
unarchiveTerritory(name: String!, desc: String, baseCost: Int!,
postTypes: [String!]!,
replyCost: Int!, postTypes: [String!]!,
billingType: String!, billingAutoRenew: Boolean!,
moderated: Boolean!, nsfw: Boolean!): SubPaidAction!
}
Expand All @@ -45,6 +46,7 @@ export default gql`
billedLastAt: Date!
billPaidUntil: Date
baseCost: Int!
replyCost: Int!
status: String!
moderated: Boolean!
moderatedCount: Int!
Expand Down
2 changes: 1 addition & 1 deletion components/reply.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export default forwardRef(function Reply ({
{reply &&
<div className={styles.reply}>
<FeeButtonProvider
baseLineItems={postCommentBaseLineItems({ baseCost: 1, comment: true, me: !!me })}
baseLineItems={postCommentBaseLineItems({ baseCost: sub?.replyCost ?? 1, comment: true, me: !!me })}
useRemoteLineItems={postCommentUseRemoteLineItems({ parentId: item.id, me: !!me })}
>
<Form
Expand Down
8 changes: 8 additions & 0 deletions components/territory-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export default function TerritoryForm ({ sub }) {
name: sub?.name || '',
desc: sub?.desc || '',
baseCost: sub?.baseCost || 10,
replyCost: sub?.replyCost || 1,
postTypes: sub?.postTypes || POST_TYPES,
billingType: sub?.billingType || 'MONTHLY',
billingAutoRenew: sub?.billingAutoRenew || false,
Expand Down Expand Up @@ -234,6 +235,13 @@ export default function TerritoryForm ({ sub }) {
header={<div style={{ fontWeight: 'bold', fontSize: '92%' }}>options</div>}
body={
<>
<Input
label='reply cost'
name='replyCost'
type='number'
required
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
/>
<BootstrapForm.Label>moderation</BootstrapForm.Label>
<Checkbox
inline
Expand Down
13 changes: 10 additions & 3 deletions components/territory-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,16 @@ export function TerritoryInfo ({ sub }) {
<span> on </span>
<span className='fw-bold'>{new Date(sub.createdAt).toDateString()}</span>
</div>
<div className='text-muted'>
<span>post cost </span>
<span className='fw-bold'>{numWithUnits(sub.baseCost)}</span>
<div className='d-flex'>
<div className='text-muted'>
<span>post cost </span>
<span className='fw-bold'>{numWithUnits(sub.baseCost)}</span>
</div>
<span className='px-1'> \ </span>
<div className='text-muted'>
<span>reply cost </span>
<span className='fw-bold'>{numWithUnits(sub.replyCost)}</span>
</div>
</div>
<TerritoryBillingLine sub={sub} />
</CardFooter>
Expand Down
1 change: 1 addition & 0 deletions fragments/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const ITEM_FIELDS = gql`
meMuteSub
meSubscription
nsfw
replyCost
}
otsHash
position
Expand Down
8 changes: 4 additions & 4 deletions fragments/paidAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,10 @@ export const UPDATE_COMMENT = gql`
export const UPSERT_SUB = gql`
${PAID_ACTION}
mutation upsertSub($oldName: String, $name: String!, $desc: String, $baseCost: Int!,
$postTypes: [String!]!, $billingType: String!,
$replyCost: Int!, $postTypes: [String!]!, $billingType: String!,
$billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) {
upsertSub(oldName: $oldName, name: $name, desc: $desc, baseCost: $baseCost,
postTypes: $postTypes, billingType: $billingType,
replyCost: $replyCost, postTypes: $postTypes, billingType: $billingType,
billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) {
result {
name
Expand All @@ -279,10 +279,10 @@ export const UPSERT_SUB = gql`
export const UNARCHIVE_TERRITORY = gql`
${PAID_ACTION}
mutation unarchiveTerritory($name: String!, $desc: String, $baseCost: Int!,
$postTypes: [String!]!, $billingType: String!,
$replyCost: Int!, $postTypes: [String!]!, $billingType: String!,
$billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) {
unarchiveTerritory(name: $name, desc: $desc, baseCost: $baseCost,
postTypes: $postTypes, billingType: $billingType,
replyCost: $replyCost, postTypes: $postTypes, billingType: $billingType,
billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) {
result {
name
Expand Down
1 change: 1 addition & 0 deletions fragments/subs.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const SUB_FIELDS = gql`
billedLastAt
billPaidUntil
baseCost
replyCost
userId
desc
status
Expand Down
3 changes: 3 additions & 0 deletions lib/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ export function territorySchema (args) {
baseCost: intValidator
.min(1, 'must be at least 1')
.max(100000, 'must be at most 100k'),
replyCost: intValidator
.min(1, 'must be at least 1')
.max(100000, 'must be at most 100k'),
postTypes: array().of(string().oneOf(POST_TYPES)).min(1, 'must support at least one post type'),
billingType: string().required('required').oneOf(TERRITORY_BILLING_TYPES, 'required'),
nsfw: boolean()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Sub" ADD COLUMN "replyCost" INTEGER NOT NULL DEFAULT 1;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ model Sub {
rankingType RankingType
allowFreebies Boolean @default(true)
baseCost Int @default(1)
replyCost Int @default(1)
rewardsPct Int @default(50)
desc String?
status Status @default(ACTIVE)
Expand Down