Compare commits

...

11 Commits

Author SHA1 Message Date
k00b
4dd9088f25 fix #1945 2025-03-06 09:27:23 -06:00
soxa
b03e02e4cf
Expose env-dependent constant to service worker; Add Brave Browser-specific push registration error and guidance; Remove unused fetch debug plugin (#1947) 2025-03-06 09:24:49 -06:00
ekzyis
75d0a8e3d9
Fix undefined db for wallet logs (#1944) 2025-03-05 07:29:21 -06:00
k00b
d3e5af40ec fix trust after mathjs upgrade 2025-03-05 07:26:59 -06:00
ekzyis
bf54044a96
Also check for user before setting multi auth cookies (#1941)
* Move multi auth init

* Store same token as we return in jwt callback
2025-03-04 08:58:48 -06:00
k00b
8eb5a51fd6 move sanctioned country codes to env var 2025-03-03 18:14:36 -06:00
k00b
5a8804de79 disallow buying CCs through lnurl-pay and lightning address 2025-03-03 18:03:34 -06:00
Keyan
090203b579
Update extend-awards.yml adding issues: read 2025-03-03 15:41:04 -06:00
soxa
8baf725a37
fix safari videos regression, overflow clipping images (#1938) 2025-03-03 14:53:02 -06:00
Keyan
20b2f9d4c6
Update extend-awards.yml with contents write 2025-03-03 14:39:31 -06:00
Scroogey-SN
65cb25e28c
Extend awards action (#1939)
* remove debug job, restrict create-pull-request to only awards.txt, add documentation

* make create-pull-request use a custom branch, and filter that out, so PRs generated by action don't invoke action again

* add permissions: line

* pull-requests write instead of all

---------

Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
2025-03-03 14:35:22 -06:00
11 changed files with 38 additions and 34 deletions

View File

@ -5,6 +5,10 @@ on:
types: [ closed ] types: [ closed ]
branches: branches:
- master - master
permissions:
pull-requests: write
contents: write
issues: read
jobs: jobs:
if_merged: if_merged:
if: | if: |

View File

@ -7,8 +7,7 @@ export const anonable = false
export const paymentMethods = [ export const paymentMethods = [
PAID_ACTION_PAYMENT_METHODS.P2P, PAID_ACTION_PAYMENT_METHODS.P2P,
PAID_ACTION_PAYMENT_METHODS.DIRECT, PAID_ACTION_PAYMENT_METHODS.DIRECT
PAID_ACTION_PAYMENT_METHODS.OPTIMISTIC
] ]
export async function getCost ({ msats }) { export async function getCost ({ msats }) {

View File

@ -733,7 +733,10 @@ export function NotificationAlert () {
error error
? ( ? (
<Alert variant='danger' dismissible onClose={() => setError(null)}> <Alert variant='danger' dismissible onClose={() => setError(null)}>
<span>{error.toString()}</span> <span>{navigator?.brave && error.name === 'AbortError'
? 'Push registration failed. Enable "Use Google services for push messaging" in Brave\'s privacy settings and try again.'
: error.toString()}
</span>
</Alert> </Alert>
) )
: showAlert : showAlert

View File

@ -167,7 +167,6 @@
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
height: auto; height: auto;
overflow: hidden;
max-height: 25vh; max-height: 25vh;
aspect-ratio: var(--aspect-ratio); aspect-ratio: var(--aspect-ratio);
margin: 0; margin: 0;
@ -196,14 +195,11 @@
.p:has(> .mediaContainer) .mediaContainer video .p:has(> .mediaContainer) .mediaContainer video
{ {
block-size: revert-layer; block-size: revert-layer;
min-width: 30%;
max-width: stretch; max-width: stretch;
} }
.p.onlyImages { .p.onlyImages {
display: block;
}
.p.onlyImages:has(> .mediaContainer.loaded) {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;

View File

@ -92,9 +92,7 @@ export const RESERVED_MAX_USER_ID = 615
export const GLOBAL_SEED = USER_ID.k00b export const GLOBAL_SEED = USER_ID.k00b
export const FREEBIE_BASE_COST_THRESHOLD = 10 export const FREEBIE_BASE_COST_THRESHOLD = 10
// WIP ultimately subject to this list: https://ofac.treasury.gov/sanctions-programs-and-country-information export const SANCTIONED_COUNTRY_CODES = process.env.SANCTIONED_COUNTRY_CODES?.split(',') || []
// From lawyers: north korea, cuba, iran, ukraine, syria
export const SANCTIONED_COUNTRY_CODES = ['KP', 'CU', 'IR', 'UA', 'SY']
export const TERRITORY_COST_MONTHLY = 50000 export const TERRITORY_COST_MONTHLY = 50000
export const TERRITORY_COST_YEARLY = 500000 export const TERRITORY_COST_YEARLY = 500000

View File

@ -220,6 +220,7 @@ module.exports = withPlausibleProxy()({
'process.env.NEXT_PUBLIC_NORMAL_POLL_INTERVAL': JSON.stringify(process.env.NEXT_PUBLIC_NORMAL_POLL_INTERVAL), 'process.env.NEXT_PUBLIC_NORMAL_POLL_INTERVAL': JSON.stringify(process.env.NEXT_PUBLIC_NORMAL_POLL_INTERVAL),
'process.env.NEXT_PUBLIC_LONG_POLL_INTERVAL': JSON.stringify(process.env.NEXT_PUBLIC_LONG_POLL_INTERVAL), 'process.env.NEXT_PUBLIC_LONG_POLL_INTERVAL': JSON.stringify(process.env.NEXT_PUBLIC_LONG_POLL_INTERVAL),
'process.env.NEXT_PUBLIC_EXTRA_LONG_POLL_INTERVAL': JSON.stringify(process.env.NEXT_PUBLIC_EXTRA_LONG_POLL_INTERVAL), 'process.env.NEXT_PUBLIC_EXTRA_LONG_POLL_INTERVAL': JSON.stringify(process.env.NEXT_PUBLIC_EXTRA_LONG_POLL_INTERVAL),
'process.env.SANCTIONED_COUNTRY_CODES': JSON.stringify(process.env.SANCTIONED_COUNTRY_CODES),
'process.env.NEXT_IS_EXPORT_WORKER': 'true' 'process.env.NEXT_IS_EXPORT_WORKER': 'true'
}) })
] ]

View File

@ -125,15 +125,12 @@ function getCallbacks (req, res) {
token.sub = Number(token.id) token.sub = Number(token.id)
} }
// this only runs during a signup/login because response is only defined during signup/login // add multi_auth cookie for user that just logged in
// and will add the multi_auth cookies for the user we just logged in as if (user && req && res) {
if (req && res) {
req = new NodeNextRequest(req)
res = new NodeNextResponse(res)
const secret = process.env.NEXTAUTH_SECRET const secret = process.env.NEXTAUTH_SECRET
const jwt = await encodeJWT({ token, secret }) const jwt = await encodeJWT({ token, secret })
const me = await prisma.user.findUnique({ where: { id: token.id } }) const me = await prisma.user.findUnique({ where: { id: token.id } })
setMultiAuthCookies(req, res, { ...me, jwt }) setMultiAuthCookies(new NodeNextRequest(req), new NodeNextResponse(res), { ...me, jwt })
} }
return token return token

View File

@ -96,6 +96,6 @@ export default async ({ query: { username, amount, nostr, comment, payerdata: pa
}) })
} catch (error) { } catch (error) {
console.log(error) console.log(error)
res.status(400).json({ status: 'ERROR', reason: 'could not generate invoice' }) res.status(400).json({ status: 'ERROR', reason: 'could not generate invoice to customer\'s attached wallet' })
} }
} }

View File

@ -33,7 +33,7 @@ setDefaultHandler(new NetworkOnly({
plugins: [{ plugins: [{
fetchDidFail: async (args) => { fetchDidFail: async (args) => {
// tell us why a request failed in dev // tell us why a request failed in dev
process.env.NODE_ENV !== 'production' && console.log('fetch did fail', ...args) // process.env.NODE_ENV !== 'production' && console.log('fetch did fail', ...args)
}, },
fetchDidSucceed: async ({ request, response, event, state }) => { fetchDidSucceed: async ({ request, response, event, state }) => {
if ( if (

View File

@ -105,7 +105,7 @@ export function useWalletPayment () {
// if we reach this line, no wallet payment succeeded // if we reach this line, no wallet payment succeeded
throw new WalletPaymentAggregateError([aggregateError], latestInvoice) throw new WalletPaymentAggregateError([aggregateError], latestInvoice)
}, [wallets, invoiceHelper, sendPayment]) }, [wallets, invoiceHelper, sendPayment, loggerFactory])
} }
function invoiceController (inv, isInvoice) { function invoiceController (inv, isInvoice) {

View File

@ -18,15 +18,12 @@ export async function trust ({ boss, models }) {
const MAX_DEPTH = 10 const MAX_DEPTH = 10
const MAX_TRUST = 1 const MAX_TRUST = 1
const MIN_SUCCESS = 1 const MIN_SUCCESS = 1
// increasing disgree_mult increases distrust when there's disagreement
// ... this cancels DISAGREE_MULT number of "successes" for every disagreement
const DISAGREE_MULT = 10
// https://en.wikipedia.org/wiki/Normal_distribution#Quantile_function // https://en.wikipedia.org/wiki/Normal_distribution#Quantile_function
const Z_CONFIDENCE = 6.109410204869 // 99.9999999% confidence const Z_CONFIDENCE = 6.109410204869 // 99.9999999% confidence
const GLOBAL_ROOT = 616 const GLOBAL_ROOT = 616
const SEED_WEIGHT = 0.25 const SEED_WEIGHT = 1.0
const AGAINST_MSAT_MIN = 1000 const AGAINST_MSAT_MIN = 1000
const MSAT_MIN = 1000 const MSAT_MIN = 20001 // 20001 is the minimum for a tip to be counted in trust
const SIG_DIFF = 0.1 // need to differ by at least 10 percent const SIG_DIFF = 0.1 // need to differ by at least 10 percent
/* /*
@ -88,16 +85,16 @@ function trustGivenGraph (graph) {
const std = sqapply(mat, math.std) // math.squeeze(math.std(mat, 1)) const std = sqapply(mat, math.std) // math.squeeze(math.std(mat, 1))
const mean = sqapply(mat, math.mean) // math.squeeze(math.mean(mat, 1)) const mean = sqapply(mat, math.mean) // math.squeeze(math.mean(mat, 1))
const zscore = math.map(mat, (val, idx) => { const zscore = math.map(mat, (val, idx) => {
const zstd = math.subset(std, math.index(idx[0])) const zstd = math.subset(std, math.index(idx[0], 0))
const zmean = math.subset(mean, math.index(idx[0])) const zmean = math.subset(mean, math.index(idx[0], 0))
return zstd ? (val - zmean) / zstd : 0 return zstd ? (val - zmean) / zstd : 0
}) })
console.timeLog('trust', 'minmax') console.timeLog('trust', 'minmax')
const min = sqapply(zscore, math.min) // math.squeeze(math.min(zscore, 1)) const min = sqapply(zscore, math.min) // math.squeeze(math.min(zscore, 1))
const max = sqapply(zscore, math.max) // math.squeeze(math.max(zscore, 1)) const max = sqapply(zscore, math.max) // math.squeeze(math.max(zscore, 1))
const mPersonal = math.map(zscore, (val, idx) => { const mPersonal = math.map(zscore, (val, idx) => {
const zmin = math.subset(min, math.index(idx[0])) const zmin = math.subset(min, math.index(idx[0], 0))
const zmax = math.subset(max, math.index(idx[0])) const zmax = math.subset(max, math.index(idx[0], 0))
const zrange = zmax - zmin const zrange = zmax - zmin
if (val > zmax) return MAX_TRUST if (val > zmax) return MAX_TRUST
return zrange ? (val - zmin) / zrange : 0 return zrange ? (val - zmin) / zrange : 0
@ -123,7 +120,8 @@ async function getGraph (models) {
WITH user_votes AS ( WITH user_votes AS (
SELECT "ItemAct"."userId" AS user_id, users.name AS name, "ItemAct"."itemId" AS item_id, min("ItemAct".created_at) AS act_at, SELECT "ItemAct"."userId" AS user_id, users.name AS name, "ItemAct"."itemId" AS item_id, min("ItemAct".created_at) AS act_at,
users.created_at AS user_at, "ItemAct".act = 'DONT_LIKE_THIS' AS against, users.created_at AS user_at, "ItemAct".act = 'DONT_LIKE_THIS' AS against,
count(*) OVER (partition by "ItemAct"."userId") AS user_vote_count count(*) OVER (partition by "ItemAct"."userId") AS user_vote_count,
sum("ItemAct".msats) as user_msats
FROM "ItemAct" FROM "ItemAct"
JOIN "Item" ON "Item".id = "ItemAct"."itemId" AND "ItemAct".act IN ('FEE', 'TIP', 'DONT_LIKE_THIS') JOIN "Item" ON "Item".id = "ItemAct"."itemId" AND "ItemAct".act IN ('FEE', 'TIP', 'DONT_LIKE_THIS')
AND "Item"."parentId" IS NULL AND NOT "Item".bio AND "Item"."userId" <> "ItemAct"."userId" AND "Item"."parentId" IS NULL AND NOT "Item".bio AND "Item"."userId" <> "ItemAct"."userId"
@ -136,9 +134,9 @@ async function getGraph (models) {
), ),
user_pair AS ( user_pair AS (
SELECT a.user_id AS a_id, b.user_id AS b_id, SELECT a.user_id AS a_id, b.user_id AS b_id,
count(*) FILTER(WHERE a.act_at > b.act_at AND a.against = b.against) AS before, sum(CASE WHEN b.user_msats > a.user_msats THEN a.user_msats / b.user_msats::FLOAT ELSE b.user_msats / a.user_msats::FLOAT END) FILTER(WHERE a.act_at > b.act_at AND a.against = b.against) AS before,
count(*) FILTER(WHERE b.act_at > a.act_at AND a.against = b.against) AS after, sum(CASE WHEN b.user_msats > a.user_msats THEN a.user_msats / b.user_msats::FLOAT ELSE b.user_msats / a.user_msats::FLOAT END) FILTER(WHERE b.act_at > a.act_at AND a.against = b.against) AS after,
count(*) FILTER(WHERE a.against <> b.against) * ${DISAGREE_MULT} AS disagree, sum(log(1 + a.user_msats / 10000::float) + log(1 + b.user_msats / 10000::float)) FILTER(WHERE a.against <> b.against) AS disagree,
b.user_vote_count AS b_total, a.user_vote_count AS a_total b.user_vote_count AS b_total, a.user_vote_count AS a_total
FROM user_votes a FROM user_votes a
JOIN user_votes b ON a.item_id = b.item_id JOIN user_votes b ON a.item_id = b.item_id
@ -180,7 +178,7 @@ async function storeTrust (models, graph, vGlobal, mPersonal) {
}) })
math.forEach(mPersonal, (val, [fromIdx, toIdx]) => { math.forEach(mPersonal, (val, [fromIdx, toIdx]) => {
const globalVal = vGlobal.get([toIdx]) const globalVal = vGlobal.get([toIdx, 0])
if (isNaN(val) || val - globalVal <= SIG_DIFF) return if (isNaN(val) || val - globalVal <= SIG_DIFF) return
if (personalValues) personalValues += ',' if (personalValues) personalValues += ','
personalValues += `(${graph[fromIdx].id}, ${graph[toIdx].id}, ${val}::FLOAT)` personalValues += `(${graph[fromIdx].id}, ${graph[toIdx].id}, ${val}::FLOAT)`
@ -199,6 +197,14 @@ async function storeTrust (models, graph, vGlobal, mPersonal) {
SELECT id, oid, trust SELECT id, oid, trust
FROM (values ${personalValues}) g(id, oid, trust) FROM (values ${personalValues}) g(id, oid, trust)
ON CONFLICT ("fromId", "toId") DO UPDATE SET "zapTrust" = EXCLUDED."zapTrust"` ON CONFLICT ("fromId", "toId") DO UPDATE SET "zapTrust" = EXCLUDED."zapTrust"`
),
// select all arcs that don't exist in personalValues and delete them
models.$executeRawUnsafe(
`DELETE FROM "Arc"
WHERE ("fromId", "toId") NOT IN (
SELECT id, oid
FROM (values ${personalValues}) g(id, oid, trust)
)`
) )
]) ])
} }