Compare commits
No commits in common. "371084016740fc29751e5964e17c687420c6ea57" and "79f0df17b2ba0ec372da7d74b18bbdb4b84b2665" have entirely different histories.
3710840167
...
79f0df17b2
@ -157,12 +157,6 @@ export default {
|
|||||||
SELECT date_trunc('day', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago' as from,
|
SELECT date_trunc('day', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago' as from,
|
||||||
(date_trunc('day', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago') + interval '1 day - 1 second' as to`
|
(date_trunc('day', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago') + interval '1 day - 1 second' as to`
|
||||||
return await topUsers(parent, { when: 'custom', to: new Date(to).getTime().toString(), from: new Date(from).getTime().toString(), limit: 100 }, { models, ...context })
|
return await topUsers(parent, { when: 'custom', to: new Date(to).getTime().toString(), from: new Date(from).getTime().toString(), limit: 100 }, { models, ...context })
|
||||||
},
|
|
||||||
total: async (parent, args, { models }) => {
|
|
||||||
if (!parent.total) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return parent.total
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
|
@ -745,7 +745,7 @@ export async function createWithdrawal (parent, { invoice, maxFee }, { me, model
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function sendToLnAddr (parent, { addr, amount, maxFee, comment, ...payer },
|
export async function sendToLnAddr (parent, { addr, amount, maxFee, comment, ...payer },
|
||||||
{ me, models, lnd, headers, walletId }) {
|
{ me, models, lnd, headers, autoWithdraw = false }) {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } })
|
throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } })
|
||||||
}
|
}
|
||||||
@ -788,7 +788,7 @@ export async function sendToLnAddr (parent, { addr, amount, maxFee, comment, ...
|
|||||||
try {
|
try {
|
||||||
const decoded = await decodePaymentRequest({ lnd, request: res.pr })
|
const decoded = await decodePaymentRequest({ lnd, request: res.pr })
|
||||||
const ourPubkey = (await getIdentity({ lnd })).public_key
|
const ourPubkey = (await getIdentity({ lnd })).public_key
|
||||||
if (walletId && decoded.destination === ourPubkey && process.env.NODE_ENV === 'production') {
|
if (autoWithdraw && decoded.destination === ourPubkey && process.env.NODE_ENV === 'production') {
|
||||||
// unset lnaddr so we don't trigger another withdrawal with same destination
|
// unset lnaddr so we don't trigger another withdrawal with same destination
|
||||||
await models.wallet.deleteMany({
|
await models.wallet.deleteMany({
|
||||||
where: { userId: me.id, type: Wallet.LnAddr.type }
|
where: { userId: me.id, type: Wallet.LnAddr.type }
|
||||||
@ -804,5 +804,5 @@ export async function sendToLnAddr (parent, { addr, amount, maxFee, comment, ...
|
|||||||
}
|
}
|
||||||
|
|
||||||
// take pr and createWithdrawl
|
// take pr and createWithdrawl
|
||||||
return await createWithdrawal(parent, { invoice: res.pr, maxFee }, { me, models, lnd, headers, walletId })
|
return await createWithdrawal(parent, { invoice: res.pr, maxFee }, { me, models, lnd, headers, autoWithdraw })
|
||||||
}
|
}
|
||||||
|
@ -54,60 +54,6 @@ export default async function getSSRApolloClient ({ req, res, me = null }) {
|
|||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
function oneDayReferral (request, { me }) {
|
|
||||||
if (!me) return
|
|
||||||
const refHeader = request.headers['x-stacker-news-referrer']
|
|
||||||
if (!refHeader) return
|
|
||||||
|
|
||||||
const referrers = refHeader.split('; ').filter(Boolean)
|
|
||||||
for (const referrer of referrers) {
|
|
||||||
let prismaPromise, getData
|
|
||||||
|
|
||||||
if (referrer.startsWith('item-')) {
|
|
||||||
prismaPromise = models.item.findUnique({ where: { id: parseInt(referrer.slice(5)) } })
|
|
||||||
getData = item => ({
|
|
||||||
referrerId: item.userId,
|
|
||||||
refereeId: parseInt(me.id),
|
|
||||||
type: item.parentId ? 'COMMENT' : 'POST',
|
|
||||||
typeId: String(item.id)
|
|
||||||
})
|
|
||||||
} else if (referrer.startsWith('profile-')) {
|
|
||||||
prismaPromise = models.user.findUnique({ where: { name: referrer.slice(8) } })
|
|
||||||
getData = user => ({
|
|
||||||
referrerId: user.id,
|
|
||||||
refereeId: parseInt(me.id),
|
|
||||||
type: 'PROFILE',
|
|
||||||
typeId: String(user.id)
|
|
||||||
})
|
|
||||||
} else if (referrer.startsWith('territory-')) {
|
|
||||||
prismaPromise = models.sub.findUnique({ where: { name: referrer.slice(10) } })
|
|
||||||
getData = sub => ({
|
|
||||||
referrerId: sub.userId,
|
|
||||||
refereeId: parseInt(me.id),
|
|
||||||
type: 'TERRITORY',
|
|
||||||
typeId: sub.name
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
prismaPromise = models.user.findUnique({ where: { name: referrer } })
|
|
||||||
getData = user => ({
|
|
||||||
referrerId: user.id,
|
|
||||||
refereeId: parseInt(me.id),
|
|
||||||
type: 'REFERRAL',
|
|
||||||
typeId: String(user.id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
prismaPromise?.then(ref => {
|
|
||||||
if (ref && getData) {
|
|
||||||
const data = getData(ref)
|
|
||||||
// can't refer yourself
|
|
||||||
if (data.refereeId === data.referrerId) return
|
|
||||||
models.oneDayReferral.create({ data }).catch(console.error)
|
|
||||||
}
|
|
||||||
}).catch(console.error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a query and variables and returns a getServerSideProps function
|
* Takes a query and variables and returns a getServerSideProps function
|
||||||
*
|
*
|
||||||
@ -178,8 +124,6 @@ export function getGetServerSideProps (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oneDayReferral(req, { me })
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
...props,
|
...props,
|
||||||
|
@ -1,76 +1,23 @@
|
|||||||
import { NextResponse, URLPattern } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
|
|
||||||
const referrerPattern = new URLPattern({ pathname: ':pathname(*)/r/:referrer([\\w_]+)' })
|
const referrerRegex = /(\/.*)?\/r\/([\w_]+)/
|
||||||
const itemPattern = new URLPattern({ pathname: '/items/:id(\\d+){/:other(\\w+)}?' })
|
|
||||||
const profilePattern = new URLPattern({ pathname: '/:name([\\w_]+){/:type(\\w+)}?' })
|
|
||||||
const territoryPattern = new URLPattern({ pathname: '/~:name([\\w_]+){/*}?' })
|
|
||||||
|
|
||||||
// key for /r/... link referrers
|
|
||||||
const SN_REFERRER = 'sn_referrer'
|
|
||||||
// we use this to hold /r/... referrers through the redirect
|
|
||||||
const SN_REFERRER_NONCE = 'sn_referrer_nonce'
|
|
||||||
|
|
||||||
// we store the referrers in cookies for a future signup event
|
|
||||||
// we pass the referrers in the request headers so we can use them in referral rewards for logged in stackers
|
|
||||||
function referrerMiddleware (request) {
|
function referrerMiddleware (request) {
|
||||||
if (referrerPattern.test(request.url)) {
|
const m = referrerRegex.exec(request.nextUrl.pathname)
|
||||||
const { pathname, referrer } = referrerPattern.exec(request.url).pathname.groups
|
|
||||||
|
|
||||||
const url = new URL(pathname || '/', request.url)
|
const url = new URL(m[1] || '/', request.url)
|
||||||
url.search = request.nextUrl.search
|
url.search = request.nextUrl.search
|
||||||
url.hash = request.nextUrl.hash
|
url.hash = request.nextUrl.hash
|
||||||
|
|
||||||
const response = NextResponse.redirect(url)
|
const resp = NextResponse.redirect(url)
|
||||||
// explicit referrers are set for a day and can only be overriden by other explicit
|
resp.cookies.set('sn_referrer', m[2])
|
||||||
// referrers. Content referrers do not override explicit referrers because
|
return resp
|
||||||
// explicit referees might click around before signing up.
|
|
||||||
response.cookies.set(SN_REFERRER, referrer, { maxAge: 60 * 60 * 24 })
|
|
||||||
// store the explicit referrer for one page load
|
|
||||||
// this allows us to attribute both explicit and implicit referrers after the redirect
|
|
||||||
// e.g. items/<num>/r/<referrer> links should attribute both the item op and the referrer
|
|
||||||
// without this the /r/<referrer> would be lost on redirect
|
|
||||||
response.cookies.set(SN_REFERRER_NONCE, referrer, { maxAge: 1 })
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
let contentReferrer
|
|
||||||
if (itemPattern.test(request.url)) {
|
|
||||||
let id = request.nextUrl.searchParams.get('commentId')
|
|
||||||
if (!id) {
|
|
||||||
({ id } = itemPattern.exec(request.url).pathname.groups)
|
|
||||||
}
|
|
||||||
contentReferrer = `item-${id}`
|
|
||||||
} else if (profilePattern.test(request.url)) {
|
|
||||||
const { name } = profilePattern.exec(request.url).pathname.groups
|
|
||||||
contentReferrer = `profile-${name}`
|
|
||||||
} else if (territoryPattern.test(request.url)) {
|
|
||||||
const { name } = territoryPattern.exec(request.url).pathname.groups
|
|
||||||
contentReferrer = `territory-${name}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass the referrers to SSR in the request headers
|
|
||||||
const requestHeaders = new Headers(request.headers)
|
|
||||||
const referrers = [request.cookies.get(SN_REFERRER_NONCE)?.value, contentReferrer].filter(Boolean)
|
|
||||||
if (referrers.length) {
|
|
||||||
requestHeaders.set('x-stacker-news-referrer', referrers.join('; '))
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = NextResponse.next({
|
|
||||||
request: {
|
|
||||||
headers: requestHeaders
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// if we don't already have an explicit referrer, give them the content referrer as one
|
|
||||||
if (!request.cookies.has(SN_REFERRER) && contentReferrer) {
|
|
||||||
response.cookies.set(SN_REFERRER, contentReferrer, { maxAge: 60 * 60 * 24 })
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function middleware (request) {
|
export function middleware (request) {
|
||||||
const resp = referrerMiddleware(request)
|
let resp = NextResponse.next()
|
||||||
|
if (referrerRegex.test(request.nextUrl.pathname)) {
|
||||||
|
resp = referrerMiddleware(request)
|
||||||
|
}
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV === 'development'
|
const isDev = process.env.NODE_ENV === 'development'
|
||||||
|
|
||||||
|
63
package-lock.json
generated
63
package-lock.json
generated
@ -62,7 +62,7 @@
|
|||||||
"page-metadata-parser": "^1.1.4",
|
"page-metadata-parser": "^1.1.4",
|
||||||
"pg-boss": "^9.0.3",
|
"pg-boss": "^9.0.3",
|
||||||
"piexifjs": "^1.0.6",
|
"piexifjs": "^1.0.6",
|
||||||
"prisma": "^5.16.1",
|
"prisma": "^5.14.0",
|
||||||
"qrcode.react": "^3.1.0",
|
"qrcode.react": "^3.1.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-avatar-editor": "^13.0.0",
|
"react-avatar-editor": "^13.0.0",
|
||||||
@ -4109,43 +4109,48 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/debug": {
|
"node_modules/@prisma/debug": {
|
||||||
"version": "5.16.1",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz",
|
||||||
"integrity": "sha512-JsNgZAg6BD9RInLSrg7ZYzo11N7cVvYArq3fHGSD89HSgtN0VDdjV6bib7YddbcO6snzjchTiLfjeTqBjtArVQ=="
|
"integrity": "sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w=="
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines": {
|
"node_modules/@prisma/engines": {
|
||||||
"version": "5.16.1",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz",
|
||||||
"integrity": "sha512-KkyF3eIUtBIyp5A/rJHCtwQO18OjpGgx18PzjyGcJDY/+vNgaVyuVd+TgwBgeq6NLdd1XMwRCI+58vinHsAdfA==",
|
"integrity": "sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "5.16.1",
|
"@prisma/debug": "5.14.0",
|
||||||
"@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303",
|
"@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48",
|
||||||
"@prisma/fetch-engine": "5.16.1",
|
"@prisma/fetch-engine": "5.14.0",
|
||||||
"@prisma/get-platform": "5.16.1"
|
"@prisma/get-platform": "5.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines-version": {
|
"node_modules/@prisma/engines/node_modules/@prisma/engines-version": {
|
||||||
"version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303",
|
"version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz",
|
||||||
"integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw=="
|
"integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA=="
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/fetch-engine": {
|
"node_modules/@prisma/fetch-engine": {
|
||||||
"version": "5.16.1",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz",
|
||||||
"integrity": "sha512-oOkjaPU1lhcA/Rvr4GVfd1NLJBwExgNBE36Ueq7dr71kTMwy++a3U3oLd2ZwrV9dj9xoP6LjCcky799D9nEt4w==",
|
"integrity": "sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "5.16.1",
|
"@prisma/debug": "5.14.0",
|
||||||
"@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303",
|
"@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48",
|
||||||
"@prisma/get-platform": "5.16.1"
|
"@prisma/get-platform": "5.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@prisma/fetch-engine/node_modules/@prisma/engines-version": {
|
||||||
|
"version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48",
|
||||||
|
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz",
|
||||||
|
"integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA=="
|
||||||
|
},
|
||||||
"node_modules/@prisma/get-platform": {
|
"node_modules/@prisma/get-platform": {
|
||||||
"version": "5.16.1",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz",
|
||||||
"integrity": "sha512-R4IKnWnMkR2nUAbU5gjrPehdQYUUd7RENFD2/D+xXTNhcqczp0N+WEGQ3ViyI3+6mtVcjjNIMdnUTNyu3GxIgA==",
|
"integrity": "sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "5.16.1"
|
"@prisma/debug": "5.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@protobufjs/aspromise": {
|
"node_modules/@protobufjs/aspromise": {
|
||||||
@ -15813,12 +15818,12 @@
|
|||||||
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
||||||
},
|
},
|
||||||
"node_modules/prisma": {
|
"node_modules/prisma": {
|
||||||
"version": "5.16.1",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz",
|
||||||
"integrity": "sha512-Z1Uqodk44diztImxALgJJfNl2Uisl9xDRvqybMKEBYJLNKNhDfAHf+ZIJbZyYiBhLMbKU9cYGdDVG5IIXEnL2Q==",
|
"integrity": "sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/engines": "5.16.1"
|
"@prisma/engines": "5.14.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"prisma": "build/index.js"
|
"prisma": "build/index.js"
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
"page-metadata-parser": "^1.1.4",
|
"page-metadata-parser": "^1.1.4",
|
||||||
"pg-boss": "^9.0.3",
|
"pg-boss": "^9.0.3",
|
||||||
"piexifjs": "^1.0.6",
|
"piexifjs": "^1.0.6",
|
||||||
"prisma": "^5.16.1",
|
"prisma": "^5.14.0",
|
||||||
"qrcode.react": "^3.1.0",
|
"qrcode.react": "^3.1.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-avatar-editor": "^13.0.0",
|
"react-avatar-editor": "^13.0.0",
|
||||||
|
@ -36,22 +36,6 @@ function getEventCallbacks () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getReferrerId (referrer) {
|
|
||||||
try {
|
|
||||||
if (referrer.startsWith('item-')) {
|
|
||||||
return (await prisma.item.findUnique({ where: { id: parseInt(referrer.slice(5)) } }))?.userId
|
|
||||||
} else if (referrer.startsWith('profile-')) {
|
|
||||||
return (await prisma.user.findUnique({ where: { name: referrer.slice(8) } }))?.id
|
|
||||||
} else if (referrer.startsWith('territory-')) {
|
|
||||||
return (await prisma.sub.findUnique({ where: { name: referrer.slice(10) } }))?.userId
|
|
||||||
} else {
|
|
||||||
return (await prisma.user.findUnique({ where: { name: referrer } }))?.id
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('error getting referrer id', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @returns {Partial<import('next-auth').CallbacksOptions>} */
|
/** @returns {Partial<import('next-auth').CallbacksOptions>} */
|
||||||
function getCallbacks (req) {
|
function getCallbacks (req) {
|
||||||
return {
|
return {
|
||||||
@ -73,10 +57,10 @@ function getCallbacks (req) {
|
|||||||
// isNewUser doesn't work for nostr/lightning auth because we create the user before nextauth can
|
// isNewUser doesn't work for nostr/lightning auth because we create the user before nextauth can
|
||||||
// this means users can update their referrer if they don't have one, which is fine
|
// this means users can update their referrer if they don't have one, which is fine
|
||||||
if (req.cookies.sn_referrer && user?.id) {
|
if (req.cookies.sn_referrer && user?.id) {
|
||||||
const referrerId = await getReferrerId(req.cookies.sn_referrer)
|
const referrer = await prisma.user.findUnique({ where: { name: req.cookies.sn_referrer } })
|
||||||
if (referrerId && referrerId !== parseInt(user?.id)) {
|
if (referrer && referrer.id !== Number(user.id)) {
|
||||||
await prisma.user.updateMany({ where: { id: user.id, referrerId: null }, data: { referrerId } })
|
await prisma.user.updateMany({ where: { id: user.id, referrerId: null }, data: { referrerId: referrer.id } })
|
||||||
notifyReferral(referrerId)
|
notifyReferral(referrer.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
-- CreateEnum
|
|
||||||
CREATE TYPE "OneDayReferralType" AS ENUM ('REFERRAL', 'POST', 'COMMENT', 'PROFILE', 'TERRITORY');
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "OneDayReferral" (
|
|
||||||
"id" SERIAL NOT NULL,
|
|
||||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"referrerId" INTEGER NOT NULL,
|
|
||||||
"refereeId" INTEGER NOT NULL,
|
|
||||||
"type" "OneDayReferralType" NOT NULL,
|
|
||||||
"typeId" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "OneDayReferral_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "OneDayReferral_created_at_idx" ON "OneDayReferral"("created_at");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "OneDayReferral_referrerId_idx" ON "OneDayReferral"("referrerId");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "OneDayReferral_refereeId_idx" ON "OneDayReferral"("refereeId");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "OneDayReferral_type_typeId_idx" ON "OneDayReferral"("type", "typeId");
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "OneDayReferral" ADD CONSTRAINT "OneDayReferral_referrerId_fkey" FOREIGN KEY ("referrerId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "OneDayReferral" ADD CONSTRAINT "OneDayReferral_refereeId_fkey" FOREIGN KEY ("refereeId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -127,8 +127,6 @@ model User {
|
|||||||
Reminder Reminder[]
|
Reminder Reminder[]
|
||||||
PollBlindVote PollBlindVote[]
|
PollBlindVote PollBlindVote[]
|
||||||
ItemUserAgg ItemUserAgg[]
|
ItemUserAgg ItemUserAgg[]
|
||||||
oneDayReferrals OneDayReferral[] @relation("OneDayReferral_referrer")
|
|
||||||
oneDayReferrees OneDayReferral[] @relation("OneDayReferral_referrees")
|
|
||||||
|
|
||||||
@@index([photoId])
|
@@index([photoId])
|
||||||
@@index([createdAt], map: "users.created_at_index")
|
@@index([createdAt], map: "users.created_at_index")
|
||||||
@ -136,31 +134,6 @@ model User {
|
|||||||
@@map("users")
|
@@map("users")
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OneDayReferralType {
|
|
||||||
REFERRAL
|
|
||||||
POST
|
|
||||||
COMMENT
|
|
||||||
PROFILE
|
|
||||||
TERRITORY
|
|
||||||
}
|
|
||||||
|
|
||||||
model OneDayReferral {
|
|
||||||
id Int @id @default(autoincrement())
|
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
|
||||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
|
||||||
referrerId Int
|
|
||||||
refereeId Int
|
|
||||||
referrer User @relation("OneDayReferral_referrer", fields: [referrerId], references: [id], onDelete: Cascade)
|
|
||||||
referee User @relation("OneDayReferral_referrees", fields: [refereeId], references: [id], onDelete: Cascade)
|
|
||||||
type OneDayReferralType
|
|
||||||
typeId String
|
|
||||||
|
|
||||||
@@index([createdAt])
|
|
||||||
@@index([referrerId])
|
|
||||||
@@index([refereeId])
|
|
||||||
@@index([type, typeId])
|
|
||||||
}
|
|
||||||
|
|
||||||
enum WalletType {
|
enum WalletType {
|
||||||
LIGHTNING_ADDRESS
|
LIGHTNING_ADDRESS
|
||||||
LND
|
LND
|
||||||
|
@ -113,7 +113,7 @@ export const createImgproxyUrls = async (id, text, { models, forceFetch }) => {
|
|||||||
dimensions: await getDimensions(fetchUrl)
|
dimensions: await getDimensions(fetchUrl)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('[imgproxy] id:', id, '-- error getting dimensions (possibly not running imgproxy pro)', err)
|
console.log('[imgproxy] id:', id, '-- error getting dimensions (possibly not running imgproxy pro)')
|
||||||
}
|
}
|
||||||
for (const res of resolutions) {
|
for (const res of resolutions) {
|
||||||
const [w, h] = res.split('x')
|
const [w, h] = res.split('x')
|
||||||
|
@ -45,12 +45,7 @@ async function transitionInvoice (jobName, { invoiceId, fromState, toState, toDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
await onTransition({ lndInvoice, dbInvoice, tx })
|
await onTransition({ lndInvoice, dbInvoice, tx })
|
||||||
}, {
|
}, { isolationLevel: Prisma.TransactionIsolationLevel.ReadCommitted })
|
||||||
isolationLevel: Prisma.TransactionIsolationLevel.ReadCommitted,
|
|
||||||
// we only need to do this because we settleHodlInvoice inside the transaction
|
|
||||||
// ... and it's prone to timing out
|
|
||||||
timeout: 60000
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log('transition succeeded')
|
console.log('transition succeeded')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -103,10 +98,7 @@ export async function holdAction ({ data: { invoiceId }, models, lnd, boss }) {
|
|||||||
fromState: 'PENDING_HELD',
|
fromState: 'PENDING_HELD',
|
||||||
toState: 'HELD',
|
toState: 'HELD',
|
||||||
toData: invoice => {
|
toData: invoice => {
|
||||||
// XXX allow both held and confirmed invoices to do this transition
|
if (!invoice.is_held) {
|
||||||
// because it's possible for a prior settleHodlInvoice to have succeeded but
|
|
||||||
// timeout and rollback the transaction, leaving the invoice in a pending_held state
|
|
||||||
if (!(invoice.is_held || invoice.is_confirmed)) {
|
|
||||||
throw new Error('invoice is not held')
|
throw new Error('invoice is not held')
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -130,8 +122,7 @@ export async function holdAction ({ data: { invoiceId }, models, lnd, boss }) {
|
|||||||
await tx.invoice.update({
|
await tx.invoice.update({
|
||||||
where: { id: dbInvoice.id },
|
where: { id: dbInvoice.id },
|
||||||
data: {
|
data: {
|
||||||
actionResult: result,
|
actionResult: result
|
||||||
actionError: null
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user