Skip to content
Open
29 changes: 29 additions & 0 deletions lib/webPush.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import webPush from 'web-push'
import removeMd from 'remove-markdown'
import { COMMENT_DEPTH_LIMIT, FOUND_BLURBS, LOST_BLURBS } from './constants'
import { msatsToSats, numWithUnits } from './format'
import { nextBillingWithGrace } from '@/lib/territory'
import models from '@/api/models'
import { isMuted } from '@/lib/user'
import { Prisma } from '@prisma/client'
Expand Down Expand Up @@ -380,6 +381,34 @@ export const notifyTerritoryTransfer = async ({ models, sub, to }) => {
}
}

export const notifyTerritoryStatusChange = async ({ sub }) => {
const dueDate = nextBillingWithGrace(sub)
const days = Math.ceil((new Date(dueDate) - new Date()) / (1000 * 60 * 60 * 24))
const timeLeft = days === 1 ? 'tomorrow' : `in ${days} days`
const title = sub.status === 'ACTIVE'
? 'your territory is active again'
: sub.status === 'GRACE'
? `your territory payment for ~${sub.name} is due or your territory will be archived ${timeLeft}`
: `~${sub.name} has been archived!`

try {
await sendUserNotification(sub.userId, { title, tag: `TERRITORY_STATUS-${sub.name}` })
} catch (err) {
console.error(err)
}
}

export const notifyTerritoryRevenue = async (subAct) => {
const fmt = msats => numWithUnits(msatsToSats(msats, { abbreviate: false }))
const title = `you earned ${fmt(subAct.msats)} in revenue from ~${subAct.subName}`
try {
await sendUserNotification(subAct.userId, { title, tag: `TERRITORY_REVENUE-${subAct.subName}` })
} catch (err) {
console.error(err)
}
}

// TODO: needs testing, fix rewards not working first
export async function notifyEarner (userId, earnings) {
const fmt = msats => numWithUnits(msatsToSats(msats, { abbreviate: false }))

Expand Down
24 changes: 21 additions & 3 deletions worker/territory.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ import performPaidAction from '@/api/paidAction'
import { PAID_ACTION_PAYMENT_METHODS } from '@/lib/constants'
import { nextBillingWithGrace } from '@/lib/territory'
import { datePivot } from '@/lib/time'
import { notifyTerritoryStatusChange, notifyTerritoryRevenue } from '@/lib/webPush'

export async function territoryBilling ({ data: { subName }, boss, models }) {
const sub = await models.sub.findUnique({
let sub = await models.sub.findUnique({
where: {
name: subName
}
})

async function territoryStatusUpdate () {
if (sub.status !== 'STOPPED') {
await models.sub.update({
sub = await models.sub.update({
include: { user: true },
where: {
name: subName
Expand All @@ -24,7 +25,8 @@ export async function territoryBilling ({ data: { subName }, boss, models }) {
}
})
}

// send push notification with the new status
await notifyTerritoryStatusChange({ sub })
// retry billing in one day
await boss.send('territoryBilling', { subName }, { startAfter: datePivot(new Date(), { days: 1 }) })
}
Expand All @@ -44,6 +46,9 @@ export async function territoryBilling ({ data: { subName }, boss, models }) {
})
if (!result) {
throw new Error('not enough fee credits to auto-renew territory')
} else if (sub.status === 'GRACE' && result.status === 'ACTIVE') {
// if the sub was in grace and we successfully auto-renewed it, send a push notification
await notifyTerritoryStatusChange({ result })
}
} catch (e) {
console.error(e)
Expand Down Expand Up @@ -90,4 +95,17 @@ export async function territoryRevenue ({ models }) {
"stackedMsats" = users."stackedMsats" + "SubActResultTotal".total_msats
FROM "SubActResultTotal"
WHERE users.id = "SubActResultTotal"."userId"`

const territoryRevenue = await models.subAct.findMany({
where: {
createdAt: { // retrieve revenue calculated in the last hour
gte: datePivot(new Date(), { hours: -1 })
},
type: 'REVENUE'
}
})

await Promise.allSettled(
territoryRevenue.map(subAct => notifyTerritoryRevenue(subAct))
)
}