pockethost 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +16 -0
- package/dist/index.mjs +3156 -0
- package/dist/instance-app/migrations/1699198734_pockethost_defaults.js +39 -0
- package/dist/instance-app/pb_hooks/_ph_admin_sync.pb.js +71 -0
- package/dist/instance-app/pb_hooks/_ph_lib.js +19 -0
- package/dist/instance-app/tsconfig.json +8 -0
- package/dist/instance-app/types/goja.d.ts +58 -0
- package/dist/instance-app/types/lib.d.ts +5 -0
- package/dist/instance-app/types/types.d.ts +19573 -0
- package/dist/mothership-app/migrations/1705062576_collections_snapshot.js +1863 -0
- package/dist/mothership-app/migrations/1705083826_updated_stats.js +721 -0
- package/dist/mothership-app/migrations/1706060446_updated_instances.js +44 -0
- package/dist/mothership-app/pb_hooks/src/instances-create.pb.js +65 -0
- package/dist/mothership-app/pb_hooks/src/instances-delete.pb.js +69 -0
- package/dist/mothership-app/pb_hooks/src/instances-migrate-versions.pb.js +33 -0
- package/dist/mothership-app/pb_hooks/src/instances-notify-discord-after-create.pb.js +31 -0
- package/dist/mothership-app/pb_hooks/src/instances-notify-on-maintenance-mode.pb.js +52 -0
- package/dist/mothership-app/pb_hooks/src/instances-reset-idle.pb.js +7 -0
- package/dist/mothership-app/pb_hooks/src/instances-update.pb.js +121 -0
- package/dist/mothership-app/pb_hooks/src/instances-validate-before-create.pb.js +16 -0
- package/dist/mothership-app/pb_hooks/src/instances-validate-before-update.pb.js +43 -0
- package/dist/mothership-app/pb_hooks/src/lib.js +171 -0
- package/dist/mothership-app/pb_hooks/src/ls.pb.js +159 -0
- package/dist/mothership-app/pb_hooks/src/mail.pb.js +49 -0
- package/dist/mothership-app/pb_hooks/src/notifications.pb.js +62 -0
- package/dist/mothership-app/pb_hooks/src/random-words.js +2085 -0
- package/dist/mothership-app/pb_hooks/src/signup.pb.js +214 -0
- package/dist/mothership-app/pb_hooks/src/sns.pb.js +133 -0
- package/dist/mothership-app/pb_hooks/src/unsubscribe.pb.js +33 -0
- package/dist/mothership-app/pb_hooks/src/user-token.pb.js +33 -0
- package/dist/mothership-app/pb_hooks/src/user-welcome-msg.pb.js +32 -0
- package/dist/mothership-app/pb_hooks/src/versions-route.pb.js +12 -0
- package/dist/mothership-app/pb_hooks/src/versions.js +0 -0
- package/dist/mothership-app/pb_hooks/tsconfig.json +8 -0
- package/dist/mothership-app/pb_hooks/types/global.d.ts +1 -0
- package/dist/mothership-app/pb_hooks/types/goja.d.ts +58 -0
- package/dist/mothership-app/pb_hooks/types/lemon.d.ts +12 -0
- package/dist/mothership-app/pb_hooks/types/lib.d.ts +55 -0
- package/dist/mothership-app/pb_hooks/types/types.d.ts +19573 -0
- package/dist/mothership-app/ph_app/index.js +11 -0
- package/dist/mothership-app/ph_app/package-lock.json +657 -0
- package/dist/mothership-app/ph_app/package.json +14 -0
- package/package.json +144 -0
- package/readme.md +168 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
routerAdd('POST', '/api/ls', (c) => {
|
|
2
|
+
const dao = $app.dao()
|
|
3
|
+
const { audit, mkLog, enqueueNotification } = /** @type {Lib} */ (
|
|
4
|
+
require(`${__hooks}/lib.js`)
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
const log = mkLog(`ls`)
|
|
8
|
+
|
|
9
|
+
const secret = $os.getenv('LS_WEBHOOK_SECRET')
|
|
10
|
+
log(`Secret`, secret)
|
|
11
|
+
|
|
12
|
+
const raw = readerToString(c.request().body)
|
|
13
|
+
const data = JSON.parse(raw)
|
|
14
|
+
log(`payload`, JSON.stringify(data, null, 2))
|
|
15
|
+
|
|
16
|
+
/** @type {WebHook} */
|
|
17
|
+
let {
|
|
18
|
+
meta: {
|
|
19
|
+
custom_data: { user_id },
|
|
20
|
+
},
|
|
21
|
+
data: {
|
|
22
|
+
type,
|
|
23
|
+
attributes: {
|
|
24
|
+
order_number,
|
|
25
|
+
first_order_item: { product_name, /** @type {number} */ product_id },
|
|
26
|
+
status,
|
|
27
|
+
user_email: email,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
} = data
|
|
31
|
+
|
|
32
|
+
log({ user_id, order_number, product_name, product_id, status, email })
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
if (!user_id) {
|
|
36
|
+
throw new Error(`No user ID`)
|
|
37
|
+
} else {
|
|
38
|
+
log(`user ID ok`, user_id)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (![`orders`].includes(type)) {
|
|
42
|
+
throw new Error(`Unsupported event: ${type}`)
|
|
43
|
+
} else {
|
|
44
|
+
log(`event type ok`)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (![`active`, `paid`].includes(status)) {
|
|
48
|
+
throw new Error(`Unsupported status: ${status}`)
|
|
49
|
+
} else {
|
|
50
|
+
log(`status ok`, status)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!order_number) {
|
|
54
|
+
throw new Error(`No order #`)
|
|
55
|
+
} else {
|
|
56
|
+
log(`order # ok`, order_number)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const userRec = (() => {
|
|
60
|
+
try {
|
|
61
|
+
return dao.findFirstRecordByData('users', 'id', user_id)
|
|
62
|
+
} catch (e) {}
|
|
63
|
+
})()
|
|
64
|
+
if (!userRec) {
|
|
65
|
+
throw new Error(`User ${user_id} not found`)
|
|
66
|
+
} else {
|
|
67
|
+
log(`user record ok`, userRec)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** @type{{[_:number]: ()=>void}} */
|
|
71
|
+
const editions = {
|
|
72
|
+
// Founder's annual
|
|
73
|
+
159792: () => {
|
|
74
|
+
userRec.set(`subscription`, `premium`)
|
|
75
|
+
userRec.set(`isFounder`, true)
|
|
76
|
+
},
|
|
77
|
+
// Founder's lifetime
|
|
78
|
+
159794: () => {
|
|
79
|
+
userRec.set(`subscription`, `lifetime`)
|
|
80
|
+
userRec.set(`isFounder`, true)
|
|
81
|
+
},
|
|
82
|
+
// Pro annual
|
|
83
|
+
159791: () => {
|
|
84
|
+
userRec.set(`subscription`, `premium`)
|
|
85
|
+
},
|
|
86
|
+
// Pro monthly
|
|
87
|
+
159790: () => {
|
|
88
|
+
userRec.set(`subscription`, `premium`)
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const applyEditionSpecifics = editions[product_id]
|
|
93
|
+
if (!applyEditionSpecifics) {
|
|
94
|
+
throw new Error(`Product ID not found: ${product_id}`)
|
|
95
|
+
} else {
|
|
96
|
+
log(`product id ok`, product_id)
|
|
97
|
+
}
|
|
98
|
+
applyEditionSpecifics()
|
|
99
|
+
|
|
100
|
+
const payment = new Record(dao.findCollectionByNameOrId('payments'), {
|
|
101
|
+
user: user_id,
|
|
102
|
+
payment_id: `ls_${order_number}`,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
dao.runInTransaction((txDao) => {
|
|
106
|
+
log(`transaction started`)
|
|
107
|
+
if (!userRec.getDateTime(`welcome`)) {
|
|
108
|
+
enqueueNotification(`email`, `welcome`, user_id, { log, dao: txDao })
|
|
109
|
+
userRec.set(`welcome`, new DateTime())
|
|
110
|
+
}
|
|
111
|
+
txDao.saveRecord(userRec)
|
|
112
|
+
log(`saved user`)
|
|
113
|
+
txDao.saveRecord(payment)
|
|
114
|
+
log(`saved payment`)
|
|
115
|
+
txDao
|
|
116
|
+
.db()
|
|
117
|
+
.newQuery(
|
|
118
|
+
`update settings set value=value-1 where name='founders-edition-count'`,
|
|
119
|
+
)
|
|
120
|
+
.execute()
|
|
121
|
+
log(`saved founder count`)
|
|
122
|
+
|
|
123
|
+
log(`about to enqueue email`)
|
|
124
|
+
enqueueNotification(`email`, `lemon_order_email`, user_id, {
|
|
125
|
+
dao: txDao,
|
|
126
|
+
log,
|
|
127
|
+
})
|
|
128
|
+
log(`about to enqueue lemonbot`)
|
|
129
|
+
enqueueNotification(`lemonbot`, `lemon_order_discord`, user_id, {
|
|
130
|
+
dao: txDao,
|
|
131
|
+
log,
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
log(`saved discord notice`)
|
|
135
|
+
})
|
|
136
|
+
log(`database updated`)
|
|
137
|
+
audit(`LS`, `Order ${order_number} ${product_name} processed.`, {
|
|
138
|
+
log,
|
|
139
|
+
dao,
|
|
140
|
+
extra: {
|
|
141
|
+
email,
|
|
142
|
+
user: user_id,
|
|
143
|
+
},
|
|
144
|
+
})
|
|
145
|
+
} catch (e) {
|
|
146
|
+
audit(`LS_ERR`, `${e}`, {
|
|
147
|
+
log,
|
|
148
|
+
dao,
|
|
149
|
+
extra: {
|
|
150
|
+
email,
|
|
151
|
+
user: user_id,
|
|
152
|
+
raw_payload: raw,
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
return c.json(500, `${e}`)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return c.json(200, { status: 'ok' })
|
|
159
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
routerAdd(
|
|
4
|
+
'POST',
|
|
5
|
+
'/api/mail',
|
|
6
|
+
(c) => {
|
|
7
|
+
const { mkLog, audit } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
|
8
|
+
const log = mkLog(`mail`)
|
|
9
|
+
|
|
10
|
+
let data = /** @type {{ to: string; subject: string; body: string }} */ (
|
|
11
|
+
new DynamicModel({
|
|
12
|
+
to: '',
|
|
13
|
+
subject: '',
|
|
14
|
+
body: '',
|
|
15
|
+
})
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
log(`before bind`)
|
|
19
|
+
|
|
20
|
+
c.bind(data)
|
|
21
|
+
|
|
22
|
+
log(`after bind`)
|
|
23
|
+
|
|
24
|
+
// This is necessary for destructuring to work correctly
|
|
25
|
+
data = JSON.parse(JSON.stringify(data))
|
|
26
|
+
|
|
27
|
+
log(`bind parsed`, JSON.stringify(data))
|
|
28
|
+
|
|
29
|
+
const { to, subject, body } = data
|
|
30
|
+
|
|
31
|
+
const email = new MailerMessage({
|
|
32
|
+
from: {
|
|
33
|
+
address: $app.settings().meta.senderAddress,
|
|
34
|
+
name: $app.settings().meta.senderName,
|
|
35
|
+
},
|
|
36
|
+
to: [{ address: to }],
|
|
37
|
+
subject: subject,
|
|
38
|
+
html: body,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
$app.newMailClient().send(email)
|
|
42
|
+
|
|
43
|
+
const msg = `Sent to ${to}`
|
|
44
|
+
log(msg)
|
|
45
|
+
|
|
46
|
+
return c.json(200, { status: 'ok' })
|
|
47
|
+
},
|
|
48
|
+
$apis.requireAdminAuth(),
|
|
49
|
+
)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
routerAdd(`GET`, `api/process_single_notification`, (c) => {
|
|
4
|
+
const { mkLog, processNotification } = /** @type {Lib} */ (
|
|
5
|
+
require(`${__hooks}/lib.js`)
|
|
6
|
+
)
|
|
7
|
+
const log = mkLog(`process_single_notification`)
|
|
8
|
+
log(`start`)
|
|
9
|
+
|
|
10
|
+
const dao = $app.dao()
|
|
11
|
+
try {
|
|
12
|
+
const notification = dao.findFirstRecordByData(
|
|
13
|
+
`notifications`,
|
|
14
|
+
`delivered`,
|
|
15
|
+
``,
|
|
16
|
+
)
|
|
17
|
+
if (!notification) {
|
|
18
|
+
return c.json(200, `No notifications to send`)
|
|
19
|
+
}
|
|
20
|
+
processNotification(notification, {
|
|
21
|
+
log,
|
|
22
|
+
dao,
|
|
23
|
+
test: !!c.queryParam(`test`),
|
|
24
|
+
})
|
|
25
|
+
} catch (e) {
|
|
26
|
+
c.json(500, `${e}`)
|
|
27
|
+
}
|
|
28
|
+
return c.json(200, { status: 'ok' })
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
onModelAfterCreate((e) => {
|
|
32
|
+
const dao = e.dao || $app.dao()
|
|
33
|
+
return
|
|
34
|
+
const { processNotification, mkLog, audit } = /** @type {Lib} */ (
|
|
35
|
+
require(`${__hooks}/lib.js`)
|
|
36
|
+
)
|
|
37
|
+
const log = mkLog(`notification:sendImmediately`)
|
|
38
|
+
|
|
39
|
+
const notificationRec = /** @type {models.Record} */ (e.model)
|
|
40
|
+
|
|
41
|
+
log({ notificationRec })
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
dao.expandRecord(notificationRec, ['message_template'], null)
|
|
45
|
+
|
|
46
|
+
const messageTemplateRec = notificationRec.expandedOne(`message_template`)
|
|
47
|
+
if (!messageTemplateRec) {
|
|
48
|
+
throw new Error(`Missing message template`)
|
|
49
|
+
}
|
|
50
|
+
if ([`maintenance-mode`].includes(messageTemplateRec.getString(`slug`))) {
|
|
51
|
+
processNotification(notificationRec, { log, dao })
|
|
52
|
+
}
|
|
53
|
+
} catch (e) {
|
|
54
|
+
audit(`ERROR`, `${e}`, {
|
|
55
|
+
log,
|
|
56
|
+
dao,
|
|
57
|
+
extra: {
|
|
58
|
+
notification: notificationRec.getId(),
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}, `notifications`)
|