feat: license violation protection (#13285)
* spec(frontend): aboutページにリポジトリ・フィードバックのURLを表示させる Cherry-picked from MisskeyIO#441 Cherry-picked from MisskeyIO#438 * feat: license violation protection * build: fix typo * build: fix typo * fix: farewell to the static type land * fix: key typo * fix: import typo * fix: properly interpret `prominently` * docs: add disclaimer * docs: update CHANGELOG * chore: add gap --------- Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
parent
fa243276c5
commit
acba96c1d3
@ -2,6 +2,63 @@
|
||||
# Misskey configuration
|
||||
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
# ┌──────────────────────────────┐
|
||||
#───┘ a boring but important thing └────────────────────────────
|
||||
|
||||
#
|
||||
# First of all, let me tell you a story that may possibly be
|
||||
# boring to you and possibly important to you.
|
||||
#
|
||||
# Misskey is licensed under the AGPLv3 license. This license is
|
||||
# known to be often misunderstood. Please read the following
|
||||
# instructions carefully and select the appropriate option so
|
||||
# that you do not negligently cause a license violation.
|
||||
#
|
||||
|
||||
# --------
|
||||
# Option 1: If you host Misskey AS-IS (without any changes to
|
||||
# the source code. forks are not included).
|
||||
#
|
||||
# Step 1: Congratulations! You don't need to do anything.
|
||||
|
||||
# --------
|
||||
# Option 2: If you have made changes to the source code (forks
|
||||
# are included) and publish a Git repository of source
|
||||
# code. There should be no access restrictions on
|
||||
# this repository. Strictly speaking, it doesn't have
|
||||
# to be a Git repository, but you'll probably use Git!
|
||||
#
|
||||
# Step 1: Build and run the Misskey server first.
|
||||
# Step 2: Open <https://your.misskey.example/admin/settings> in
|
||||
# your browser with the administrator account.
|
||||
# Step 3: Enter the URL of your Git repository in the
|
||||
# "Repository URL" field.
|
||||
|
||||
# --------
|
||||
# Option 3: If neither of the above applies to you.
|
||||
# (In this case, the source code should be published
|
||||
# on the Misskey interface. IT IS NOT ENOUGH TO
|
||||
# DISCLOSE THE SOURCE CODE WEHN A USER REQUESTS IT BY
|
||||
# E-MAIL OR OTHER MEANS. If you are not satisfied
|
||||
# with this, it is recommended that you read the
|
||||
# license again carefully. Anyway, enabling this
|
||||
# option will automatically generate and publish a
|
||||
# tarball at build time, protecting you from
|
||||
# inadvertent license violations. (There is no legal
|
||||
# guarantee, of course.) The tarball will generated
|
||||
# from the root directory of your codebase. So it is
|
||||
# also recommended to check <built/tarball> directory
|
||||
# once after building and before activating the server
|
||||
# to avoid ACCIDENTAL LEAKING OF SENSITIVE INFORMATION.
|
||||
# To prevent certain files from being included in the
|
||||
# tarball, add a glob pattern after line 15 in
|
||||
# <scripts/tarball.mjs>. DO NOT FORGET TO BUILD AFTER
|
||||
# ENABLING THIS OPTION!)
|
||||
#
|
||||
# Step 1: Uncomment the following line.
|
||||
#
|
||||
# publishTarballInsteadOfProvideRepositoryUrl: true
|
||||
|
||||
# ┌─────┐
|
||||
#───┘ URL └─────────────────────────────────────────────────────
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
### General
|
||||
- Feat: [mCaptcha](https://github.com/mCaptcha/mCaptcha)のサポートを追加
|
||||
- Feat: Add support for TrueMail
|
||||
- Feat: AGPLv3ライセンスに誤って違反するのを防止する機能を追加
|
||||
- 管理者がrepositoryUrlを変更したり、またはソースコードを直接頒布することを選択できるようになります
|
||||
- 本体のソースコードに改変を加えた際に、ライセンスに基づく適切な案内を表示します
|
||||
- Enhance: モデレーターはすべてのユーザーのリアクション一覧を見られるように
|
||||
- Fix: リストライムラインの「リノートを表示」が正しく機能しない問題を修正
|
||||
- Fix: リモートユーザーのリアクション一覧がすべて見えてしまうのを修正
|
||||
|
40
locales/index.d.ts
vendored
40
locales/index.d.ts
vendored
@ -3980,6 +3980,10 @@ export interface Locale extends ILocale {
|
||||
* Misskeyは{host}が使用している無料のソフトウェアです。これからも開発を続けられるように、ぜひ寄付をお願いします!
|
||||
*/
|
||||
"pleaseDonate": ParameterizedString<"host">;
|
||||
/**
|
||||
* 対応するソースコードは{anchor}から利用可能です。
|
||||
*/
|
||||
"correspondingSourceIsAvailable": ParameterizedString<"anchor">;
|
||||
/**
|
||||
* ロール
|
||||
*/
|
||||
@ -4684,6 +4688,34 @@ export interface Locale extends ILocale {
|
||||
* 外部サービス
|
||||
*/
|
||||
"externalServices": string;
|
||||
/**
|
||||
* ソースコード
|
||||
*/
|
||||
"sourceCode": string;
|
||||
/**
|
||||
* ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。
|
||||
*/
|
||||
"sourceCodeIsNotYetProvided": string;
|
||||
/**
|
||||
* リポジトリURL
|
||||
*/
|
||||
"repositoryUrl": string;
|
||||
/**
|
||||
* ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Misskeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/misskey-dev/misskey と記入します。
|
||||
*/
|
||||
"repositoryUrlDescription": string;
|
||||
/**
|
||||
* リポジトリを公開していない場合、代わりにtarballを提供する必要があります。詳細は.config/example.ymlを参照してください。
|
||||
*/
|
||||
"repositoryUrlOrTarballRequired": string;
|
||||
/**
|
||||
* フィードバック
|
||||
*/
|
||||
"feedback": string;
|
||||
/**
|
||||
* フィードバックURL
|
||||
*/
|
||||
"feedbackUrl": string;
|
||||
/**
|
||||
* 運営者情報
|
||||
*/
|
||||
@ -6813,6 +6845,14 @@ export interface Locale extends ILocale {
|
||||
* ソースコード
|
||||
*/
|
||||
"source": string;
|
||||
/**
|
||||
* オリジナル
|
||||
*/
|
||||
"original": string;
|
||||
/**
|
||||
* {name}はオリジナルのMisskeyを改変したバージョンを使用しています。
|
||||
*/
|
||||
"thisIsModifiedVersion": ParameterizedString<"name">;
|
||||
/**
|
||||
* Misskeyを翻訳
|
||||
*/
|
||||
|
@ -991,6 +991,7 @@ neverShow: "今後表示しない"
|
||||
remindMeLater: "また後で"
|
||||
didYouLikeMisskey: "Misskeyを気に入っていただけましたか?"
|
||||
pleaseDonate: "Misskeyは{host}が使用している無料のソフトウェアです。これからも開発を続けられるように、ぜひ寄付をお願いします!"
|
||||
correspondingSourceIsAvailable: "対応するソースコードは{anchor}から利用可能です。"
|
||||
roles: "ロール"
|
||||
role: "ロール"
|
||||
noRole: "ロールはありません"
|
||||
@ -1167,6 +1168,13 @@ hideRepliesToOthersInTimelineAll: "TLに現在フォロー中の人全員の返
|
||||
confirmShowRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めるようにしますか?"
|
||||
confirmHideRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めないようにしますか?"
|
||||
externalServices: "外部サービス"
|
||||
sourceCode: "ソースコード"
|
||||
sourceCodeIsNotYetProvided: "ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。"
|
||||
repositoryUrl: "リポジトリURL"
|
||||
repositoryUrlDescription: "ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Misskeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/misskey-dev/misskey と記入します。"
|
||||
repositoryUrlOrTarballRequired: "リポジトリを公開していない場合、代わりにtarballを提供する必要があります。詳細は.config/example.ymlを参照してください。"
|
||||
feedback: "フィードバック"
|
||||
feedbackUrl: "フィードバックURL"
|
||||
impressum: "運営者情報"
|
||||
impressumUrl: "運営者情報URL"
|
||||
impressumDescription: "ドイツなどの一部の国と地域では表示が義務付けられています(Impressum)。"
|
||||
@ -1778,6 +1786,8 @@ _aboutMisskey:
|
||||
contributors: "コントリビューター"
|
||||
allContributors: "全てのコントリビューター"
|
||||
source: "ソースコード"
|
||||
original: "オリジナル"
|
||||
thisIsModifiedVersion: "{name}はオリジナルのMisskeyを改変したバージョンを使用しています。"
|
||||
translation: "Misskeyを翻訳"
|
||||
donate: "Misskeyに寄付"
|
||||
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
|
||||
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class MakeRepositoryUrlNullable1707808106310 {
|
||||
name = 'MakeRepositoryUrlNullable1707808106310'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" DROP NOT NULL`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET NOT NULL`);
|
||||
}
|
||||
}
|
@ -57,6 +57,8 @@ type Source = {
|
||||
scope?: 'local' | 'global' | string[];
|
||||
};
|
||||
|
||||
publishTarballInsteadOfProvideRepositoryUrl?: boolean;
|
||||
|
||||
proxy?: string;
|
||||
proxySmtp?: string;
|
||||
proxyBypassHosts?: string[];
|
||||
@ -145,6 +147,7 @@ export type Config = {
|
||||
signToActivityPubGet: boolean | undefined;
|
||||
|
||||
version: string;
|
||||
publishTarballInsteadOfProvideRepositoryUrl: boolean;
|
||||
host: string;
|
||||
hostname: string;
|
||||
scheme: string;
|
||||
@ -209,6 +212,7 @@ export function loadConfig(): Config {
|
||||
|
||||
return {
|
||||
version,
|
||||
publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl,
|
||||
url: url.origin,
|
||||
port: config.port ?? parseInt(process.env.PORT ?? '', 10),
|
||||
socket: config.socket,
|
||||
|
@ -357,9 +357,9 @@ export class MiMeta {
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
default: 'https://github.com/misskey-dev/misskey',
|
||||
nullable: false,
|
||||
nullable: true,
|
||||
})
|
||||
public repositoryUrl: string;
|
||||
public repositoryUrl: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
|
@ -429,7 +429,7 @@ export const meta = {
|
||||
},
|
||||
repositoryUrl: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
summalyProxy: {
|
||||
type: 'string',
|
||||
|
@ -104,8 +104,8 @@ export const paramDef = {
|
||||
swPublicKey: { type: 'string', nullable: true },
|
||||
swPrivateKey: { type: 'string', nullable: true },
|
||||
tosUrl: { type: 'string', nullable: true },
|
||||
repositoryUrl: { type: 'string' },
|
||||
feedbackUrl: { type: 'string' },
|
||||
repositoryUrl: { type: 'string', nullable: true },
|
||||
feedbackUrl: { type: 'string', nullable: true },
|
||||
impressumUrl: { type: 'string', nullable: true },
|
||||
privacyPolicyUrl: { type: 'string', nullable: true },
|
||||
useObjectStorage: { type: 'boolean' },
|
||||
@ -402,7 +402,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
}
|
||||
|
||||
if (ps.repositoryUrl !== undefined) {
|
||||
set.repositoryUrl = ps.repositoryUrl;
|
||||
set.repositoryUrl = URL.canParse(ps.repositoryUrl!) ? ps.repositoryUrl : null;
|
||||
}
|
||||
|
||||
if (ps.feedbackUrl !== undefined) {
|
||||
|
@ -37,6 +37,10 @@ export const meta = {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
providesTarball: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
@ -69,12 +73,12 @@ export const meta = {
|
||||
},
|
||||
repositoryUrl: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
optional: false, nullable: true,
|
||||
default: 'https://github.com/misskey-dev/misskey',
|
||||
},
|
||||
feedbackUrl: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
optional: false, nullable: true,
|
||||
default: 'https://github.com/misskey-dev/misskey/issues/new',
|
||||
},
|
||||
defaultDarkTheme: {
|
||||
@ -352,6 +356,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
maintainerEmail: instance.maintainerEmail,
|
||||
|
||||
version: this.config.version,
|
||||
providesTarball: this.config.publishTarballInsteadOfProvideRepositoryUrl,
|
||||
|
||||
name: instance.name,
|
||||
shortName: instance.shortName,
|
||||
|
@ -11,6 +11,7 @@ import { alert, confirm, popup, post, toast } from '@/os.js';
|
||||
import { useStream } from '@/stream.js';
|
||||
import * as sound from '@/scripts/sound.js';
|
||||
import { $i, signout, updateAccount } from '@/account.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { ColdDeviceStorage, defaultStore } from '@/store.js';
|
||||
import { makeHotkey } from '@/scripts/hotkey.js';
|
||||
import { reactionPicker } from '@/scripts/reaction-picker.js';
|
||||
@ -234,6 +235,13 @@ export async function mainBoot() {
|
||||
}
|
||||
}
|
||||
|
||||
fetchInstance().then(() => {
|
||||
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
||||
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
|
||||
popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed');
|
||||
}
|
||||
});
|
||||
|
||||
if ('Notification' in window) {
|
||||
// 許可を得ていなかったらリクエスト
|
||||
if (Notification.permission === 'default') {
|
||||
|
112
packages/frontend/src/components/MkSourceCodeAvailablePopup.vue
Normal file
112
packages/frontend/src/components/MkSourceCodeAvailablePopup.vue
Normal file
@ -0,0 +1,112 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="_panel _shadow" :class="$style.root">
|
||||
<div :class="$style.icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-open-source" width="40" height="40" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M12 3a9 9 0 0 1 3.618 17.243l-2.193 -5.602a3 3 0 1 0 -2.849 0l-2.193 5.603a9 9 0 0 1 3.617 -17.244z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div :class="$style.main">
|
||||
<div :class="$style.title">
|
||||
<I18n :src="i18n.ts.aboutX" tag="span">
|
||||
<template #x>
|
||||
{{ instance.name ?? host }}
|
||||
</template>
|
||||
</I18n>
|
||||
</div>
|
||||
<div :class="$style.text">
|
||||
<I18n :src="i18n.ts._aboutMisskey.thisIsModifiedVersion" tag="span">
|
||||
<template #name>
|
||||
{{ instance.name ?? host }}
|
||||
</template>
|
||||
</I18n>
|
||||
<I18n :src="i18n.ts.correspondingSourceIsAvailable" tag="span">
|
||||
<template #anchor>
|
||||
<MkA to="/about-misskey" class="_link">{{ i18n.ts.aboutMisskey }}</MkA>
|
||||
</template>
|
||||
</I18n>
|
||||
</div>
|
||||
<div class="_buttons">
|
||||
<MkButton @click="close">{{ i18n.ts.gotIt }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
<button class="_button" :class="$style.close" @click="close"><i class="ti ti-x"></i></button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { host } from '@/config.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const zIndex = os.claimZIndex('low');
|
||||
|
||||
function close() {
|
||||
miLocalStorage.setItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read', 'true');
|
||||
emit('closed');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
position: fixed;
|
||||
z-index: v-bind(zIndex);
|
||||
bottom: var(--margin);
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
box-sizing: border-box;
|
||||
width: calc(100% - (var(--margin) * 2));
|
||||
max-width: 500px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.icon {
|
||||
text-align: center;
|
||||
padding-top: 25px;
|
||||
width: 100px;
|
||||
color: var(--accent);
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
.icon {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 450px) {
|
||||
.icon {
|
||||
width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 25px 25px 25px 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin: 0.7em 0 1em 0;
|
||||
}
|
||||
</style>
|
@ -12,6 +12,7 @@ type Keys =
|
||||
'latestDonationInfoShownAt' |
|
||||
'neverShowDonationInfo' |
|
||||
'neverShowLocalOnlyInfo' |
|
||||
'modifiedVersionMustProminentlyOfferInAgplV3Section13Read' |
|
||||
'lastUsed' |
|
||||
'lang' |
|
||||
'drafts' |
|
||||
|
@ -31,7 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<div class="_gaps_s">
|
||||
<FormLink to="https://github.com/misskey-dev/misskey" external>
|
||||
<template #icon><i class="ti ti-code"></i></template>
|
||||
{{ i18n.ts._aboutMisskey.source }}
|
||||
{{ i18n.ts._aboutMisskey.source }} ({{ i18n.ts._aboutMisskey.original }})
|
||||
<template #suffix>GitHub</template>
|
||||
</FormLink>
|
||||
<FormLink to="https://crowdin.com/project/misskey" external>
|
||||
@ -46,6 +46,25 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</FormLink>
|
||||
</div>
|
||||
</FormSection>
|
||||
<FormSection v-if="instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey'">
|
||||
<div class="_gaps_s">
|
||||
<MkInfo>
|
||||
{{ i18n.tsx._aboutMisskey.thisIsModifiedVersion({ name: instance.name }) }}
|
||||
</MkInfo>
|
||||
<FormLink v-if="instance.repositoryUrl" :to="instance.repositoryUrl" external>
|
||||
<template #icon><i class="ti ti-code"></i></template>
|
||||
{{ i18n.ts._aboutMisskey.source }}
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.providesTarball" :to="`/tarball/misskey-${version}.tar.gz`" external>
|
||||
<template #icon><i class="ti ti-download"></i></template>
|
||||
{{ i18n.ts._aboutMisskey.source }}
|
||||
<template #suffix>Tarball</template>
|
||||
</FormLink>
|
||||
<MkInfo v-if="!instance.repositoryUrl && !instance.providesTarball" warn>
|
||||
{{ i18n.ts.sourceCodeIsNotYetProvided }}
|
||||
</MkInfo>
|
||||
</div>
|
||||
</FormSection>
|
||||
<FormSection>
|
||||
<template #label>{{ i18n.ts._aboutMisskey.projectMembers }}</template>
|
||||
<div :class="$style.contributors">
|
||||
@ -118,9 +137,10 @@ import { version } from '@/config.js';
|
||||
import FormLink from '@/components/form/link.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkLink from '@/components/MkLink.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { physics } from '@/scripts/physics.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import * as os from '@/os.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
@ -31,7 +31,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</MkKeyValue>
|
||||
<div v-html="i18n.tsx.poweredByMisskeyDescription({ name: instance.name ?? host })">
|
||||
</div>
|
||||
<FormLink to="/about-misskey">{{ i18n.ts.aboutMisskey }}</FormLink>
|
||||
<FormLink to="/about-misskey">
|
||||
<template #icon><i class="ti ti-info-circle"></i></template>
|
||||
{{ i18n.ts.aboutMisskey }}
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.repositoryUrl || instance.providesTarball" :to="instance.repositoryUrl || `/tarball/misskey-${version}.tar.gz`" external>
|
||||
<template #icon><i class="ti ti-code"></i></template>
|
||||
{{ i18n.ts.sourceCode }}
|
||||
</FormLink>
|
||||
<MkInfo v-else warn>
|
||||
{{ i18n.ts.sourceCodeIsNotYetProvided }}
|
||||
</MkInfo>
|
||||
</div>
|
||||
</FormSection>
|
||||
|
||||
@ -47,17 +57,33 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<template #value>{{ instance.maintainerEmail }}</template>
|
||||
</MkKeyValue>
|
||||
</FormSplit>
|
||||
<FormLink v-if="instance.impressumUrl" :to="instance.impressumUrl" external>{{ i18n.ts.impressum }}</FormLink>
|
||||
<FormLink v-if="instance.impressumUrl" :to="instance.impressumUrl" external>
|
||||
<template #icon><i class="ti ti-user-shield"></i></template>
|
||||
{{ i18n.ts.impressum }}
|
||||
</FormLink>
|
||||
<div class="_gaps_s">
|
||||
<MkFolder v-if="instance.serverRules.length > 0">
|
||||
<template #label>{{ i18n.ts.serverRules }}</template>
|
||||
<template #label>
|
||||
<i class="ti ti-checkup-list"></i>
|
||||
{{ i18n.ts.serverRules }}
|
||||
</template>
|
||||
|
||||
<ol class="_gaps_s" :class="$style.rules">
|
||||
<li v-for="item, index in instance.serverRules" :key="index" :class="$style.rule"><div :class="$style.ruleText" v-html="item"></div></li>
|
||||
<li v-for="(item, index) in instance.serverRules" :key="index" :class="$style.rule"><div :class="$style.ruleText" v-html="item"></div></li>
|
||||
</ol>
|
||||
</MkFolder>
|
||||
<FormLink v-if="instance.tosUrl" :to="instance.tosUrl" external>{{ i18n.ts.termsOfService }}</FormLink>
|
||||
<FormLink v-if="instance.privacyPolicyUrl" :to="instance.privacyPolicyUrl" external>{{ i18n.ts.privacyPolicy }}</FormLink>
|
||||
<FormLink v-if="instance.tosUrl" :to="instance.tosUrl" external>
|
||||
<template #icon><i class="ti ti-license"></i></template>
|
||||
{{ i18n.ts.termsOfService }}
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.privacyPolicyUrl" :to="instance.privacyPolicyUrl" external>
|
||||
<template #icon><i class="ti ti-shield-lock"></i></template>
|
||||
{{ i18n.ts.privacyPolicy }}
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.feedbackUrl" :to="instance.feedbackUrl" external>
|
||||
<template #icon><i class="ti ti-message"></i></template>
|
||||
{{ i18n.ts.feedback }}
|
||||
</FormLink>
|
||||
</div>
|
||||
</div>
|
||||
</FormSection>
|
||||
@ -86,7 +112,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<FormLink :to="`/.well-known/nodeinfo`" external>nodeinfo</FormLink>
|
||||
<FormLink :to="`/robots.txt`" external>robots.txt</FormLink>
|
||||
<FormLink :to="`/manifest.json`" external>manifest.json</FormLink>
|
||||
<FormLink :to="`/tarball/misskey-${version}.tar.gz`" external>source code</FormLink>
|
||||
</div>
|
||||
</FormSection>
|
||||
</div>
|
||||
@ -116,6 +141,7 @@ import FormSuspense from '@/components/form/suspense.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkInstanceStats from '@/components/MkInstanceStats.vue';
|
||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
|
@ -76,6 +76,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<template #caption>{{ i18n.ts.instanceDefaultThemeDescription }}</template>
|
||||
</MkTextarea>
|
||||
|
||||
<MkInput v-model="repositoryUrl" type="url">
|
||||
<template #prefix><i class="ti ti-link"></i></template>
|
||||
<template #label>{{ i18n.ts.repositoryUrl }}</template>
|
||||
</MkInput>
|
||||
|
||||
<MkInput v-model="feedbackUrl" type="url">
|
||||
<template #prefix><i class="ti ti-link"></i></template>
|
||||
<template #label>{{ i18n.ts.feedbackUrl }}</template>
|
||||
</MkInput>
|
||||
|
||||
<MkTextarea v-model="manifestJsonOverride">
|
||||
<template #label>{{ i18n.ts._serverSettings.manifestJsonOverride }}</template>
|
||||
</MkTextarea>
|
||||
@ -120,6 +130,8 @@ const defaultDarkTheme = ref<string | null>(null);
|
||||
const serverErrorImageUrl = ref<string | null>(null);
|
||||
const infoImageUrl = ref<string | null>(null);
|
||||
const notFoundImageUrl = ref<string | null>(null);
|
||||
const repositoryUrl = ref<string | null>(null);
|
||||
const feedbackUrl = ref<string | null>(null);
|
||||
const manifestJsonOverride = ref<string>('{}');
|
||||
|
||||
async function init() {
|
||||
@ -135,6 +147,8 @@ async function init() {
|
||||
serverErrorImageUrl.value = meta.serverErrorImageUrl;
|
||||
infoImageUrl.value = meta.infoImageUrl;
|
||||
notFoundImageUrl.value = meta.notFoundImageUrl;
|
||||
repositoryUrl.value = meta.repositoryUrl;
|
||||
feedbackUrl.value = meta.feedbackUrl;
|
||||
manifestJsonOverride.value = meta.manifestJsonOverride === '' ? '{}' : JSON.stringify(JSON.parse(meta.manifestJsonOverride), null, '\t');
|
||||
}
|
||||
|
||||
@ -151,6 +165,8 @@ function save() {
|
||||
infoImageUrl: infoImageUrl.value === '' ? null : infoImageUrl.value,
|
||||
notFoundImageUrl: notFoundImageUrl.value === '' ? null : notFoundImageUrl.value,
|
||||
serverErrorImageUrl: serverErrorImageUrl.value === '' ? null : serverErrorImageUrl.value,
|
||||
repositoryUrl: repositoryUrl.value === '' ? null : repositoryUrl.value,
|
||||
feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value,
|
||||
manifestJsonOverride: manifestJsonOverride.value === '' ? '{}' : JSON.stringify(JSON5.parse(manifestJsonOverride.value)),
|
||||
}).then(() => {
|
||||
fetchInstance();
|
||||
|
@ -34,6 +34,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</MkInput>
|
||||
</FormSplit>
|
||||
|
||||
<MkInput v-model="repositoryUrl" type="url">
|
||||
<template #label>{{ i18n.ts.repositoryUrl }}</template>
|
||||
<template #prefix><i class="ti ti-link"></i></template>
|
||||
<template #caption>{{ i18n.ts.repositoryUrlDescription }}</template>
|
||||
</MkInput>
|
||||
|
||||
<MkInfo v-if="!instance.providesTarball && !repositoryUrl" warn>
|
||||
{{ i18n.ts.repositoryUrlOrTarballRequired }}
|
||||
</MkInfo>
|
||||
|
||||
<MkInput v-model="impressumUrl" type="url">
|
||||
<template #label>{{ i18n.ts.impressumUrl }}</template>
|
||||
<template #prefix><i class="ti ti-link"></i></template>
|
||||
@ -159,7 +169,7 @@ import FormSplit from '@/components/form/split.vue';
|
||||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
@ -169,6 +179,7 @@ const shortName = ref<string | null>(null);
|
||||
const description = ref<string | null>(null);
|
||||
const maintainerName = ref<string | null>(null);
|
||||
const maintainerEmail = ref<string | null>(null);
|
||||
const repositoryUrl = ref<string | null>(null);
|
||||
const impressumUrl = ref<string | null>(null);
|
||||
const pinnedUsers = ref<string>('');
|
||||
const cacheRemoteFiles = ref<boolean>(false);
|
||||
@ -191,6 +202,7 @@ async function init(): Promise<void> {
|
||||
description.value = meta.description;
|
||||
maintainerName.value = meta.maintainerName;
|
||||
maintainerEmail.value = meta.maintainerEmail;
|
||||
repositoryUrl.value = meta.repositoryUrl;
|
||||
impressumUrl.value = meta.impressumUrl;
|
||||
pinnedUsers.value = meta.pinnedUsers.join('\n');
|
||||
cacheRemoteFiles.value = meta.cacheRemoteFiles;
|
||||
@ -214,6 +226,7 @@ async function save(): void {
|
||||
description: description.value,
|
||||
maintainerName: maintainerName.value,
|
||||
maintainerEmail: maintainerEmail.value,
|
||||
repositoryUrl: repositoryUrl.value,
|
||||
impressumUrl: impressumUrl.value,
|
||||
pinnedUsers: pinnedUsers.value.split('\n'),
|
||||
cacheRemoteFiles: cacheRemoteFiles.value,
|
||||
|
@ -4845,7 +4845,7 @@ export type operations = {
|
||||
shortName: string | null;
|
||||
objectStorageS3ForcePathStyle: boolean;
|
||||
privacyPolicyUrl: string | null;
|
||||
repositoryUrl: string;
|
||||
repositoryUrl: string | null;
|
||||
summalyProxy: string | null;
|
||||
themeColor: string | null;
|
||||
tosUrl: string | null;
|
||||
@ -8757,8 +8757,8 @@ export type operations = {
|
||||
swPublicKey?: string | null;
|
||||
swPrivateKey?: string | null;
|
||||
tosUrl?: string | null;
|
||||
repositoryUrl?: string;
|
||||
feedbackUrl?: string;
|
||||
repositoryUrl?: string | null;
|
||||
feedbackUrl?: string | null;
|
||||
impressumUrl?: string | null;
|
||||
privacyPolicyUrl?: string | null;
|
||||
useObjectStorage?: boolean;
|
||||
@ -19450,6 +19450,7 @@ export type operations = {
|
||||
maintainerName: string | null;
|
||||
maintainerEmail: string | null;
|
||||
version: string;
|
||||
providesTarball: boolean;
|
||||
name: string;
|
||||
shortName: string | null;
|
||||
/**
|
||||
@ -19461,9 +19462,9 @@ export type operations = {
|
||||
langs: string[];
|
||||
tosUrl: string | null;
|
||||
/** @default https://github.com/misskey-dev/misskey */
|
||||
repositoryUrl: string;
|
||||
repositoryUrl: string | null;
|
||||
/** @default https://github.com/misskey-dev/misskey/issues/new */
|
||||
feedbackUrl: string;
|
||||
feedbackUrl: string | null;
|
||||
defaultDarkTheme: string | null;
|
||||
defaultLightTheme: string | null;
|
||||
disableRegistration: boolean;
|
||||
|
@ -5,7 +5,9 @@
|
||||
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import cssnano from 'cssnano';
|
||||
import * as yaml from 'js-yaml';
|
||||
import postcss from 'postcss';
|
||||
import * as terser from 'terser';
|
||||
|
||||
@ -14,8 +16,19 @@ import generateDTS from '../locales/generateDTS.js';
|
||||
import meta from '../package.json' assert { type: "json" };
|
||||
import buildTarball from './tarball.mjs';
|
||||
|
||||
const configDir = fileURLToPath(new URL('../.config', import.meta.url));
|
||||
const configPath = process.env.MISSKEY_CONFIG_YML
|
||||
? path.resolve(configDir, process.env.MISSKEY_CONFIG_YML)
|
||||
: process.env.NODE_ENV === 'test'
|
||||
? path.resolve(configDir, 'test.yml')
|
||||
: path.resolve(configDir, 'default.yml');
|
||||
|
||||
let locales = buildLocales();
|
||||
|
||||
async function loadConfig() {
|
||||
return fs.readFile(configPath, 'utf-8').then(data => yaml.load(data)).catch(() => null);
|
||||
}
|
||||
|
||||
async function copyFrontendFonts() {
|
||||
await fs.cp('./packages/frontend/node_modules/three/examples/fonts', './built/_frontend_dist_/fonts', { dereference: true, recursive: true });
|
||||
}
|
||||
@ -78,7 +91,7 @@ async function build() {
|
||||
copyBackendViews(),
|
||||
buildBackendScript(),
|
||||
buildBackendStyle(),
|
||||
buildTarball(),
|
||||
loadConfig().then(config => config?.publishTarballInsteadOfProvideRepositoryUrl && buildTarball()),
|
||||
]);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user