base: Fix upload support for null
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
base: Tweak serve to be slightly more extendable discord_embed: Added new site, discord embed
This commit is contained in:
parent
9b227ead62
commit
2b1e2d695a
17 changed files with 577 additions and 21 deletions
|
@ -15,20 +15,27 @@ export function uploadMedia(file) {
|
|||
}
|
||||
}
|
||||
|
||||
console.log(media)
|
||||
|
||||
let body = {}
|
||||
|
||||
if (media.preview) {
|
||||
body.preview = media.preview
|
||||
}
|
||||
if (media.small?.avif) {
|
||||
body.small = media.small.avif
|
||||
}
|
||||
if (media.medium?.avif) {
|
||||
body.medium = media.medium.avif
|
||||
}
|
||||
if (media.large?.avif) {
|
||||
body.large = media.large.avif
|
||||
}
|
||||
|
||||
return client.upload(media.path + '?token=' + token, { file: {
|
||||
file: file.path,
|
||||
filename: file.name,
|
||||
} }, 'POST', {
|
||||
preview: media.preview,
|
||||
small: media.small?.avif,
|
||||
medium: media.medium?.avif,
|
||||
large: media.large?.avif,
|
||||
/*
|
||||
|
||||
small: media.small.jpeg,
|
||||
medium: media.medium.avif,
|
||||
large_jpeg: mediakl.large.jpeg,*/
|
||||
}).then(res => {
|
||||
} }, 'POST', body).then(res => {
|
||||
out.filename = res.filename
|
||||
out.path = res.path
|
||||
out.preview = res.preview
|
||||
|
@ -38,11 +45,18 @@ export function uploadMedia(file) {
|
|||
out.size = file.size
|
||||
out.type = file.type
|
||||
|
||||
return client.post(media.path + '/' + out.filename + '?token=' + token, {
|
||||
small: media.small?.jpeg,
|
||||
medium: media.medium?.jpeg,
|
||||
large: media.large?.jpeg,
|
||||
})
|
||||
let body = {}
|
||||
if (media.small?.jpeg) {
|
||||
body.small = media.small.jpeg
|
||||
}
|
||||
if (media.medium?.jpeg) {
|
||||
body.medium = media.medium.jpeg
|
||||
}
|
||||
if (media.large?.jpeg) {
|
||||
body.large = media.large.jpeg
|
||||
}
|
||||
|
||||
return client.post(media.path + '/' + out.filename + '?token=' + token, body)
|
||||
.then(res => {
|
||||
if (out.sizes.small) { out.sizes.small.jpeg = res.small }
|
||||
if (out.sizes.medium) { out.sizes.medium.jpeg = res.medium }
|
||||
|
|
|
@ -22,8 +22,11 @@ export default class ServeHandler {
|
|||
}
|
||||
|
||||
let indexFile = fsSync.readFileSync(path.join(this.root, 'index.html'))
|
||||
this.loadTemplate(indexFile)
|
||||
}
|
||||
|
||||
loadTemplate(indexFile) {
|
||||
this.template = dot.template(indexFile.toString(), { argName: ['headerDescription', 'headerImage', 'headerTitle', 'headerUrl', 'payloadData', 'payloadTree', 'version', 'nonce', 'type', 'banner', 'media', 'in_debug'] })
|
||||
// console.log(indexFile.toString())
|
||||
}
|
||||
|
||||
register(server) {
|
||||
|
|
|
@ -53,6 +53,10 @@ export default class Server {
|
|||
|
||||
this.flaska.before(function(ctx) {
|
||||
ctx.state.started = new Date().getTime()
|
||||
ctx.req.ip = ctx.req.headers['x-forwarded-for'] || ctx.req.connection.remoteAddress
|
||||
ctx.log = ctx.log.child({
|
||||
id: Math.random().toString(36).substring(2, 14),
|
||||
})
|
||||
ctx.db = pool
|
||||
})
|
||||
this.flaska.before(QueryHandler())
|
||||
|
@ -92,6 +96,7 @@ export default class Server {
|
|||
ctx.log[level]({
|
||||
duration: requestTime,
|
||||
status: ctx.status,
|
||||
ip: ctx.req.ip,
|
||||
}, (ctx.aborted ? '[ABORT]' : '<--') + ` ${status}${ctx.method} ${ctx.url}`)
|
||||
})
|
||||
}
|
||||
|
|
85
discord_embed/api/id.mjs
Normal file
85
discord_embed/api/id.mjs
Normal file
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Javascript AlphabeticID class
|
||||
* (based on a script by Kevin van Zonneveld <kevin@vanzonneveld.net>)
|
||||
*
|
||||
* Author: Even Simon <even.simon@gmail.com>
|
||||
*
|
||||
* Description: Translates a numeric identifier into a short string and backwords.
|
||||
*
|
||||
* Usage:
|
||||
* var str = AlphabeticID.encode(9007199254740989); // str = 'fE2XnNGpF'
|
||||
* var id = AlphabeticID.decode('fE2XnNGpF'); // id = 9007199254740989;
|
||||
**/
|
||||
|
||||
const AlphabeticID = {
|
||||
index:'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
|
||||
/**
|
||||
* [@function](https://twitter.com/function) AlphabeticID.encode
|
||||
* [@description](https://twitter.com/description) Encode a number into short string
|
||||
* [@param](https://twitter.com/param) integer
|
||||
* [@return](https://twitter.com/return) string
|
||||
**/
|
||||
encode:function(_number){
|
||||
if('undefined' == typeof _number){
|
||||
return null;
|
||||
}
|
||||
else if('number' != typeof(_number)){
|
||||
throw new Error('Wrong parameter type');
|
||||
}
|
||||
|
||||
var ret = '';
|
||||
|
||||
for(var i=Math.floor(Math.log(parseInt(_number))/Math.log(AlphabeticID.index.length));i>=0;i--){
|
||||
ret = ret + AlphabeticID.index.substr((Math.floor(parseInt(_number) / AlphabeticID.bcpow(AlphabeticID.index.length, i)) % AlphabeticID.index.length),1);
|
||||
}
|
||||
|
||||
return reverse(ret);
|
||||
},
|
||||
|
||||
/**
|
||||
* [@function](https://twitter.com/function) AlphabeticID.decode
|
||||
* [@description](https://twitter.com/description) Decode a short string and return number
|
||||
* [@param](https://twitter.com/param) string
|
||||
* [@return](https://twitter.com/return) integer
|
||||
**/
|
||||
decode:function(_string){
|
||||
if('undefined' == typeof _string){
|
||||
return null;
|
||||
}
|
||||
else if('string' != typeof _string){
|
||||
throw new Error('Wrong parameter type');
|
||||
}
|
||||
|
||||
var str = reverse(_string);
|
||||
var ret = 0;
|
||||
|
||||
for(var i=0;i<=(str.length - 1);i++){
|
||||
ret = ret + AlphabeticID.index.indexOf(str.substr(i,1)) * (AlphabeticID.bcpow(AlphabeticID.index.length, (str.length - 1) - i));
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
/**
|
||||
* [@function](https://twitter.com/function) AlphabeticID.bcpow
|
||||
* [@description](https://twitter.com/description) Raise _a to the power _b
|
||||
* [@param](https://twitter.com/param) float _a
|
||||
* [@param](https://twitter.com/param) integer _b
|
||||
* [@return](https://twitter.com/return) string
|
||||
**/
|
||||
bcpow:function(_a, _b){
|
||||
return Math.floor(Math.pow(parseFloat(_a), parseInt(_b)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* [@function](https://twitter.com/function) String.reverse
|
||||
* [@description](https://twitter.com/description) Reverse a string
|
||||
* [@return](https://twitter.com/return) string
|
||||
**/
|
||||
function reverse(str){
|
||||
return str.split('').reverse().join('');
|
||||
};
|
||||
|
||||
export default AlphabeticID
|
96
discord_embed/api/post.mjs
Normal file
96
discord_embed/api/post.mjs
Normal file
|
@ -0,0 +1,96 @@
|
|||
import { uploadMedia } from '../base/media/upload.mjs'
|
||||
import config from '../base/config.mjs'
|
||||
|
||||
export default class IndexPost {
|
||||
constructor(opts = {}) {
|
||||
Object.assign(this, {
|
||||
frontend: opts.frontend,
|
||||
uploadMedia: uploadMedia,
|
||||
})
|
||||
}
|
||||
|
||||
register(server) {
|
||||
this.serve = server.routes.serve
|
||||
server.flaska.post('/', [
|
||||
server.formidable({ maxFileSize: 8 * 1024 * 1024, }),
|
||||
], this.createNewLink.bind(this))
|
||||
}
|
||||
|
||||
hasErrors(ctx, hasMedia) {
|
||||
if (!ctx.req.body.video) {
|
||||
return 'Missing video link'
|
||||
}
|
||||
|
||||
if (!ctx.req.body.video.startsWith('http')
|
||||
|| !(ctx.req.body.video.includes('mp4')
|
||||
|| ctx.req.body.video.includes('webm'))) {
|
||||
return 'Video link has to be a valid full url and contain mp4 or webm in it'
|
||||
}
|
||||
|
||||
if (!ctx.req.body.image && !hasMedia) {
|
||||
return 'Missing image link or file'
|
||||
}
|
||||
|
||||
if (ctx.req.body.image) {
|
||||
if (!ctx.req.body.image.startsWith('http')
|
||||
|| !(ctx.req.body.image.includes('jpg')
|
||||
|| ctx.req.body.image.includes('jpeg')
|
||||
|| ctx.req.body.image.includes('webp')
|
||||
|| ctx.req.body.image.includes('png')
|
||||
)
|
||||
) {
|
||||
return 'Image link has to be a valid full url and contain jpg, jpeg, webp or png'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** PUT: /api/auth/articles/:id */
|
||||
async createNewLink(ctx) {
|
||||
let hasMedia = ctx.req.files.media && ctx.req.files.media.size
|
||||
|
||||
ctx.state.video = ctx.req.body.video
|
||||
ctx.state.image = ctx.req.body.image
|
||||
let redirect = ''
|
||||
let error = this.hasErrors(ctx, hasMedia)
|
||||
|
||||
if (!error && hasMedia) {
|
||||
try {
|
||||
let temp = await this.uploadMedia(ctx.req.files.media)
|
||||
ctx.state.image = ctx.req.body.image = 'https://cdn.nfp.is' + temp.sizes.small.jpeg.path
|
||||
}
|
||||
catch (err) {
|
||||
ctx.log.error(err)
|
||||
error = 'Unable to upload file: ' + err.message
|
||||
}
|
||||
}
|
||||
if (!error) {
|
||||
redirect = `${this.frontend}/?v=${ctx.state.video}&i=${ctx.state.image}`
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
try {
|
||||
let params = [
|
||||
]
|
||||
let res = await ctx.db.safeCallProc('discord_embed.link_add', params)
|
||||
console.log(res)
|
||||
}
|
||||
catch (err) {
|
||||
ctx.log.error(err)
|
||||
error = 'Error while generating shortened link.'
|
||||
}
|
||||
}
|
||||
|
||||
if (redirect && !error) {
|
||||
ctx.status = 302
|
||||
ctx.headers['Location'] = redirect
|
||||
ctx.type = 'text/html; charset=utf-8'
|
||||
ctx.body = `
|
||||
Redirecting
|
||||
<a href="${redirect}">Click here if it doesn't redirect</a>
|
||||
`
|
||||
}
|
||||
ctx.state.error = error
|
||||
return this.serve.serveIndex(ctx)
|
||||
}
|
||||
}
|
||||
// https://litter.catbox.moe/cnl6hy.mp4
|
46
discord_embed/api/serve.mjs
Normal file
46
discord_embed/api/serve.mjs
Normal file
|
@ -0,0 +1,46 @@
|
|||
import path from 'path'
|
||||
import Parent from '../base/serve.mjs'
|
||||
import fs from 'fs/promises'
|
||||
import fsSync from 'fs'
|
||||
import dot from 'dot'
|
||||
import config from '../base/config.mjs'
|
||||
|
||||
export default class ServeHandler extends Parent {
|
||||
loadTemplate(indexFile) {
|
||||
this.template = dot.template(indexFile.toString(), { argName: [
|
||||
'imageLink',
|
||||
'videoLink',
|
||||
'error',
|
||||
'siteUrl',
|
||||
'siteUrlBase',
|
||||
'version',
|
||||
'nonce',
|
||||
'in_debug',
|
||||
'inputVideo',
|
||||
'inputImage'
|
||||
] })
|
||||
}
|
||||
|
||||
async serveIndex(ctx) {
|
||||
if (config.get('NODE_ENV') === 'development') {
|
||||
let indexFile = await fs.readFile(path.join(this.root, 'index.html'))
|
||||
this.loadTemplate(indexFile)
|
||||
}
|
||||
|
||||
let payload = {
|
||||
imageLink: ctx.query.get('i') || '',
|
||||
videoLink: ctx.query.get('v') || '',
|
||||
error: ctx.state.error || '',
|
||||
inputVideo: ctx.state.video || ctx.query.get('v') || '',
|
||||
inputImage: ctx.state.image || ctx.query.get('i') || '',
|
||||
siteUrl: this.frontend + ctx.url,
|
||||
siteUrlBase: this.frontend + '/',
|
||||
version: this.version,
|
||||
nonce: ctx.state.nonce,
|
||||
in_debug: config.get('NODE_ENV') === 'development' && false,
|
||||
}
|
||||
|
||||
ctx.body = this.template(payload)
|
||||
ctx.type = 'text/html; charset=utf-8'
|
||||
}
|
||||
}
|
22
discord_embed/api/server.mjs
Normal file
22
discord_embed/api/server.mjs
Normal file
|
@ -0,0 +1,22 @@
|
|||
import config from '../base/config.mjs'
|
||||
import Parent from '../base/server.mjs'
|
||||
import IndexPost from './post.mjs'
|
||||
import ServeHandler from './serve.mjs'
|
||||
|
||||
export default class Server extends Parent {
|
||||
init() {
|
||||
super.init()
|
||||
let localUtil = new this.core.sc.Util(import.meta.url)
|
||||
|
||||
this.routes = {
|
||||
post: new IndexPost({
|
||||
frontend: config.get('frontend:url'),
|
||||
})
|
||||
}
|
||||
this.routes.serve = new ServeHandler({
|
||||
root: localUtil.getPathFromRoot('../public'),
|
||||
version: this.core.app.running,
|
||||
frontend: config.get('frontend:url'),
|
||||
})
|
||||
}
|
||||
}
|
1
discord_embed/base
Symbolic link
1
discord_embed/base
Symbolic link
|
@ -0,0 +1 @@
|
|||
../base
|
8
discord_embed/build-package.json
Normal file
8
discord_embed/build-package.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"scripts": {
|
||||
"build": "echo done;"
|
||||
},
|
||||
"dependencies": {
|
||||
"service-core": "^3.0.0-beta.17"
|
||||
}
|
||||
}
|
24
discord_embed/dev.mjs
Normal file
24
discord_embed/dev.mjs
Normal file
|
@ -0,0 +1,24 @@
|
|||
import fs from 'fs'
|
||||
import { ServiceCore } from 'service-core'
|
||||
import * as index from './index.mjs'
|
||||
|
||||
const port = 4120
|
||||
|
||||
var core = new ServiceCore('nfp_moe', import.meta.url, port, '')
|
||||
|
||||
let config = {
|
||||
frontend: {
|
||||
url: 'http://localhost:' + port
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync('./config.json'))
|
||||
} catch {}
|
||||
|
||||
config.port = port
|
||||
|
||||
core.setConfig(config)
|
||||
core.init(index).then(function() {
|
||||
return core.run()
|
||||
})
|
11
discord_embed/index.mjs
Normal file
11
discord_embed/index.mjs
Normal file
|
@ -0,0 +1,11 @@
|
|||
import config from './base/config.mjs'
|
||||
|
||||
export function start(http, port, ctx) {
|
||||
config.sources[1].store = ctx.config
|
||||
|
||||
return import('./api/server.mjs')
|
||||
.then(function(module) {
|
||||
let server = new module.default(http, port, ctx)
|
||||
return server.run()
|
||||
})
|
||||
}
|
47
discord_embed/package.json
Normal file
47
discord_embed/package.json
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"name": "av1_embed",
|
||||
"version": "1.0.0",
|
||||
"port": 4120,
|
||||
"description": "AV1 discord server embed helper",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node --experimental-modules index.mjs",
|
||||
"dev:server": "node dev.mjs | bunyan",
|
||||
"dev": "npm-watch dev:server"
|
||||
},
|
||||
"watch": {
|
||||
"dev:server": {
|
||||
"patterns": [
|
||||
"api/*",
|
||||
"base/*",
|
||||
"../base/*"
|
||||
],
|
||||
"extensions": "js,mjs",
|
||||
"quiet": true,
|
||||
"inherit": true
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.nfp.is/nfp/nfp_sites.git"
|
||||
},
|
||||
"author": "Jonatan Nilsson",
|
||||
"license": "WTFPL",
|
||||
"bugs": {
|
||||
"url": "https://git.nfp.is/nfp/nfp_sites/issues"
|
||||
},
|
||||
"homepage": "https://git.nfp.is/nfp/nfp_sites",
|
||||
"dependencies": {
|
||||
"dot": "^2.0.0-beta.1",
|
||||
"flaska": "^1.3.0",
|
||||
"formidable": "^1.2.6",
|
||||
"ioredis": "^5.2.3",
|
||||
"nconf-lite": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"service-core": "^3.0.0-beta.17"
|
||||
}
|
||||
}
|
0
discord_embed/public/app.css
Normal file
0
discord_embed/public/app.css
Normal file
BIN
discord_embed/public/favicon.png
Normal file
BIN
discord_embed/public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3 KiB |
BIN
discord_embed/public/heart.png
Normal file
BIN
discord_embed/public/heart.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 393 KiB |
192
discord_embed/public/index.html
Normal file
192
discord_embed/public/index.html
Normal file
|
@ -0,0 +1,192 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Discord Embedder from AV1 server</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
{{ if (imageLink) { }}
|
||||
<meta property="og:image" content="{{=imageLink}}">
|
||||
<meta property="og:type" content="video.other">
|
||||
<meta property="og:video:url" content="{{=videoLink}}">
|
||||
<meta property="og:video:width" content="1280">
|
||||
<meta property="og:video:height" content="720">
|
||||
{{ } else { }}
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="{{=siteUrl}}" />
|
||||
<meta property="og:image" content="/heart.png" />
|
||||
<meta property="og:description" content="Simple site to help with embedding of AV1 videos and large/external videos into Discord." />
|
||||
<meta property="og:title" content="Discord Embedder Helper Website" />
|
||||
{{ } }}
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<style>
|
||||
|
||||
:root {
|
||||
--content-max-width: 1280px;
|
||||
--bg: black;
|
||||
--bg-content-alt: #333;
|
||||
--color: #d7dadc;
|
||||
--link: #bb4d00;
|
||||
--button-border: 1px solid #f57c00;
|
||||
--button-bg: #ffad42;
|
||||
--button-fg: #000;
|
||||
--error: red;
|
||||
}
|
||||
|
||||
/* Box sizing rules */
|
||||
*, *::before, *::after { box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Remove default margin */
|
||||
body, h1, h2, h3, h4, p, figure, blockquote, dl, dd {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
text-rendering: optimizeSpeed;
|
||||
line-height: 1.5;
|
||||
font-size: 16px;
|
||||
font-family: sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
input, button, textarea, select {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.488rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2.074rem;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.728rem;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.44rem;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1.0rem;
|
||||
}
|
||||
|
||||
a, a:visited, button {
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
input[type=text] {
|
||||
border: 1px solid var(--color);
|
||||
background: var(--bg);
|
||||
color: var(--color);
|
||||
border-radius: 0;
|
||||
padding: 0.25rem;
|
||||
line-height: 1rem;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.25rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
input[type=text]:hover,
|
||||
input[type=text]:active,
|
||||
input[type=text]:focus {
|
||||
border-color: var(--link);
|
||||
}
|
||||
|
||||
input[type=text]:focus {
|
||||
outline: 1px solid var(--link);
|
||||
}
|
||||
|
||||
button,
|
||||
input[type=submit] {
|
||||
border: var(--button-border);
|
||||
background: var(--button-bg);
|
||||
color: var(--button-fg);
|
||||
padding: 0.25rem 1rem;
|
||||
margin: 1rem 0 2rem;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: var(--bg-content-alt);
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.row-item {
|
||||
flex: 2 0 200px;
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.row-item input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.row-inbetween {
|
||||
align-self: flex-end;
|
||||
padding: 0.25rem 1rem;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--error);
|
||||
font-size: 0.8rem;
|
||||
padding: 1rem 1rem 0;
|
||||
}
|
||||
|
||||
.inside {
|
||||
width: 100%;
|
||||
max-width: var(--content-max-width);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<form action="/" method="post" enctype="multipart/form-data" class="inside">
|
||||
<h1>Create/generate embed url</h1>
|
||||
{{ if (error) { }}<p class="error">{{=error}}</p>{{ } }}
|
||||
<label>Video link</label>
|
||||
<input type="text" name="video" value="{{=inputVideo}}">
|
||||
<div class="row">
|
||||
<div class="row-item">
|
||||
<label>Image link (required for proper discord embed)</label>
|
||||
<input type="text" name="image" value="{{=inputImage}}">
|
||||
</div>
|
||||
<span class="row-inbetween">or</span>
|
||||
<div class="row-item">
|
||||
<label>Upload image file (max 8MiB)</label>
|
||||
<input type="file" name="media">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Generate embed url">
|
||||
|
||||
<p>
|
||||
Alternatively, you can generate a link yourself using the following syntax:
|
||||
</p>
|
||||
<pre>
|
||||
{{=siteUrlBase}}?v=<video link>&i=<image link>
|
||||
</pre>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -2,7 +2,6 @@ import path from 'path'
|
|||
import striptags from 'striptags'
|
||||
import Parent from '../base/serve.mjs'
|
||||
import fs from 'fs/promises'
|
||||
import dot from 'dot'
|
||||
import config from '../base/config.mjs'
|
||||
|
||||
export default class ServeHandler extends Parent {
|
||||
|
@ -49,11 +48,11 @@ export default class ServeHandler extends Parent {
|
|||
async serveIndex(ctx) {
|
||||
if (config.get('NODE_ENV') === 'development') {
|
||||
let indexFile = await fs.readFile(path.join(this.root, 'index.html'))
|
||||
this.template = dot.template(indexFile.toString(), { argName: ['headerDescription', 'headerImage', 'headerTitle', 'headerUrl', 'payloadData', 'payloadTree', 'version', 'nonce', 'type', 'banner', 'media', 'in_debug'] })
|
||||
this.loadTemplate(indexFile)
|
||||
}
|
||||
|
||||
let payload = {
|
||||
headerDescription: 'Small fansubbing and scanlation group translating and encoding our favourite shows from Japan.',
|
||||
headerDescription: 'A small fansubbing and scanlation group translating and encoding our favourite shows from Japan.',
|
||||
headerImage: this.frontend + '/assets/img/heart.png',
|
||||
headerTitle: 'NFP Moe - Anime/Manga translation group',
|
||||
headerUrl: this.frontend + ctx.url,
|
||||
|
@ -87,7 +86,8 @@ export default class ServeHandler extends Parent {
|
|||
|
||||
if (data.page) {
|
||||
payload.headerTitle = data.page.name + ' - NFP Moe'
|
||||
if (data.page.content.blocks.length) {
|
||||
payload.headerDescription = 'Page ' + data.page.name + ' over at NFP Moe. ' + payload.headerDescription
|
||||
if (data.page.content.blocks?.length) {
|
||||
payload.headerDescription = this.getDescriptionFromBlocks(data.page.content.blocks) || payload.headerDescription
|
||||
}
|
||||
if (data.page.media_alt_prefix) {
|
||||
|
@ -114,6 +114,8 @@ export default class ServeHandler extends Parent {
|
|||
payload.media = data.article?.media_avif_preview || false
|
||||
payload.payloadData = JSON.stringify(data)
|
||||
payload.type = 'article'
|
||||
} else if (ctx.url !== '/login' && !ctx.url.startsWith('/admin/')) {
|
||||
ctx.status = 404
|
||||
}
|
||||
} catch (e) {
|
||||
ctx.log.error(e)
|
||||
|
|
Loading…
Reference in a new issue