Improve freebies (#1333)

* remove free posts

* deleted and freebie comments are always last
This commit is contained in:
Keyan 2024-08-26 19:23:07 -05:00 committed by GitHub
parent cc003a9a3e
commit 266e9a892d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 17 additions and 29 deletions

View File

@ -23,7 +23,7 @@ export async function getCost ({ subName, parentId, uploadIds, boost = 0, bio },
// sub allows freebies (or is a bio or a comment), cost is less than baseCost, not anon, // sub allows freebies (or is a bio or a comment), cost is less than baseCost, not anon,
// cost must be greater than user's balance, and user has not disabled freebies // cost must be greater than user's balance, and user has not disabled freebies
const freebie = (parentId || bio || sub?.allowFreebies) && cost <= baseCost && !!me && const freebie = (parentId || bio) && cost <= baseCost && !!me &&
cost > me?.msats && !me?.disableFreebies cost > me?.msats && !me?.disableFreebies
return freebie ? BigInt(0) : BigInt(cost) return freebie ? BigInt(0) : BigInt(cost)

View File

@ -23,19 +23,19 @@ import performPaidAction from '../paidAction'
function commentsOrderByClause (me, models, sort) { function commentsOrderByClause (me, models, sort) {
if (sort === 'recent') { if (sort === 'recent') {
return 'ORDER BY "Item".created_at DESC, "Item".id DESC' return 'ORDER BY ("Item"."deletedAt" IS NULL) DESC, ("Item".cost > 0 OR "Item"."weightedVotes" - "Item"."weightedDownVotes" > 0) DESC, "Item".created_at DESC, "Item".id DESC'
} }
if (me && sort === 'hot') { if (me && sort === 'hot') {
return `ORDER BY COALESCE( return `ORDER BY ("Item"."deletedAt" IS NULL) DESC, COALESCE(
personal_hot_score, personal_hot_score,
${orderByNumerator(models, 0)}/POWER(GREATEST(3, EXTRACT(EPOCH FROM (now_utc() - "Item".created_at))/3600), 1.3)) DESC NULLS LAST, ${orderByNumerator(models, 0)}/POWER(GREATEST(3, EXTRACT(EPOCH FROM (now_utc() - "Item".created_at))/3600), 1.3)) DESC NULLS LAST,
"Item".msats DESC, ("Item".cost > 0) DESC, "Item".id DESC` "Item".msats DESC, ("Item".cost > 0) DESC, "Item".id DESC`
} else { } else {
if (sort === 'top') { if (sort === 'top') {
return `ORDER BY ${orderByNumerator(models, 0)} DESC NULLS LAST, "Item".msats DESC, ("Item".cost > 0) DESC, "Item".id DESC` return `ORDER BY ("Item"."deletedAt" IS NULL) DESC, ${orderByNumerator(models, 0)} DESC NULLS LAST, "Item".msats DESC, ("Item".cost > 0) DESC, "Item".id DESC`
} else { } else {
return `ORDER BY ${orderByNumerator(models, 0)}/POWER(GREATEST(3, EXTRACT(EPOCH FROM (now_utc() - "Item".created_at))/3600), 1.3) DESC NULLS LAST, "Item".msats DESC, ("Item".cost > 0) DESC, "Item".id DESC` return `ORDER BY ("Item"."deletedAt" IS NULL) DESC, ${orderByNumerator(models, 0)}/POWER(GREATEST(3, EXTRACT(EPOCH FROM (now_utc() - "Item".created_at))/3600), 1.3) DESC NULLS LAST, "Item".msats DESC, ("Item".cost > 0) DESC, "Item".id DESC`
} }
} }
} }
@ -1290,11 +1290,7 @@ export const updateItem = async (parent, { sub: subName, forward, ...item }, { m
const differentSub = subName && old.subName !== subName const differentSub = subName && old.subName !== subName
if (differentSub) { if (differentSub) {
const sub = await models.sub.findUnique({ where: { name: subName } }) const sub = await models.sub.findUnique({ where: { name: subName } })
if (old.cost === 0) { if (sub.baseCost > old.sub.baseCost) {
if (!sub.allowFreebies) {
throw new GraphQLError(`~${subName} does not allow freebies`, { extensions: { code: 'BAD_INPUT' } })
}
} else if (sub.baseCost > old.sub.baseCost) {
throw new GraphQLError('cannot change to a more expensive sub', { extensions: { code: 'BAD_INPUT' } }) throw new GraphQLError('cannot change to a more expensive sub', { extensions: { code: 'BAD_INPUT' } })
} }
} }

View File

@ -16,7 +16,7 @@ export default gql`
extend type Mutation { extend type Mutation {
upsertSub(oldName: String, name: String!, desc: String, baseCost: Int!, upsertSub(oldName: String, name: String!, desc: String, baseCost: Int!,
postTypes: [String!]!, allowFreebies: Boolean!, postTypes: [String!]!,
billingType: String!, billingAutoRenew: Boolean!, billingType: String!, billingAutoRenew: Boolean!,
moderated: Boolean!, nsfw: Boolean!): SubPaidAction! moderated: Boolean!, nsfw: Boolean!): SubPaidAction!
paySub(name: String!): SubPaidAction! paySub(name: String!): SubPaidAction!
@ -24,7 +24,7 @@ export default gql`
toggleSubSubscription(name: String!): Boolean! toggleSubSubscription(name: String!): Boolean!
transferTerritory(subName: String!, userName: String!): Sub transferTerritory(subName: String!, userName: String!): Sub
unarchiveTerritory(name: String!, desc: String, baseCost: Int!, unarchiveTerritory(name: String!, desc: String, baseCost: Int!,
postTypes: [String!]!, allowFreebies: Boolean!, postTypes: [String!]!,
billingType: String!, billingAutoRenew: Boolean!, billingType: String!, billingAutoRenew: Boolean!,
moderated: Boolean!, nsfw: Boolean!): SubPaidAction! moderated: Boolean!, nsfw: Boolean!): SubPaidAction!
} }

View File

@ -14,7 +14,7 @@ import { SubmitButton } from './form'
const FeeButtonContext = createContext() const FeeButtonContext = createContext()
export function postCommentBaseLineItems ({ baseCost = 1, comment = false, allowFreebies = true, me }) { export function postCommentBaseLineItems ({ baseCost = 1, comment = false, me }) {
const anonCharge = me const anonCharge = me
? {} ? {}
: { : {
@ -29,7 +29,7 @@ export function postCommentBaseLineItems ({ baseCost = 1, comment = false, allow
term: baseCost, term: baseCost,
label: `${comment ? 'comment' : 'post'} cost`, label: `${comment ? 'comment' : 'post'} cost`,
modifier: (cost) => cost + baseCost, modifier: (cost) => cost + baseCost,
allowFreebies allowFreebies: comment
}, },
...anonCharge ...anonCharge
} }

View File

@ -149,7 +149,7 @@ export function PostForm ({ type, sub, children }) {
return ( return (
<FeeButtonProvider <FeeButtonProvider
baseLineItems={sub ? postCommentBaseLineItems({ baseCost: sub.baseCost, allowFreebies: sub.allowFreebies, me: !!me }) : undefined} baseLineItems={sub ? postCommentBaseLineItems({ baseCost: sub.baseCost, me: !!me }) : undefined}
useRemoteLineItems={postCommentUseRemoteLineItems({ me: !!me })} useRemoteLineItems={postCommentUseRemoteLineItems({ me: !!me })}
> >
<FormType sub={sub}>{children}</FormType> <FormType sub={sub}>{children}</FormType>

View File

@ -91,7 +91,6 @@ export default function TerritoryForm ({ sub }) {
desc: sub?.desc || '', desc: sub?.desc || '',
baseCost: sub?.baseCost || 10, baseCost: sub?.baseCost || 10,
postTypes: sub?.postTypes || POST_TYPES, postTypes: sub?.postTypes || POST_TYPES,
allowFreebies: typeof sub?.allowFreebies === 'undefined' ? true : sub?.allowFreebies,
billingType: sub?.billingType || 'MONTHLY', billingType: sub?.billingType || 'MONTHLY',
billingAutoRenew: sub?.billingAutoRenew || false, billingAutoRenew: sub?.billingAutoRenew || false,
moderated: sub?.moderated || false, moderated: sub?.moderated || false,
@ -133,15 +132,9 @@ export default function TerritoryForm ({ sub }) {
label='post cost' label='post cost'
name='baseCost' name='baseCost'
type='number' type='number'
groupClassName='mb-2'
required required
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>} append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
/> />
<Checkbox
label='allow free posts'
name='allowFreebies'
groupClassName='ms-1'
/>
<CheckboxGroup label='post types' name='postTypes'> <CheckboxGroup label='post types' name='postTypes'>
<Row> <Row>
<Col xs={4} sm='auto'> <Col xs={4} sm='auto'>

View File

@ -223,10 +223,10 @@ export const UPDATE_COMMENT = gql`
export const UPSERT_SUB = gql` export const UPSERT_SUB = gql`
${PAID_ACTION} ${PAID_ACTION}
mutation upsertSub($oldName: String, $name: String!, $desc: String, $baseCost: Int!, mutation upsertSub($oldName: String, $name: String!, $desc: String, $baseCost: Int!,
$postTypes: [String!]!, $allowFreebies: Boolean!, $billingType: String!, $postTypes: [String!]!, $billingType: String!,
$billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) { $billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) {
upsertSub(oldName: $oldName, name: $name, desc: $desc, baseCost: $baseCost, upsertSub(oldName: $oldName, name: $name, desc: $desc, baseCost: $baseCost,
postTypes: $postTypes, allowFreebies: $allowFreebies, billingType: $billingType, postTypes: $postTypes, billingType: $billingType,
billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) { billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) {
result { result {
name name
@ -238,10 +238,10 @@ export const UPSERT_SUB = gql`
export const UNARCHIVE_TERRITORY = gql` export const UNARCHIVE_TERRITORY = gql`
${PAID_ACTION} ${PAID_ACTION}
mutation unarchiveTerritory($name: String!, $desc: String, $baseCost: Int!, mutation unarchiveTerritory($name: String!, $desc: String, $baseCost: Int!,
$postTypes: [String!]!, $allowFreebies: Boolean!, $billingType: String!, $postTypes: [String!]!, $billingType: String!,
$billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) { $billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) {
unarchiveTerritory(name: $name, desc: $desc, baseCost: $baseCost, unarchiveTerritory(name: $name, desc: $desc, baseCost: $baseCost,
postTypes: $postTypes, allowFreebies: $allowFreebies, billingType: $billingType, postTypes: $postTypes, billingType: $billingType,
billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) { billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) {
result { result {
name name

View File

@ -7,7 +7,6 @@ export const SUB_FIELDS = gql`
name name
createdAt createdAt
postTypes postTypes
allowFreebies
rankingType rankingType
billingType billingType
billingCost billingCost

View File

@ -257,9 +257,9 @@ export default function Settings ({ ssrData }) {
label={ label={
<div className='d-flex align-items-center'>disable freebies <div className='d-flex align-items-center'>disable freebies
<Info> <Info>
<p>Some posts and comments can be created without paying. However, that content has limited visibility.</p> <p>Some comments can be created without paying. However, those comments have limited visibility.</p>
<p>If you disable freebies, you will always pay for your posts and comments and get standard visibility.</p> <p>If you disable freebies, you will always pay for your comments and get standard visibility.</p>
<p>If you attach a sending wallet, we disable freebies for you unless you have checked/unchecked this value already.</p> <p>If you attach a sending wallet, we disable freebies for you unless you have checked/unchecked this value already.</p>
</Info> </Info>