Compare commits

...

12 Commits

Author SHA1 Message Date
syuilo
626d64631e 11.35.1 2019-11-05 22:24:00 +09:00
syuilo
608fa287c7 Update dependency 2019-11-05 22:21:52 +09:00
syuilo
a35d01ee0f Resolve #5581 2019-11-05 22:20:56 +09:00
syuilo
77c9b90e6d Store nodeinfo per federated instances (#5578)
* Store nodeinfo per federated instances

* Update fetch-nodeinfo.ts

* Update fetch-nodeinfo.ts

* update
2019-11-05 22:14:42 +09:00
syuilo
2f8992f98a Fix bug 2019-11-05 22:11:47 +09:00
tamaina
c8ab0e9d62 Update example.yml (#5572)
Redisの設定にprefix, dbを追加
2019-11-04 20:48:07 +09:00
syuilo
072bc2d9fb Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-11-04 20:44:05 +09:00
syuilo
cc7fec4b9f Improve reaction setting
Fix #5577
2019-11-04 20:44:01 +09:00
MeiMei
570931cff8 Fix #5552 (#5579) 2019-11-03 17:54:37 +09:00
Acid Chicken (硫酸鶏)
88ec15d4c7 Update README.md [AUTOGEN] (#5574) 2019-11-03 04:22:36 +09:00
Acid Chicken (硫酸鶏)
c23c8ae4c3 Update README.md [AUTOGEN] (#5570) 2019-11-02 13:47:24 +09:00
MeiMei
92af4401e2 実行時にpackage.jsonを参照しないように (#5418)
* 実行時にpackage.jsonを参照しないように

* nodeinfo

* move meta.json

* add dummy

* lowercase
2019-11-01 22:34:26 +09:00
28 changed files with 296 additions and 107 deletions

View File

@@ -79,6 +79,8 @@ redis:
host: localhost
port: 6379
#pass: example-pass
#prefix: example-prefix
#db: 1
# ┌─────────────────────────────┐
#───┘ Elasticsearch configuration └─────────────────────────────

View File

@@ -1,6 +1,13 @@
ChangeLog
=========
11.35.1 (2019/11/05)
--------------------
### 🐛Fixes
* リモートのフォローボタンを押してmisskeyインスタンスを入力したとき正しく動作しない問題を修正
* リアクション設定で改行ができない問題を修正
* nodeinfoのmetadataを一般的なものに修正
11.35.0 (2019/11/01)
--------------------
### ✨Improvements

View File

@@ -167,7 +167,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
</tr></table>
**Last updated:** Thu, 31 Oct 2019 06:09:07 UTC
**Last updated:** Sat, 02 Nov 2019 18:09:05 UTC
<!-- PATREON_END -->
:four_leaf_clover: Copyright

View File

@@ -96,7 +96,7 @@ gulp.task('cleanall', gulp.parallel('clean', cb =>
));
gulp.task('build:client:script', () => {
const client = require('./built/client/meta.json');
const client = require('./built/meta.json');
return gulp.src(['./src/client/app/boot.js', './src/client/app/safe.js'])
.pipe(replace('VERSION', JSON.stringify(client.version)))
.pipe(replace('ENV', JSON.stringify(env)))

View File

@@ -312,6 +312,7 @@ common:
sync: "同期"
save: "保存"
saved: "保存しました"
preview: "プレビュー"
home-profile: "ホームのプロファイル"
deck-profile: "デッキのプロファイル"
room: "ルーム"

View File

@@ -0,0 +1,29 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class nodeinfo1572760203493 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "system"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "softwareName" character varying(64) DEFAULT null`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "softwareVersion" character varying(64) DEFAULT null`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "openRegistrations" boolean DEFAULT null`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "name" character varying(256) DEFAULT null`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "description" character varying(4096) DEFAULT null`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "maintainerName" character varying(128) DEFAULT null`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "maintainerEmail" character varying(256) DEFAULT null`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "infoUpdatedAt" TIMESTAMP WITH TIME ZONE`, undefined);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "infoUpdatedAt"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "maintainerEmail"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "maintainerName"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "description"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "name"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "openRegistrations"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "softwareVersion"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "softwareName"`, undefined);
await queryRunner.query(`ALTER TABLE "instance" ADD "system" character varying(64)`, undefined);
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "11.35.0",
"version": "11.35.1",
"codename": "daybreak",
"repository": {
"type": "git",
@@ -103,7 +103,7 @@
"@typescript-eslint/parser": "2.3.3",
"agentkeepalive": "4.1.0",
"animejs": "3.1.0",
"apexcharts": "3.10.0",
"apexcharts": "3.10.1",
"autobind-decorator": "2.4.0",
"autosize": "4.0.2",
"autwh": "0.1.0",

View File

@@ -1,8 +1,8 @@
import * as program from 'commander';
import * as pkg from '../package.json';
import config from './config';
program
.version(pkg.version)
.version(config.version)
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
.option('--disable-clustering', 'Disable clustering')
.option('--only-server', 'Run server only (without job queue processing)')

View File

@@ -8,7 +8,6 @@ import Logger from '../services/logger';
import loadConfig from '../config/load';
import { Config } from '../config/types';
import { lessThan } from '../prelude/array';
import * as pkg from '../../package.json';
import { program } from '../argv';
import { showMachineInfo } from '../misc/show-machine-info';
import { initDb } from '../db/postgre';
@@ -16,10 +15,10 @@ import { initDb } from '../db/postgre';
const logger = new Logger('core', 'cyan');
const bootLogger = logger.createSubLogger('boot', 'magenta', false);
function greet() {
function greet(config: Config) {
if (!program.quiet) {
//#region Misskey logo
const v = `v${pkg.version}`;
const v = `v${config.version}`;
console.log(' _____ _ _ ');
console.log(' | |_|___ ___| |_ ___ _ _ ');
console.log(' | | | | |_ -|_ -| \'_| -_| | |');
@@ -35,21 +34,21 @@ function greet() {
}
bootLogger.info('Welcome to Misskey!');
bootLogger.info(`Misskey v${pkg.version}`, null, true);
bootLogger.info(`Misskey v${config.version}`, null, true);
}
/**
* Init master process
*/
export async function masterMain() {
greet();
let config!: Config;
try {
// initialize app
config = await init();
greet(config);
if (config.port == null || Number.isNaN(config.port)) {
bootLogger.error('The port is not configured. Please configure port.', null, true);
process.exit(1);

View File

@@ -145,13 +145,18 @@ export default (opts: Opts = {}) => ({
this.blur();
const w = this.$root.new(MkReactionPicker, {
source: this.$refs.reactButton,
note: this.appearNote,
showFocus: viaKeyboard,
animation: !viaKeyboard
}).$once('closed', this.focus);
this.$once('hook:beforeDestroy', () => {
w.close();
});
w.$once('chosen', reaction => {
this.$root.api('notes/reactions/create', {
noteId: this.appearNote.id,
reaction: reaction
}).then(() => {
w.close();
});
});
w.$once('closed', this.focus);
},
reactDirectly(reaction) {

View File

@@ -4,7 +4,7 @@
<div class="popover" :class="{ isMobile: $root.isMobile }" ref="popover">
<p v-if="!$root.isMobile">{{ title }}</p>
<div class="buttons" ref="buttons" :class="{ showFocus }">
<button v-for="(reaction, i) in $store.state.settings.reactions" :key="reaction" @click="react(reaction)" @mouseover="onMouseover" @mouseout="onMouseout" :tabindex="i + 1" :title="/^[a-z]+$/.test(reaction) ? $t('@.reactions.' + reaction) : reaction" v-particle><mk-reaction-icon :reaction="reaction"/></button>
<button v-for="(reaction, i) in rs" :key="reaction" @click="react(reaction)" @mouseover="onMouseover" @mouseout="onMouseout" :tabindex="i + 1" :title="/^[a-z]+$/.test(reaction) ? $t('@.reactions.' + reaction) : reaction" v-particle><mk-reaction-icon :reaction="reaction"/></button>
</div>
<div v-if="enableEmojiReaction" class="text">
<input v-model="text" :placeholder="$t('input-reaction-placeholder')" @keyup.enter="reactText" @input="tryReactText" v-autocomplete="{ model: 'text' }">
@@ -22,16 +22,11 @@ import { emojiRegex } from '../../../../../misc/emoji-regex';
export default Vue.extend({
i18n: i18n('common/views/components/reaction-picker.vue'),
props: {
note: {
type: Object,
required: true
},
source: {
required: true
},
cb: {
reactions: {
required: false
},
@@ -50,6 +45,7 @@ export default Vue.extend({
data() {
return {
rs: this.reactions || this.$store.state.settings.reactions,
title: this.$t('choose-reaction'),
text: null,
enableEmojiReaction: false,
@@ -134,14 +130,7 @@ export default Vue.extend({
methods: {
react(reaction) {
this.$root.api('notes/reactions/create', {
noteId: this.note.id,
reaction: reaction
}).then(() => {
if (this.cb) this.cb();
this.$emit('closed');
this.destroyDom();
});
this.$emit('chosen', reaction);
},
reactText() {

View File

@@ -113,6 +113,10 @@
<ui-textarea v-model="reactions">
{{ $t('@._settings.reactions') }}<template #desc>{{ $t('@._settings.reactions-description') }}</template>
</ui-textarea>
<ui-horizon-group>
<ui-button @click="save('reactions', reactions.trim().split('\n'))" primary><fa :icon="faSave"/> {{ $t('@._settings.save') }}</ui-button>
<ui-button @click="previewReaction()" ref="reactionsPreviewButton"><fa :icon="faEye"/> {{ $t('@._settings.preview') }}</ui-button>
</ui-horizon-group>
</section>
<section>
@@ -311,11 +315,12 @@ import XApi from './api.vue';
import XLanguage from './language.vue';
import XAppType from './app-type.vue';
import XNotification from './notification.vue';
import MkReactionPicker from '../reaction-picker.vue';
import { url, version } from '../../../../config';
import checkForUpdate from '../../../scripts/check-for-update';
import { formatTimeString } from '../../../../../../misc/format-time-string';
import { faSave } from '@fortawesome/free-regular-svg-icons';
import { faSave, faEye } from '@fortawesome/free-regular-svg-icons';
export default Vue.extend({
i18n: i18n(),
@@ -346,11 +351,12 @@ export default Vue.extend({
return {
meta: null,
version,
reactions: this.$store.state.settings.reactions.join('\n'),
webSearchEngine: this.$store.state.settings.webSearchEngine,
pastedFileName : this.$store.state.settings.pastedFileName,
latestVersion: undefined,
checkingForUpdate: false,
faSave
faSave, faEye
};
},
computed: {
@@ -414,11 +420,6 @@ export default Vue.extend({
set(value) { this.$store.dispatch('settings/set', { key: 'disableViaMobile', value }); }
},
reactions: {
get() { return this.$store.state.settings.reactions.join('\n'); },
set(value: string) { this.$store.dispatch('settings/set', { key: 'reactions', value: value.trim().split('\n') }); }
},
useShadow: {
get() { return this.$store.state.device.useShadow; },
set(value) { this.$store.commit('device/set', { key: 'useShadow', value }); }
@@ -655,6 +656,16 @@ export default Vue.extend({
pastedFileNamePreview() {
return `${formatTimeString(new Date(), this.pastedFileName).replace(/{{number}}/g, `1`)}.png`
},
previewReaction() {
const picker = this.$root.new(MkReactionPicker, {
source: this.$refs.reactionsPreviewButton.$el,
reactions: this.reactions.trim().split('\n'),
showFocus: false,
});
picker.$once('chosen', reaction => {
picker.close();
});
}
}
});
</script>

View File

@@ -72,11 +72,40 @@ export default Vue.extend({
const acct = new URL(location.href).searchParams.get('acct');
this.fetching = true;
Progress.start();
this.$root.api('users/show', parseAcct(acct)).then(user => {
this.user = user;
this.fetching = false;
Progress.done();
});
if (acct.match(/^https?:/)) {
this.$root.api('ap/show', {
uri: acct
}).then((res: { type: string, object: any }) => {
if (res.type !== 'User') {
this.$root.dialog({
type: 'error',
text: 'acct is not an user'
});
} else {
this.user = res.object;
}
}).catch((e: any) => {
this.$root.dialog({
type: 'error',
text: e.message
});
}).finally(() => {
this.fetching = false;
Progress.done();
});
} else {
this.$root.api('users/show', parseAcct(acct)).then((user: any) => {
this.user = user;
}).catch((e: any) => {
this.$root.dialog({
type: 'error',
text: e.message
});
}).finally(() => {
this.fetching = false;
Progress.done();
});
}
},
async onClick() {

View File

@@ -5,7 +5,7 @@
import * as fs from 'fs';
import * as yaml from 'js-yaml';
import { Source, Mixin } from './types';
import * as pkg from '../../package.json';
import * as meta from '../meta.json';
/**
* Path of configuration directory
@@ -30,6 +30,7 @@ export default function load() {
config.port = config.port || parseInt(process.env.PORT || '', 10);
mixin.version = meta.version;
mixin.host = url.host;
mixin.hostname = url.hostname;
mixin.scheme = url.protocol.replace(/:$/, '');
@@ -38,7 +39,7 @@ export default function load() {
mixin.apiUrl = `${mixin.scheme}://${mixin.host}/api`;
mixin.authUrl = `${mixin.scheme}://${mixin.host}/auth`;
mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`;
mixin.userAgent = `Misskey/${pkg.version} (${config.url})`;
mixin.userAgent = `Misskey/${meta.version} (${config.url})`;
if (config.autoAdmin == null) config.autoAdmin = false;

View File

@@ -58,6 +58,7 @@ export type Source = {
* Misskeyが自動的に(ユーザーが設定した情報から推論して)設定する情報
*/
export type Mixin = {
version: string;
host: string;
hostname: string;
scheme: string;

3
src/meta.json Normal file
View File

@@ -0,0 +1,3 @@
{
"version": "unknown"
}

View File

@@ -20,3 +20,7 @@ const lock: (key: string, timeout?: number) => Promise<() => void>
export function getApLock(uri: string, timeout = 30 * 1000) {
return lock(`ap-object:${uri}`, timeout);
}
export function getNodeinfoLock(host: string, timeout = 30 * 1000) {
return lock(`nodeinfo:${host}`, timeout);
}

View File

@@ -25,15 +25,6 @@ export class Instance {
})
public host: string;
/**
* インスタンスのシステム (MastodonとかMisskeyとかPleromaとか)
*/
@Column('varchar', {
length: 64, nullable: true,
comment: 'The system of the Instance.'
})
public system: string | null;
/**
* インスタンスのユーザー数
*/
@@ -129,4 +120,45 @@ export class Instance {
default: false
})
public isMarkedAsClosed: boolean;
@Column('varchar', {
length: 64, nullable: true, default: null,
comment: 'The software of the Instance.'
})
public softwareName: string | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public softwareVersion: string | null;
@Column('boolean', {
nullable: true, default: null,
})
public openRegistrations: boolean | null;
@Column('varchar', {
length: 256, nullable: true, default: null,
})
public name: string | null;
@Column('varchar', {
length: 4096, nullable: true, default: null,
})
public description: string | null;
@Column('varchar', {
length: 128, nullable: true, default: null,
})
public maintainerName: string | null;
@Column('varchar', {
length: 256, nullable: true, default: null,
})
public maintainerEmail: string | null;
@Column('timestamp with time zone', {
nullable: true,
})
public infoUpdatedAt: Date | null;
}

View File

@@ -4,6 +4,7 @@ import { registerOrFetchInstanceDoc } from '../../services/register-or-fetch-ins
import Logger from '../../services/logger';
import { Instances } from '../../models';
import { instanceChart } from '../../services/chart';
import { fetchNodeinfo } from '../../services/fetch-nodeinfo';
const logger = new Logger('deliver');
@@ -28,6 +29,8 @@ export default async (job: Bull.Job) => {
isNotResponding: false
});
fetchNodeinfo(i);
instanceChart.requestSent(i.host, true);
});

View File

@@ -13,6 +13,7 @@ import { fetchMeta } from '../../misc/fetch-meta';
import { toPuny } from '../../misc/convert-host';
import { validActor } from '../../remote/activitypub/type';
import { ensure } from '../../prelude/ensure';
import { fetchNodeinfo } from '../../services/fetch-nodeinfo';
const logger = new Logger('inbox');
@@ -105,6 +106,8 @@ export default async (job: Bull.Job): Promise<void> => {
isNotResponding: false
});
fetchNodeinfo(i);
instanceChart.requestReceived(i.host);
});

View File

@@ -27,6 +27,7 @@ import { validActor } from '../../../remote/activitypub/type';
import { getConnection } from 'typeorm';
import { ensure } from '../../../prelude/ensure';
import { toArray } from '../../../prelude/array';
import { fetchNodeinfo } from '../../../services/fetch-nodeinfo';
const logger = apLogger;
@@ -191,6 +192,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
registerOrFetchInstanceDoc(host).then(i => {
Instances.increment({ id: i.id }, 'usersCount', 1);
instanceChart.newUser(i.host);
fetchNodeinfo(i);
});
usersChart.update(user!, true);

View File

@@ -3,7 +3,6 @@ import * as os from 'os';
import config from '../../../config';
import define from '../define';
import { fetchMeta } from '../../../misc/fetch-meta';
import * as pkg from '../../../../package.json';
import { Emojis } from '../../../models';
import { getConnection } from 'typeorm';
import redis from '../../../db/redis';
@@ -36,7 +35,7 @@ export const meta = {
type: 'string' as const,
optional: false as const, nullable: false as const,
description: 'The version of Misskey of this instance.',
example: pkg.version
example: config.version
},
name: {
type: 'string' as const,
@@ -114,7 +113,7 @@ export default define(meta, async (ps, me) => {
maintainerName: instance.maintainerName,
maintainerEmail: instance.maintainerEmail,
version: pkg.version,
version: config.version,
name: instance.name,
uri: config.url,

View File

@@ -2,7 +2,6 @@ import * as Router from '@koa/router';
import config from '../config';
import { fetchMeta } from '../misc/fetch-meta';
// import User from '../models/user';
import { name as softwareName, version, repository } from '../../package.json';
// import Note from '../models/note';
const router = new Router();
@@ -20,27 +19,7 @@ export const links = [/* (awaiting release) {
const nodeinfo2 = async () => {
const [
{
name,
description,
maintainerName,
maintainerEmail,
langs,
ToSUrl,
repositoryUrl,
feedbackUrl,
announcements,
disableRegistration,
disableLocalTimeline,
disableGlobalTimeline,
enableRecaptcha,
maxNoteTextLength,
enableTwitterIntegration,
enableGithubIntegration,
enableDiscordIntegration,
enableEmail,
enableServiceWorker
},
meta,
// total,
// activeHalfyear,
// activeMonth,
@@ -57,43 +36,43 @@ const nodeinfo2 = async () => {
return {
software: {
name: softwareName,
version,
repository: repository.url
name: 'misskey',
version: config.version,
repository: meta.repositoryUrl,
},
protocols: ['activitypub'],
services: {
inbound: [] as string[],
outbound: ['atom1.0', 'rss2.0']
},
openRegistrations: !disableRegistration,
openRegistrations: !meta.disableRegistration,
usage: {
users: {} // { total, activeHalfyear, activeMonth },
// localPosts,
// localComments
},
metadata: {
name,
description,
nodeName: meta.name,
nodeDescription: meta.description,
maintainer: {
name: maintainerName,
email: maintainerEmail
name: meta.maintainerName,
email: meta.maintainerEmail
},
langs,
ToSUrl,
repositoryUrl,
feedbackUrl,
announcements,
disableRegistration,
disableLocalTimeline,
disableGlobalTimeline,
enableRecaptcha,
maxNoteTextLength,
enableTwitterIntegration,
enableGithubIntegration,
enableDiscordIntegration,
enableEmail,
enableServiceWorker
langs: meta.langs,
ToSUrl: meta.ToSUrl,
repositoryUrl: meta.repositoryUrl,
feedbackUrl: meta.feedbackUrl,
announcements: meta.announcements,
disableRegistration: meta.disableRegistration,
disableLocalTimeline: meta.disableLocalTimeline,
disableGlobalTimeline: meta.disableGlobalTimeline,
enableRecaptcha: meta.enableRecaptcha,
maxNoteTextLength: meta.maxNoteTextLength,
enableTwitterIntegration: meta.enableTwitterIntegration,
enableGithubIntegration: meta.enableGithubIntegration,
enableDiscordIntegration: meta.enableDiscordIntegration,
enableEmail: meta.enableEmail,
enableServiceWorker: meta.enableServiceWorker
}
};
};

View File

@@ -13,7 +13,6 @@ import * as views from 'koa-views';
import docs from './docs';
import packFeed from './feed';
import { fetchMeta } from '../../misc/fetch-meta';
import * as pkg from '../../../package.json';
import { genOpenapiSpec } from '../api/openapi/gen-spec';
import config from '../../config';
import { Users, Notes, Emojis, UserProfiles, Pages } from '../../models';
@@ -257,7 +256,7 @@ router.get('/info', async ctx => {
where: { host: null }
});
await ctx.render('info', {
version: pkg.version,
version: config.version,
machine: os.hostname(),
os: os.platform(),
node: process.version,

View File

@@ -69,7 +69,8 @@ function postProcess(file: DriveFile, isExpired = false) {
isLink: true,
url: file.uri,
thumbnailUrl: file.uri,
webpublicUrl: file.uri
webpublicUrl: file.uri,
size: 0,
});
} else {
DriveFiles.delete(file.id);

View File

@@ -0,0 +1,91 @@
import * as request from 'request-promise-native';
import { Instance } from '../models/entities/instance';
import { Instances } from '../models';
import config from '../config';
import { getNodeinfoLock } from '../misc/app-lock';
import Logger from '../services/logger';
export const logger = new Logger('nodeinfo', 'cyan');
export async function fetchNodeinfo(instance: Instance) {
const unlock = await getNodeinfoLock(instance.host);
const _instance = await Instances.findOne({ host: instance.host });
const now = Date.now();
if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < 1000 * 60 * 60 * 24)) {
unlock();
return;
}
logger.info(`Fetching nodeinfo of ${instance.host} ...`);
try {
const wellknown = await request({
url: 'https://' + instance.host + '/.well-known/nodeinfo',
proxy: config.proxy,
timeout: 1000 * 10,
forever: true,
headers: {
'User-Agent': config.userAgent,
Accept: 'application/json, */*'
},
json: true
}).catch(e => {
if (e.statusCode === 404) {
throw 'No nodeinfo provided';
} else {
throw e.statusCode || e.message;
}
});
if (wellknown.links == null || !Array.isArray(wellknown.links)) {
throw 'No wellknown links';
}
const links = wellknown.links as any[];
const lnik1_0 = links.find(link => link.rel === 'http://nodeinfo.diaspora.software/ns/schema/1.0');
const lnik2_0 = links.find(link => link.rel === 'http://nodeinfo.diaspora.software/ns/schema/2.0');
const lnik2_1 = links.find(link => link.rel === 'http://nodeinfo.diaspora.software/ns/schema/2.1');
const link = lnik2_1 || lnik2_0 || lnik1_0;
if (link == null) {
throw 'No nodeinfo link provided';
}
const info = await request({
url: link.href,
proxy: config.proxy,
timeout: 1000 * 10,
forever: true,
headers: {
'User-Agent': config.userAgent,
Accept: 'application/json, */*'
},
json: true
}).catch(e => {
throw e.statusCode || e.message;
});
await Instances.update(instance.id, {
infoUpdatedAt: new Date(),
softwareName: info.software.name.toLowerCase(),
softwareVersion: info.software.version,
openRegistrations: info.openRegistrations,
name: info.metadata ? (info.metadata.nodeName || info.metadata.name || null) : null,
description: info.metadata ? (info.metadata.nodeDescription || info.metadata.description || null) : null,
maintainerName: info.metadata ? info.metadata.maintainer ? (info.metadata.maintainer.name || null) : null : null,
maintainerEmail: info.metadata ? info.metadata.maintainer ? (info.metadata.maintainer.email || null) : null : null,
});
logger.succ(`Successfuly fetched nodeinfo of ${instance.host}`);
} catch (e) {
logger.error(`Failed to fetch nodeinfo of ${instance.host}: ${e}`);
await Instances.update(instance.id, {
infoUpdatedAt: new Date(),
});
} finally {
unlock();
}
}

View File

@@ -15,7 +15,6 @@ export async function registerOrFetchInstanceDoc(host: string): Promise<Instance
host,
caughtAt: new Date(),
lastCommunicatedAt: new Date(),
system: null // TODO
});
federationChart.update(true);

View File

@@ -130,7 +130,7 @@ module.exports = {
'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development')
}),
new WebpackOnBuildPlugin((stats: any) => {
fs.writeFileSync('./built/client/meta.json', JSON.stringify({ version: meta.version }), 'utf-8');
fs.writeFileSync('./built/meta.json', JSON.stringify({ version: meta.version }), 'utf-8');
fs.mkdirSync('./built/client/assets/locales', { recursive: true });