reorganized routes, store memos in db
This commit is contained in:
parent
7e3b2606f9
commit
17858006f6
@ -1,6 +1,7 @@
|
|||||||
SESSION_SECRET=
|
SESSION_SECRET=
|
||||||
MONGODB_CONN="mongodb://127.0.0.1:27017/howfeed"
|
MONGODB_CONN="mongodb://127.0.0.1:27017/howfeed"
|
||||||
SALT_WORK_FACTOR=10
|
SALT_WORK_FACTOR=10
|
||||||
|
API_TOKEN=token123
|
||||||
|
|
||||||
SMTP_SERVER=
|
SMTP_SERVER=
|
||||||
SMTP_PORT=587
|
SMTP_PORT=587
|
||||||
|
13
src/models/memo.js
Normal file
13
src/models/memo.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
|
||||||
|
const { Schema } = mongoose;
|
||||||
|
const MemoSchema = new Schema({
|
||||||
|
message: { type: String, required: true },
|
||||||
|
author: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'User'
|
||||||
|
},
|
||||||
|
time: { type: Date, default: Date.now }
|
||||||
|
});
|
||||||
|
|
||||||
|
export default mongoose.model('Memo', MemoSchema);
|
12
src/routes/a/random.js
Normal file
12
src/routes/a/random.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Article from '../../models/article.js';
|
||||||
|
|
||||||
|
export async function get(req, res, next)
|
||||||
|
{
|
||||||
|
var articleCount = await Article.countDocuments();
|
||||||
|
var random = Math.floor(Math.random() * articleCount);
|
||||||
|
var randomArticle = await Article.findOne().skip(random).select('slug');
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify(randomArticle));
|
||||||
|
}
|
42
src/routes/api/meet.js
Normal file
42
src/routes/api/meet.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import NodeCache from 'node-cache';
|
||||||
|
const cache = new NodeCache();
|
||||||
|
|
||||||
|
export async function get(req, res, next)
|
||||||
|
{
|
||||||
|
if (req.query.token === process.env.API_TOKEN) {
|
||||||
|
const time = cache.get('lastMeetingTime');
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
LastMeetingTime: time ? time.toJSON() : undefined
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function post(req, res, next)
|
||||||
|
{
|
||||||
|
if (req.body.token === process.env.API_TOKEN) {
|
||||||
|
const time = new Date();
|
||||||
|
const success = cache.set('lastMeetingTime', time, 3600);
|
||||||
|
if (success) {
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
LastMeetingTime: time.toJSON()
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
res.writeHead(500, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
Error: 'Failed to store meeting time in cache!'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
84
src/routes/api/memo.js
Normal file
84
src/routes/api/memo.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import Memo from '../../models/memo.js';
|
||||||
|
|
||||||
|
export async function get(req, res, next)
|
||||||
|
{
|
||||||
|
if (req.query.token === process.env.API_TOKEN) {
|
||||||
|
try {
|
||||||
|
const memos = await Memo.find();
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify(memos));
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(500, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
Error: 'Failed to retrieve memos from database!'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function post(req, res, next)
|
||||||
|
{
|
||||||
|
if (req.body.token === process.env.API_TOKEN) {
|
||||||
|
const msg = req.body.message;
|
||||||
|
if (!msg) {
|
||||||
|
res.writeHead(400, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
Error: 'You must provide a memo message'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const memo = await new Memo({
|
||||||
|
message: msg,
|
||||||
|
author: req.user && req.user._id
|
||||||
|
});
|
||||||
|
await memo.save();
|
||||||
|
const memos = await Memo.find();
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify(memos));
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(500, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
Error: 'Failed to store memo in database!'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function del(req, res, next)
|
||||||
|
{
|
||||||
|
if (req.body.token === process.env.API_TOKEN) {
|
||||||
|
const { id } = req.params;
|
||||||
|
const memo = await Memo.findOneAndDelete(id);
|
||||||
|
|
||||||
|
if (memo) {
|
||||||
|
const memos = await Memo.find();
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify(memos));
|
||||||
|
} else {
|
||||||
|
res.writeHead(404, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: `Not found`
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
8
src/routes/cms/logout.js
Normal file
8
src/routes/cms/logout.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export async function get(req, res)
|
||||||
|
{
|
||||||
|
req.logout();
|
||||||
|
req.session.destroy(function (err) {
|
||||||
|
if (err) next(err);
|
||||||
|
return res.redirect('/');
|
||||||
|
});
|
||||||
|
}
|
@ -1,6 +1,68 @@
|
|||||||
|
import crypto from 'crypto';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import User from '../../models/user.js';
|
import User from '../../models/user.js';
|
||||||
|
|
||||||
|
export async function post(req, res, next)
|
||||||
|
{
|
||||||
|
if (!req.user) {
|
||||||
|
res.writeHead(401, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: `You must be logged in to set an avatar.`
|
||||||
|
}));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const { upload } = req.files;
|
||||||
|
if (!upload) {
|
||||||
|
res.writeHead(422, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: `You must supply a file.`
|
||||||
|
}));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!/^image\//.test(upload.mimetype)) {
|
||||||
|
res.writeHead(422, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: `Invalid MIME type for the uploaded image.`
|
||||||
|
}));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (upload.truncated) {
|
||||||
|
res.writeHead(422, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: `Received truncated image file. Try again with a smaller file.`
|
||||||
|
}));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const ext = upload.name.match(/(\.[^.]+)$/)[0];
|
||||||
|
const filename = crypto.randomBytes(20).toString('hex') + ext;
|
||||||
|
const url = `/u/${filename}`;
|
||||||
|
await upload.mv('./static' + url);
|
||||||
|
const user = await User.findById(req.user._id);
|
||||||
|
req.user.avatar = user.avatar = filename;
|
||||||
|
await user.save();
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({ filename }));
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(500, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: `Failed to upload image: ${err}`
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function del(req, res)
|
export async function del(req, res)
|
||||||
{
|
{
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
|
41
src/routes/rss.xml.js
Normal file
41
src/routes/rss.xml.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import RSS from 'rss';
|
||||||
|
import Article from '../models/article.js';
|
||||||
|
|
||||||
|
export async function get(req, res)
|
||||||
|
{
|
||||||
|
let year = new Date().getFullYear();
|
||||||
|
let feed = new RSS({
|
||||||
|
title: 'HowFeed.biz Articles',
|
||||||
|
feed_url: 'http://howfeed.biz/rss.xml',
|
||||||
|
site_url: 'http://howfeed.biz/',
|
||||||
|
image_url: 'http://howfeed.biz/logo.png',
|
||||||
|
language: 'en',
|
||||||
|
webMaster: 'webmaster@howfeed.biz',
|
||||||
|
copyright: `${year} FemboyFinancial Holdings Co., Ltd. (USA LLC)`
|
||||||
|
});
|
||||||
|
let articles = await Article.find().populate({
|
||||||
|
path: 'author',
|
||||||
|
select: 'realname avatar'
|
||||||
|
}).populate({
|
||||||
|
path: 'category'
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let article of articles) {
|
||||||
|
feed.item({
|
||||||
|
title: article.title,
|
||||||
|
description: article.html,
|
||||||
|
url: `http://howfeed.biz/a/${article.slug}`,
|
||||||
|
categories: [ article.category.name ],
|
||||||
|
author: article.author.realname,
|
||||||
|
date: article.created_at,
|
||||||
|
enclosure: {
|
||||||
|
url: `http://howfeed.biz/a/${article.image}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/rss+xml'
|
||||||
|
});
|
||||||
|
res.end(feed.xml());
|
||||||
|
}
|
52
src/routes/suggestions.js
Normal file
52
src/routes/suggestions.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
import nodemailer from 'nodemailer';
|
||||||
|
|
||||||
|
const { SMTP_USERNAME, SMTP_PASSWORD, SMTP_SERVER, SMTP_PORT, SMTP_RECIPIENTS } = process.env;
|
||||||
|
const mailer = nodemailer.createTransport({
|
||||||
|
host: SMTP_SERVER,
|
||||||
|
port: 587,
|
||||||
|
secure: SMTP_PORT === 465,
|
||||||
|
auth: {
|
||||||
|
user: SMTP_USERNAME,
|
||||||
|
pass: SMTP_PASSWORD
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function post(req, res)
|
||||||
|
{
|
||||||
|
let { name, title, message } = req.body;
|
||||||
|
if (!message) {
|
||||||
|
res.writeHead(422, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: 'No message supplied'
|
||||||
|
}));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name = name || 'Anonymous';
|
||||||
|
title = title || 'Suggestion';
|
||||||
|
try {
|
||||||
|
await mailer.sendMail({
|
||||||
|
from: `"HowFeed Suggestions" <${SMTP_USERNAME}>`,
|
||||||
|
to: SMTP_RECIPIENTS,
|
||||||
|
subject: title,
|
||||||
|
text: `Suggested by ${name}:
|
||||||
|
|
||||||
|
${message}`
|
||||||
|
});
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: 'Your suggestion was delivered.'
|
||||||
|
}));
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(500, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: err.message
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
255
src/server.js
255
src/server.js
@ -1,3 +1,4 @@
|
|||||||
|
require('dotenv').config();
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import session from 'express-session';
|
import session from 'express-session';
|
||||||
import compression from 'compression';
|
import compression from 'compression';
|
||||||
@ -9,27 +10,21 @@ import { Strategy } from 'passport-local';
|
|||||||
import sessionFileStore from 'session-file-store';
|
import sessionFileStore from 'session-file-store';
|
||||||
import { RateLimiterMemory } from 'rate-limiter-flexible';
|
import { RateLimiterMemory } from 'rate-limiter-flexible';
|
||||||
import fileUpload from 'express-fileupload';
|
import fileUpload from 'express-fileupload';
|
||||||
import nodemailer from 'nodemailer';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import helmet from 'helmet';
|
import helmet from 'helmet';
|
||||||
import useragent from 'useragent';
|
import useragent from 'useragent';
|
||||||
import RSS from 'rss';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import NodeCache from 'node-cache';
|
|
||||||
import Article from './models/article.js';
|
import Article from './models/article.js';
|
||||||
import Category from './models/category.js';
|
import Category from './models/category.js';
|
||||||
import User from './models/user.js';
|
import User from './models/user.js';
|
||||||
import legacyMiddleware from './legacy/middleware.js';
|
import legacyMiddleware from './legacy/middleware.js';
|
||||||
import legacyRouter from './legacy/router.js';
|
import legacyRouter from './legacy/router.js';
|
||||||
|
|
||||||
require('dotenv').config();
|
|
||||||
const FileStore = sessionFileStore(session);
|
const FileStore = sessionFileStore(session);
|
||||||
const cache = new NodeCache();
|
|
||||||
|
|
||||||
const { PORT, NODE_ENV, SESSION_SECRET, MONGODB_CONN,
|
const { PORT, NODE_ENV, SESSION_SECRET, MONGODB_CONN } = process.env;
|
||||||
SMTP_USERNAME, SMTP_PASSWORD, SMTP_SERVER, SMTP_PORT, SMTP_RECIPIENTS } = process.env;
|
|
||||||
const dev = NODE_ENV === 'development';
|
const dev = NODE_ENV === 'development';
|
||||||
|
|
||||||
mongoose.set('useNewUrlParser', true);
|
mongoose.set('useNewUrlParser', true);
|
||||||
@ -115,16 +110,6 @@ const isAuthor = function(req, res, next) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const mailer = nodemailer.createTransport({
|
|
||||||
host: SMTP_SERVER,
|
|
||||||
port: 587,
|
|
||||||
secure: SMTP_PORT === 465,
|
|
||||||
auth: {
|
|
||||||
user: SMTP_USERNAME,
|
|
||||||
pass: SMTP_PASSWORD
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
app.set('view engine', 'ejs');
|
app.set('view engine', 'ejs');
|
||||||
@ -149,13 +134,6 @@ mainRouter
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.get('/cms/logout', (req, res, next) => {
|
|
||||||
req.logout();
|
|
||||||
req.session.destroy(function (err) {
|
|
||||||
if (err) next(err);
|
|
||||||
return res.redirect('/');
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.post('/cms/article/:edit?',
|
.post('/cms/article/:edit?',
|
||||||
isAuthor,
|
isAuthor,
|
||||||
async function(req, res, next) {
|
async function(req, res, next) {
|
||||||
@ -334,234 +312,7 @@ mainRouter
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
.get('/a/random',
|
|
||||||
async function(req, res, next) {
|
|
||||||
var articleCount = await Article.countDocuments();
|
|
||||||
var random = Math.floor(Math.random() * articleCount);
|
|
||||||
var randomArticle = await Article.findOne().skip(random).select('slug');
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify(randomArticle));
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.post('/me/avatar',
|
|
||||||
async function(req, res, next) {
|
|
||||||
if (!req.user) {
|
|
||||||
res.writeHead(401, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: `You must be logged in to set an avatar.`
|
|
||||||
}));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const { upload } = req.files;
|
|
||||||
if (!upload) {
|
|
||||||
res.writeHead(422, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: `You must supply a file.`
|
|
||||||
}));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!/^image\//.test(upload.mimetype)) {
|
|
||||||
res.writeHead(422, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: `Invalid MIME type for the uploaded image.`
|
|
||||||
}));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (upload.truncated) {
|
|
||||||
res.writeHead(422, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: `Received truncated image file. Try again with a smaller file.`
|
|
||||||
}));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const ext = upload.name.match(/(\.[^.]+)$/)[0];
|
|
||||||
const filename = crypto.randomBytes(20).toString('hex') + ext;
|
|
||||||
const url = `/u/${filename}`;
|
|
||||||
await upload.mv('./static' + url);
|
|
||||||
const user = await User.findById(req.user._id);
|
|
||||||
req.user.avatar = user.avatar = filename;
|
|
||||||
await user.save();
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({ filename }));
|
|
||||||
} catch (err) {
|
|
||||||
res.writeHead(500, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: `Failed to upload image: ${err}`
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.get('/rss.xml', async function (req, res) {
|
|
||||||
let year = new Date().getFullYear();
|
|
||||||
let feed = new RSS({
|
|
||||||
title: 'HowFeed.biz Articles',
|
|
||||||
feed_url: 'http://howfeed.biz/rss.xml',
|
|
||||||
site_url: 'http://howfeed.biz/',
|
|
||||||
image_url: 'http://howfeed.biz/logo.png',
|
|
||||||
language: 'en',
|
|
||||||
webMaster: 'webmaster@howfeed.biz',
|
|
||||||
copyright: `${year} FemboyFinancial Holdings Co., Ltd. (USA LLC)`
|
|
||||||
});
|
|
||||||
let articles = await Article.find().populate({
|
|
||||||
path: 'author',
|
|
||||||
select: 'realname avatar'
|
|
||||||
}).populate({
|
|
||||||
path: 'category'
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let article of articles) {
|
|
||||||
feed.item({
|
|
||||||
title: article.title,
|
|
||||||
description: article.html,
|
|
||||||
url: `http://howfeed.biz/a/${article.slug}`,
|
|
||||||
categories: [ article.category.name ],
|
|
||||||
author: article.author.realname,
|
|
||||||
date: article.created_at,
|
|
||||||
enclosure: {
|
|
||||||
url: `http://howfeed.biz/a/${article.image}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/rss+xml'
|
|
||||||
});
|
|
||||||
res.end(feed.xml());
|
|
||||||
})
|
|
||||||
.post('/suggestions', async function (req, res) {
|
|
||||||
let { name, title, message } = req.body;
|
|
||||||
if (!message) {
|
|
||||||
res.writeHead(422, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: 'No message supplied'
|
|
||||||
}));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
name = name || 'Anonymous';
|
|
||||||
title = title || 'Suggestion';
|
|
||||||
try {
|
|
||||||
await mailer.sendMail({
|
|
||||||
from: `"HowFeed Suggestions" <${SMTP_USERNAME}>`,
|
|
||||||
to: SMTP_RECIPIENTS,
|
|
||||||
subject: title,
|
|
||||||
text: `Suggested by ${name}:
|
|
||||||
|
|
||||||
${message}`
|
|
||||||
});
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: 'Your suggestion was delivered.'
|
|
||||||
}));
|
|
||||||
} catch (err) {
|
|
||||||
res.writeHead(500, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
message: err.message
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.get('/api/meet', async function (req, res, next) {
|
|
||||||
if (req.query.token === '1445') {
|
|
||||||
const time = cache.get('lastMeetingTime');
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
LastMeetingTime: time ? time.toJSON() : undefined
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.post('/api/meet', async function (req, res, next) {
|
|
||||||
if (req.body.token === '1445') {
|
|
||||||
const time = new Date();
|
|
||||||
const success = cache.set('lastMeetingTime', time, 3600);
|
|
||||||
if (success) {
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
LastMeetingTime: time.toJSON()
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
res.writeHead(500, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
Error: 'Failed to store meeting time in cache!'
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.get('/api/memo', async function (req, res, next) {
|
|
||||||
if (req.query.token === '1445') {
|
|
||||||
const memos = cache.get('memos') || [];
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify(memos));
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.post('/api/memo', async function (req, res, next) {
|
|
||||||
if (req.body.token === '1445') {
|
|
||||||
const memo = req.body.message;
|
|
||||||
if (!memo) {
|
|
||||||
res.writeHead(400, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
Error: 'You must provide a memo message'
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
const memos = cache.get('memos') || [];
|
|
||||||
memos.push({
|
|
||||||
Time: new Date(),
|
|
||||||
Message: memo
|
|
||||||
});
|
|
||||||
const success = cache.set('memos', memos);
|
|
||||||
if (success) {
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify(memos));
|
|
||||||
} else {
|
|
||||||
res.writeHead(500, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
res.end(JSON.stringify({
|
|
||||||
Error: 'Failed to store memo in cache!'
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(helmet())
|
app.use(helmet())
|
||||||
.use(cors())
|
.use(cors())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user