1
0
Fork 0
mirror of https://github.com/voltbonn/diversity.volt.link.git synced 2024-06-28 08:50:56 +00:00

removed volt.link api stuff and tracking

This commit is contained in:
thomasrosen 2022-11-20 00:00:57 +01:00
parent c2f9dbad64
commit a555093f10
2 changed files with 4 additions and 511 deletions

411
index.js
View file

@ -1,6 +1,6 @@
require('dotenv').config()
const isDevEnvironment = process.env.environment === 'dev' || false
// const isDevEnvironment = process.env.environment === 'dev' || false
const path = require('path')
const url = require('url')
@ -9,14 +9,14 @@ const http = require('http')
const express = require('express')
const rateLimit = require('express-rate-limit')
const { fetch } = require('cross-fetch')
const { sendInitialStats } = require('./stats.js')
// const { fetch } = require('cross-fetch')
const fs = require('fs')
const ObjectId = require('mongodb').ObjectId // just to check ObjectIDs
const static_files_path = path.join(__dirname, './frontend/')
// volt_team_api_key
function checkOrigin(origin){
return (
typeof origin === 'string'
@ -91,257 +91,6 @@ app.get('/login', (req, res) => {
}))
})
const blockQuery = `
_id
type
properties
content {
blockId
block {
_id
type
properties
content {
blockId
}
parent
metadata {
modified
modified_by
}
permissions
computed {
roles
inherited_block_permissions
contentAsPlaintext
}
}
}
parent
metadata {
modified
modified_by
}
permissions
computed {
roles
inherited_block_permissions
contentAsPlaintext
}
`
async function getBlockBySlug(slug, headers = {}) {
return new Promise(resolve => {
fetch((
isDevEnvironment
? 'http://0.0.0.0:4004/graphql/v1/'
: 'https://api.volt.link/graphql/v1/'
), {
method: 'POST',
body: JSON.stringify({
query: `query ($slug: String!) {
block: blockBySlug (slug: $slug) {
${blockQuery}
}
}`,
variables: {
slug,
}
}),
headers: {
...headers,
'content-type': 'application/json',
}
})
.then(async data => {
data = await data.json()
if (
data
&& data.data
&& data.data.block
) {
resolve(data.data.block)
} else {
resolve(null)
}
})
.catch(error => {
console.error(error)
resolve(null)
})
})
}
async function getBlockById(id, headers = {}) {
return new Promise(resolve => {
fetch((
isDevEnvironment
? 'http://0.0.0.0:4004/graphql/v1/'
: 'https://api.volt.link/graphql/v1/'
), {
method: 'POST',
body: JSON.stringify({
query: `query ($_id: ObjectID!) {
block (_id: $_id) {
${blockQuery}
}
}`,
variables: {
_id: id,
}
}),
headers: {
...headers,
'content-type': 'application/json',
}
})
.then(async data => {
data = await data.json()
if (
data
&& data.data
&& data.data.block
) {
resolve(data.data.block)
} else {
resolve(null)
}
})
.catch(error => {
console.error(error)
resolve(null)
})
})
}
async function getBlocks(ids = [], slugs = [], headers = {}) {
return new Promise(resolve => {
ids = ids.filter(id => ObjectId.isValid(id))
fetch((
isDevEnvironment
? 'http://0.0.0.0:4004/graphql/v1/'
: 'https://api.volt.link/graphql/v1/'
), {
method: 'POST',
body: JSON.stringify({
query: `query ($ids: [ObjectID], $slugs: [String]) {
blocks (ids: $ids, slugs: $slugs) {
${blockQuery}
}
}`,
variables: {
ids,
slugs,
}
}),
headers: {
...headers,
'content-type': 'application/json',
}
})
.then(async data => {
data = await data.json()
if (
data
&& data.data
&& data.data.blocks
) {
resolve(data.data.blocks)
} else {
resolve(null)
}
})
.catch(error => {
console.error(error)
resolve(null)
})
})
}
async function getSlugInfos(slug, headers = {}) {
return new Promise(resolve => {
fetch((
isDevEnvironment
? 'http://0.0.0.0:4004/graphql/v1/'
: 'https://api.volt.link/graphql/v1/'
), {
method: 'POST',
body: JSON.stringify({
query: `query checkSlug ($slug: String!) {
checkSlug (slug: $slug) {
existsAsSlug
existsAsId
}
}`,
variables: {
slug: slug,
}
}),
headers: {
...headers,
'content-type': 'application/json',
}
})
.then(async data => {
data = await data.json()
if (
data
&& data.data
&& data.data.checkSlug
) {
resolve({
existsAsSlug: data.data.checkSlug.existsAsSlug || false,
existsAsId: data.data.checkSlug.existsAsId || false,
})
} else {
resolve({
existsAsSlug: false,
existsAsId: false,
})
}
})
.catch(error => {
console.error('error for checkSlug:', error)
resolve({
existsAsSlug: false,
existsAsId: false,
})
})
})
}
async function getBlockBySlugOrId(slugOrId, headers = {}) {
let block = await getBlockBySlug(slugOrId, headers)
if (block) {
return {
block,
used_query: 'slug',
}
} else {
block = await getBlockById(slugOrId, headers)
return {
block,
used_query: 'id',
}
}
}
function getImageUrl(imageObj) {
if (
typeof imageObj === 'object'
&& imageObj !== null
&& !Array.isArray(imageObj)
) {
if (imageObj.type === 'url') {
return imageObj.url || ''
}
}
return ''
}
function showClient(res, blocks = []) {
// send index file to show client
const index_file_path = static_files_path + '/index.html'
@ -402,162 +151,10 @@ function showClient(res, blocks = []) {
// (TODO: There currently is no function to find the correct slug from an id.)
}
function normalizeSlug(slug) {
if (typeof slug === 'string') {
slug = slug
.trim()
.toLowerCase()
// .replace(/_/g, '-')
return slug
}
return null
}
let static_files_cache = null
async function getIsStaticFile(slug) {
if (static_files_cache === null) {
const filenames = fs.readdirSync(static_files_path, { withFileTypes: true })
.map(({ name: filename }) => normalizeSlug(filename))
const filetypes = fs.readdirSync(static_files_path, { withFileTypes: true })
.reduce((filetypes, fileinfos) => {
filetypes[fileinfos.name] = {
isFile: fileinfos.isFile(),
}
return filetypes
}, {})
static_files_cache = {
filenames,
filetypes,
}
}
if (static_files_cache !== null) {
slug = normalizeSlug(slug)
const isStaticFile = static_files_cache.filenames.includes(slug)
let isFile = false
if (static_files_cache.filetypes.hasOwnProperty(slug)) {
isFile = static_files_cache.filetypes[slug].isFile
}
return {
isStaticFile,
isFile,
}
}
return {
isStaticFile: false,
isFile: false,
}
}
app.get('/', async function (req, res, next) {
showClient(res) // call showClient to replace the default meta infos (__META_TITLE__, ...)
})
app.get(/^\/([^=/]*)(?:=?)([^=/]*)(.*)/, async function (req, res, next) {
const headers = {
cookie: req.headers.cookie, // for authentication
'user-agent': req.headers['user-agent'], // for analytics
referer: req.headers.referer, // for analytics
}
const group0 = req.params[0] // slug (or id if group1 is empty) // capture-group before separator
const group1 = req.params[1] // id // capture-group after separator
// const group2 = req.params[2] // suffix
const {
isStaticFile,
isFile,
} = await getIsStaticFile(group0)
if (isStaticFile === true) {
// captureGroupBeforeSeparator is a file. Not a slug or id.
if (isFile === true) {
res.sendFile(static_files_path + group0)
} else {
// Go to the next route.
// The next route shows static files.
next('route')
}
} else {
let done = false
if (done === false && !!group0 && !group1) {
const blocks = await getBlocks([group0], [group0], headers)
if (!!blocks && blocks.length > 0) {
// This gets called for "/:slug"
// group0 is a slug
// redirect it accoringly
const block = blocks[0]
if (block.type === 'redirect') {
let redirect_url = block.properties.url || ''
if (typeof redirect_url === 'string' && redirect_url !== '') {
done = true
// log redirect
try {
const website = isDevEnvironment
? process.env.umami_id_dev
: process.env.umami_id_prod
const hostname = isDevEnvironment
? 'localhost'
: 'volt.link'
const url = req.originalUrl
sendInitialStats({ website, url, hostname }, req.headers)
} catch (error) {
console.error('umami-error:', error)
}
// redirect
res.redirect(redirect_url)
}
}
if (done === false) {
done = true
showClient(res, blocks)
}
}
}
if (done === false && !!group1) {
// This gets called for "/:slug=:id"
// check if group1 is ID by finding it in the database
const block = await getBlockById(group1, headers)
if (!!block && !!block._id) {
if (done === false) {
done = true
showClient(res, [block])
}
}
}
if (
done === false
&& typeof group0 === 'string' && group0 !== ''
) {
// Error 403 and 404. These are checked in more detail on the client.
done = true
showClient(res)
}
if (done === false) {
next('route')
}
}
})
app.use(express.static(static_files_path))
app.get('*', function (req, res, next) {

104
stats.js
View file

@ -1,104 +0,0 @@
const https = require('https')
const { acceptedLanguages } = require('@fluent/langneg')
function trackPageview(payload, headers) {
const data = JSON.stringify({
payload: {
website: '', // 'your-website-id',
url: '/',
referrer: '',
hostname: '', // 'your-hostname',
language: '', // 'en-US',
screen: '', // '1920x1080',
...payload,
},
type: 'pageview'
})
const req = https.request({
hostname: 'umami.qiekub.org',
port: 443,
path: '/api/collect',
method: 'POST',
headers: {
'User-Agent': headers['user-agent'] || '',
'Accept-Language': headers['accept-language'] || '',
'Content-Type': 'application/json',
'Content-Length': data.length,
}
}, null)
req.on('error', error => console.error(error))
req.write(data)
req.end()
}
function trackEvent(payload, headers) {
const data = JSON.stringify({
payload: {
website: '', // 'your-website-id',
url: '/',
event_type: 'custom', // 'click',
event_value: '', // 'signup-button',
hostname: '', // 'your-hostname',
language: '', // 'en-US',
screen: '1920x1080',
...payload,
},
type: 'event'
})
const req = https.request({
hostname: 'umami.qiekub.org',
port: 443,
path: '/api/collect',
method: 'POST',
headers: {
'User-Agent': headers['user-agent'] || '',
'Accept-Language': headers['accept-language'] || '',
'Content-Type': 'application/json',
'Content-Length': data.length,
}
}, null)
req.on('error', error => console.error(error))
req.write(data)
req.end()
}
function sendInitialStats({
website = '',
url = '/',
hostname = ''
}, headers = {}) {
const userLocales = acceptedLanguages(headers['accept-language'] || '')
if (!!userLocales || Array.isArray(userLocales)) {
const defaultPayload = {
website,
url,
hostname,
language: userLocales.length > 0 ? userLocales[0] : '',
}
trackPageview(defaultPayload, headers)
for (let locale of userLocales) {
locale = locale.toLowerCase() // Not really correct but the system locales sadly don't conform to the standard.
const language = locale.split('-')[0]
if (language !== locale) {
trackEvent({
...defaultPayload,
event_value: `L: ${language}`, // Log just the language.
}, headers)
}
trackEvent({
...defaultPayload,
event_value: `L: ${locale}`, // Log the full locale.
}, headers)
}
}
}
module.exports = {
sendInitialStats,
}