Additionl of WIP NodeInfo2 support, fix content-type for Actor images
This commit is contained in:
parent
3bdce81bdb
commit
35b7c00d11
|
@ -26,6 +26,7 @@ const mimeTypes = require('mime-types');
|
||||||
const { getJson } = require('../http_util.js');
|
const { getJson } = require('../http_util.js');
|
||||||
const { getISOTimestampString } = require('../database.js');
|
const { getISOTimestampString } = require('../database.js');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
|
const paths = require('path');
|
||||||
|
|
||||||
const ActorCacheTTL = moment.duration(1, 'day');
|
const ActorCacheTTL = moment.duration(1, 'day');
|
||||||
|
|
||||||
|
@ -82,7 +83,8 @@ module.exports = class Actor extends ActivityPubObject {
|
||||||
const addImage = (o, t) => {
|
const addImage = (o, t) => {
|
||||||
const url = userSettings[t];
|
const url = userSettings[t];
|
||||||
if (url) {
|
if (url) {
|
||||||
const mt = mimeTypes.contentType(url);
|
const fn = paths.basename(url);
|
||||||
|
const mt = mimeTypes.contentType(fn);
|
||||||
if (mt) {
|
if (mt) {
|
||||||
o[t] = {
|
o[t] = {
|
||||||
mediaType: mt,
|
mediaType: mt,
|
||||||
|
|
|
@ -137,6 +137,9 @@ function getUserProfileTemplatedBody(
|
||||||
if (isString(v)) {
|
if (isString(v)) {
|
||||||
return v ? encode(v) : '';
|
return v ? encode(v) : '';
|
||||||
} else {
|
} else {
|
||||||
|
if (isNaN(v)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
return v ? v : 0;
|
return v ? v : 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -171,7 +174,7 @@ function getUserProfileTemplatedBody(
|
||||||
ACHIEVEMENT_COUNT: user.getPropertyAsNumber(
|
ACHIEVEMENT_COUNT: user.getPropertyAsNumber(
|
||||||
UserProps.AchievementTotalCount
|
UserProps.AchievementTotalCount
|
||||||
),
|
),
|
||||||
ACHIEVEMENT_POINTS: user.getProperty(
|
ACHIEVEMENT_POINTS: user.getPropertyAsNumber(
|
||||||
UserProps.AchievementTotalPoints
|
UserProps.AchievementTotalPoints
|
||||||
),
|
),
|
||||||
BOARDNAME: Config().general.boardName,
|
BOARDNAME: Config().general.boardName,
|
||||||
|
|
|
@ -306,6 +306,9 @@ module.exports = () => {
|
||||||
systemGeneral: {
|
systemGeneral: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
nodeInfo2: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
resetPassword: {
|
resetPassword: {
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
const WebHandlerModule = require('../../../web_handler_module');
|
||||||
|
const { Errors } = require('../../../enig_error');
|
||||||
|
const EngiAssert = require('../../../enigma_assert');
|
||||||
|
const Config = require('../../../config').get;
|
||||||
|
const packageJson = require('../../../../package.json');
|
||||||
|
const StatLog = require('../../../stat_log');
|
||||||
|
const SysProps = require('../../../system_property');
|
||||||
|
const SysLogKeys = require('../../../system_log');
|
||||||
|
|
||||||
|
// deps
|
||||||
|
const moment = require('moment');
|
||||||
|
const async = require('async');
|
||||||
|
|
||||||
|
exports.moduleInfo = {
|
||||||
|
name: 'NodeInfo2',
|
||||||
|
desc: 'A NodeInfo2 Handler implementing https://github.com/jaywink/nodeinfo2',
|
||||||
|
author: 'NuSkooler',
|
||||||
|
packageName: 'codes.l33t.enigma.web.handler.nodeinfo2',
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getModule = class NodeInfo2WebHadnler extends WebHandlerModule {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
init(webServer, cb) {
|
||||||
|
// we rely on the web server
|
||||||
|
this.webServer = webServer;
|
||||||
|
EngiAssert(webServer, 'NodeInfo2 Web Handler init without webServer');
|
||||||
|
|
||||||
|
this.log = webServer.logger().child({ webHandler: 'NodeInfo2' });
|
||||||
|
|
||||||
|
const domain = this.webServer.getDomain();
|
||||||
|
if (!domain) {
|
||||||
|
return cb(Errors.UnexpectedState('Web server does not have "domain" set'));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.webServer.addRoute({
|
||||||
|
method: 'GET',
|
||||||
|
path: /^\/\.well-known\/x-nodeinfo2$/,
|
||||||
|
handler: this._nodeInfo2Handler.bind(this),
|
||||||
|
});
|
||||||
|
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
_nodeInfo2Handler(req, resp) {
|
||||||
|
this.log.info({ url: req.url }, 'Serving NodeInfo2 request');
|
||||||
|
|
||||||
|
this._getNodeInfo(nodeInfo => {
|
||||||
|
const body = JSON.stringify(nodeInfo);
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Content-Length': body.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
resp.writeHead(200, headers);
|
||||||
|
return resp.end(body);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_getNodeInfo(cb) {
|
||||||
|
// https://github.com/jaywink/nodeinfo2/tree/master/schemas/1.0
|
||||||
|
const config = Config();
|
||||||
|
const nodeInfo = {
|
||||||
|
version: '1.0',
|
||||||
|
server: {
|
||||||
|
baseUrl: this.webServer.baseUrl(),
|
||||||
|
name: config.general.boardName,
|
||||||
|
software: 'ENiGMA½ Bulletin Board Software',
|
||||||
|
version: packageJson.version,
|
||||||
|
},
|
||||||
|
// :TODO: Only list what's enabled
|
||||||
|
protocols: ['telnet', 'ssh', 'gopher', 'nntp', 'ws', 'activitypub'],
|
||||||
|
services: {
|
||||||
|
inbound: [],
|
||||||
|
outbound: [''],
|
||||||
|
},
|
||||||
|
openRegistrations: !config.general.closedSystem,
|
||||||
|
usage: {
|
||||||
|
users: {
|
||||||
|
total: StatLog.getSystemStatNum(SysProps.TotalUserCount) || 1,
|
||||||
|
// others fetched dynamically below
|
||||||
|
},
|
||||||
|
|
||||||
|
// :TODO: pop with local message
|
||||||
|
// select count() from message_meta where meta_name='local_from_user_id';
|
||||||
|
localPosts: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const setActive = (since, name, next) => {
|
||||||
|
const filter = {
|
||||||
|
logName: SysLogKeys.UserLoginHistory,
|
||||||
|
resultType: 'count',
|
||||||
|
dateNewer: moment().subtract(moment.duration(since, 'days')),
|
||||||
|
};
|
||||||
|
StatLog.findSystemLogEntries(filter, (err, count) => {
|
||||||
|
if (!err) {
|
||||||
|
nodeInfo.usage[name] = count;
|
||||||
|
}
|
||||||
|
return next(null);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
async.series(
|
||||||
|
[
|
||||||
|
callback => {
|
||||||
|
return setActive(180, 'activeHalfyear', callback);
|
||||||
|
},
|
||||||
|
callback => {
|
||||||
|
return setActive(30, 'activeMonth', callback);
|
||||||
|
},
|
||||||
|
callback => {
|
||||||
|
return setActive(7, 'activeWeek', callback);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
return cb(nodeInfo);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
|
@ -8,6 +8,7 @@ const SysProps = require('./system_property.js');
|
||||||
const UserProps = require('./user_property');
|
const UserProps = require('./user_property');
|
||||||
const Message = require('./message');
|
const Message = require('./message');
|
||||||
const { getActiveConnections, AllConnections } = require('./client_connections');
|
const { getActiveConnections, AllConnections } = require('./client_connections');
|
||||||
|
const Log = require('./logger').log;
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
@ -349,6 +350,7 @@ class StatLog {
|
||||||
// - resultType: 'obj' | 'count' (default='obj')
|
// - resultType: 'obj' | 'count' (default='obj')
|
||||||
// - limit: Limit returned results
|
// - limit: Limit returned results
|
||||||
// - date: exact date to filter against
|
// - date: exact date to filter against
|
||||||
|
// - dateNewer: Entries newer than this value
|
||||||
// - order: 'timestamp' | 'timestamp_asc' | 'timestamp_desc' | 'random'
|
// - order: 'timestamp' | 'timestamp_asc' | 'timestamp_desc' | 'random'
|
||||||
// (default='timestamp')
|
// (default='timestamp')
|
||||||
//
|
//
|
||||||
|
@ -402,7 +404,9 @@ class StatLog {
|
||||||
this.setNonPersistentSystemStat(SysProps.SystemLoadStats, loadStats);
|
this.setNonPersistentSystemStat(SysProps.SystemLoadStats, loadStats);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
// :TODO: log me
|
if (err) {
|
||||||
|
Log.err({ error: err.message }, 'Error refreshing system stats');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,6 +513,11 @@ class StatLog {
|
||||||
sql += ` AND DATE(timestamp, "localtime") = DATE("${filter.date.format(
|
sql += ` AND DATE(timestamp, "localtime") = DATE("${filter.date.format(
|
||||||
'YYYY-MM-DD'
|
'YYYY-MM-DD'
|
||||||
)}")`;
|
)}")`;
|
||||||
|
} else if (filter.dateNewer) {
|
||||||
|
filter.dateNewer = moment(filter.dateNewer);
|
||||||
|
sql += ` AND DATE(timestamp, "localtime") > DATE("${filter.dateNewer.format(
|
||||||
|
'YYYY-MM-DD'
|
||||||
|
)}")`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('count' !== filter.resultType) {
|
if ('count' !== filter.resultType) {
|
||||||
|
|
Loading…
Reference in New Issue