mirror of
https://github.com/voltbonn/diversity.volt.link.git
synced 2024-09-29 13:26:13 +00:00
removed volt.link api stuff and tracking
This commit is contained in:
parent
c2f9dbad64
commit
a555093f10
411
index.js
411
index.js
|
@ -1,6 +1,6 @@
|
||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
|
|
||||||
const isDevEnvironment = process.env.environment === 'dev' || false
|
// const isDevEnvironment = process.env.environment === 'dev' || false
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const url = require('url')
|
const url = require('url')
|
||||||
|
|
||||||
|
@ -9,14 +9,14 @@ const http = require('http')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
const rateLimit = require('express-rate-limit')
|
const rateLimit = require('express-rate-limit')
|
||||||
|
|
||||||
const { fetch } = require('cross-fetch')
|
// const { fetch } = require('cross-fetch')
|
||||||
const { sendInitialStats } = require('./stats.js')
|
|
||||||
|
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const ObjectId = require('mongodb').ObjectId // just to check ObjectIDs
|
|
||||||
|
|
||||||
const static_files_path = path.join(__dirname, './frontend/')
|
const static_files_path = path.join(__dirname, './frontend/')
|
||||||
|
|
||||||
|
// volt_team_api_key
|
||||||
|
|
||||||
function checkOrigin(origin){
|
function checkOrigin(origin){
|
||||||
return (
|
return (
|
||||||
typeof origin === 'string'
|
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 = []) {
|
function showClient(res, blocks = []) {
|
||||||
// send index file to show client
|
// send index file to show client
|
||||||
const index_file_path = static_files_path + '/index.html'
|
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.)
|
// (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) {
|
app.get('/', async function (req, res, next) {
|
||||||
showClient(res) // call showClient to replace the default meta infos (__META_TITLE__, ...)
|
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.use(express.static(static_files_path))
|
||||||
|
|
||||||
app.get('*', function (req, res, next) {
|
app.get('*', function (req, res, next) {
|
||||||
|
|
104
stats.js
104
stats.js
|
@ -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,
|
|
||||||
}
|
|
Loading…
Reference in a new issue