Skip to content

Commit 858e3f8

Browse files
authored
changes and misc and stuff (#77)
* audit functions? * no more newsletter * use kvstore for page stats * kvstore all the things * fixes * update content
1 parent a15cc4a commit 858e3f8

11 files changed

Lines changed: 868 additions & 341 deletions

content

functions/kvstoreclient.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const fetch = require("node-fetch")
2+
3+
const KVstoreEndpoint = "https://kvstore.dmlas.workers.dev"
4+
console.log("key ", process.env.PRESHARED_KEY)
5+
const headers = {
6+
PRESHARED_KEY: process.env.PRESHARED_KEY,
7+
}
8+
9+
const get = async (key) => {
10+
const r = await fetch(KVstoreEndpoint, {
11+
headers,
12+
method: "POST",
13+
body: JSON.stringify({
14+
op: "READ",
15+
key,
16+
}),
17+
})
18+
const res = await r.text()
19+
return res
20+
}
21+
22+
const put = async (key, value) => {
23+
await fetch(KVstoreEndpoint, {
24+
headers,
25+
method: "POST",
26+
body: JSON.stringify({
27+
op: "WRITE",
28+
key,
29+
value,
30+
}),
31+
})
32+
return
33+
}
34+
35+
const clear = async (key) => {
36+
await fetch(KVstoreEndpoint, {
37+
headers,
38+
method: "POST",
39+
body: JSON.stringify({
40+
op: "DELETE",
41+
key,
42+
}),
43+
})
44+
return
45+
}
46+
47+
const list = async (prefix) => {
48+
const r = await fetch(KVstoreEndpoint, {
49+
headers,
50+
method: "POST",
51+
body: JSON.stringify({
52+
op: "LIST",
53+
prefix,
54+
}),
55+
})
56+
const res = await r.json()
57+
return res
58+
}
59+
60+
exports.get = get
61+
exports.put = put
62+
exports.clear = clear
63+
exports.list = list
64+

functions/package-lock.json

Lines changed: 725 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

functions/page-stats.js

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,48 @@
1-
const { GraphQLClient } = require("graphql-request")
1+
const { get, put } = require("./kvstoreclient")
22

3-
const hasuraEndpoint = "https://dshomoye.hasura.app/v1/graphql"
4-
const hasuraAdminKey = process.env.HASURA_ADMIN_KEY
5-
6-
const client = new GraphQLClient(hasuraEndpoint, {
7-
headers: {
8-
"x-hasura-admin-secret": hasuraAdminKey,
9-
},
10-
})
3+
const buildKey = (pathname, hostname) =>
4+
`dshomoye.dev:page_stats:likes:${hostname}:${pathname}`
115

126
const getPageLikes = async (pathname, hostname) => {
13-
const query = `query MyQuery {
14-
page_stats(where: {pathname: {_eq: "${pathname}"}, hostname: {_eq: "${hostname}"}}) {
15-
hostname
16-
likes
17-
pathname
18-
}
19-
}`
20-
const data = await client.request(query)
21-
return data.page_stats
22-
}
23-
24-
const addPage = async (pathname, hostname) => {
25-
const query = `mutation MyMutation {
26-
insert_page_stats(objects: {hostname: "${hostname}", pathname: "${pathname}"}) {
27-
returning {
28-
likes
29-
}
30-
}
31-
}`
32-
const res = await client.request(query)
33-
return res.insert_page_stats.returning
7+
const res = await get(buildKey(pathname, hostname))
8+
return res
349
}
3510

3611
const updatePageLike = async (pathname, hostname, by = 1) => {
37-
const query = `mutation MyMutation {
38-
update_page_stats(where: {hostname: {_eq: "${hostname}"}, pathname: {_eq: "${pathname}"}}, _inc: {likes: ${by}}) {
39-
returning {
40-
likes
41-
}
42-
}
43-
}`
44-
const res = await client.request(query)
45-
return res.update_page_stats.returning
12+
const current = await getPageLikes(pathname, hostname)
13+
if (!current) {
14+
const nextVal = by > 0 ? by : 0;
15+
console.log('updating page, current is ', nextVal)
16+
await put(buildKey(pathname, hostname), nextVal)
17+
return nextVal
18+
} else {
19+
let count = parseInt(current)
20+
count += by
21+
await put(buildKey(pathname, hostname), count)
22+
return count
23+
}
4624
}
4725

4826
exports.handler = async (event) => {
27+
if (event.httpMethod != "POST") {
28+
return {
29+
statusCode: 404,
30+
body: `{"error": "Not Found"}`,
31+
}
32+
}
4933
const eventData = JSON.parse(event.body)
5034
if (eventData.action === "get_likes") {
5135
const { pathname, hostname } = eventData.payload
5236
let res = await getPageLikes(pathname, hostname)
53-
if (res.length > 0) {
37+
if (!res) {
5438
return {
5539
statusCode: 200,
56-
body: JSON.stringify({
57-
likes: res[0].likes,
58-
}),
40+
body: JSON.stringify({ likes: 0 }),
5941
}
60-
}
61-
res = await addPage(pathname, hostname)
62-
if (res.length > 0) {
42+
} else {
6343
return {
6444
statusCode: 200,
65-
body: JSON.stringify(res[0]),
45+
body: JSON.stringify({ likes: res }),
6646
}
6747
}
6848
} else if (
@@ -77,7 +57,7 @@ exports.handler = async (event) => {
7757
)
7858
return {
7959
statusCode: 200,
80-
body: JSON.stringify(res[0]),
60+
body: JSON.stringify({ likes: res }),
8161
}
8262
}
8363

functions/push-notification.js

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
const { GraphQLClient } = require("graphql-request")
21
const webpush = require("web-push")
3-
4-
const hasuraEndpoint = "https://dshomoye.hasura.app/v1/graphql"
5-
const hasuraAdminKey = process.env.HASURA_ADMIN_KEY
6-
7-
const client = new GraphQLClient(hasuraEndpoint, {
8-
headers: {
9-
"x-hasura-admin-secret": hasuraAdminKey,
10-
},
11-
})
2+
const { get, list } = require("./kvstoreclient")
123

134
const vapidPrivateKey = process.env.VAPID_PRIVATE_KEY
145
const vapidPublicKey =
@@ -30,20 +21,18 @@ const isAuthenticated = (event) => {
3021
return false
3122
}
3223

33-
const getAllSubscriptions = async () => {
34-
const query = `query MyQuery {
35-
push_subscriptions {
36-
subscription
24+
const allSubscriptions = async () => {
25+
/** @type {string[]} */
26+
const allKeys = await list(`dshomoye.dev:push-subscriptions:`)
27+
const promises = allKeys.map(async (k) => {
28+
const r = await get(k)
29+
if (typeof r === "string") {
30+
return JSON.parse(r)
3731
}
38-
}`
39-
try {
40-
const data = await client.request(query)
41-
const subscriptions = data.push_subscriptions
42-
return subscriptions
43-
} catch (error) {
44-
console.error("error getting subs ", error)
45-
return []
46-
}
32+
return r
33+
})
34+
const result = await Promise.all(promises)
35+
return result
4736
}
4837

4938
const sendPushMsg = async (subscription, message) => {
@@ -70,7 +59,7 @@ exports.handler = async (event) => {
7059
}
7160
switch (method) {
7261
case "POST":
73-
const subscriptions = await getAllSubscriptions()
62+
const subscriptions = await allSubscriptions()
7463
const promises = subscriptions.map(async (subscription) => {
7564
return await sendPushMsg(subscription.subscription, event.body)
7665
})
@@ -86,7 +75,7 @@ exports.handler = async (event) => {
8675
default:
8776
return {
8877
statusCode: 400,
89-
body: `{"error": "Unsupportd method"}`,
78+
body: `{"error": "Unsupported method"}`,
9079
}
9180
}
9281
}

functions/push-subscription.js

Lines changed: 21 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,20 @@
1-
const { GraphQLClient } = require("graphql-request")
21
const { pushToSubscription } = require("./push-notification")
2+
const { put, clear } = require("./kvstoreclient")
33

4-
const hasuraEndpoint = "https://dshomoye.hasura.app/v1/graphql"
5-
const hasuraAdminKey = process.env.HASURA_ADMIN_KEY
6-
7-
const client = new GraphQLClient(hasuraEndpoint, {
8-
headers: {
9-
"x-hasura-admin-secret": hasuraAdminKey,
10-
},
11-
})
4+
const buildKey = (endpoint) => `dshomoye.dev:push-subscriptions:${endpoint}`
125

136
const addSubscription = async (subscription) => {
14-
const query = `mutation MyMutation($endpoint: String, $subscription: jsonb) {
15-
insert_push_subscriptions_one(object: {endpoint: $endpoint, subscription: $subscription}) {
16-
endpoint
17-
created_at
18-
subscription
19-
updated_at
20-
}
21-
}`
22-
const variables = {
23-
endpoint: subscription.endpoint,
24-
subscription,
25-
}
26-
try {
27-
const { status, errors } = await client.rawRequest(query, variables)
28-
console.log("status, error ", status, errors)
29-
if (status >= 300) {
30-
throw new Error(`Failed to add subscription: ${errors.toString()}`)
31-
}
32-
const welcomeMsg = JSON.stringify({
33-
title: "Awesome!",
34-
message: "Push Notifications are now enabled.",
35-
})
36-
const sent = await pushToSubscription(subscription, welcomeMsg)
37-
return {
38-
statusCode: 201,
39-
body: JSON.stringify({
40-
sent,
41-
}),
42-
}
43-
} catch (error) {
44-
console.error("error adding subsription: ", error)
45-
return {
46-
statusCode: 500,
47-
body: `${error}`,
48-
}
49-
}
7+
await put(buildKey(subscription.endpoint), JSON.stringify(subscription))
8+
const welcomeMsg = JSON.stringify({
9+
title: "Awesome!",
10+
message: "Push Notifications are now enabled.",
11+
})
12+
const sent = await pushToSubscription(subscription, welcomeMsg)
13+
return sent
5014
}
5115

5216
const removeSubscription = async (endpoint) => {
53-
const query = `mutation MyMutation {
54-
delete_push_subscriptions_by_pk(endpoint: "${endpoint}") {
55-
updated_at
56-
}
57-
}`
58-
try {
59-
await client.request(query)
60-
return {
61-
statusCode: 204,
62-
}
63-
} catch (error) {
64-
console.error("error deleting subscripton ", error)
65-
return {
66-
statusCode: 500,
67-
body: JSON.stringify(error),
68-
}
69-
}
17+
await clear(buildKey(endpoint))
7018
}
7119

7220
exports.handler = async function (event) {
@@ -75,8 +23,13 @@ exports.handler = async function (event) {
7523
case "POST":
7624
try {
7725
const addResponse = await addSubscription(JSON.parse(event.body))
78-
console.log("New Subscription handled.")
79-
return addResponse
26+
return {
27+
statusCode: 201,
28+
body: JSON.stringify({
29+
message: "saved",
30+
sent: addResponse
31+
})
32+
}
8033
} catch (error) {
8134
console.error("Error saving subscription ", error)
8235
return {
@@ -87,9 +40,11 @@ exports.handler = async function (event) {
8740
case "DELETE":
8841
try {
8942
const eventData = JSON.parse(event.body)
90-
const delResponse = await removeSubscription(eventData.endpoint)
43+
await removeSubscription(eventData.endpoint)
9144
console.log("Successfully unsubsribed: ", eventData.endpoint)
92-
return delResponse
45+
return {
46+
statusCode: 204
47+
}
9348
} catch (error) {
9449
console.error("Failed to delete subscription ", error)
9550
return {

functions/submission-created.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)