summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHazel K <acomputerdog@gmail.com>2024-10-06 12:26:25 -0400
committerHazel K <acomputerdog@gmail.com>2024-10-06 12:26:25 -0400
commit047563bdde95c528da5c136bf98935a06840f47e (patch)
tree154c9d666a13cfcd3b626a65942d3dc8f84b5aec
parentfix modlog and translations for "Mark as NSFW" (diff)
parentmerge: Warn when a domain is implicitly blocked because a base domain is bloc... (diff)
downloadsharkey-047563bdde95c528da5c136bf98935a06840f47e.tar.gz
sharkey-047563bdde95c528da5c136bf98935a06840f47e.tar.bz2
sharkey-047563bdde95c528da5c136bf98935a06840f47e.zip
Merge branch 'develop' into hazelnoot/579-reject-reports
# Conflicts: # packages/frontend/src/pages/instance-info.vue
-rw-r--r--locales/en-US.yml5
-rw-r--r--locales/index.d.ts28
-rw-r--r--locales/ja-JP.yml5
-rw-r--r--packages/backend/src/core/activitypub/ApRendererService.ts1
-rw-r--r--packages/backend/src/core/activitypub/misc/contexts.ts1
-rw-r--r--packages/backend/src/core/activitypub/models/ApNoteService.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/meta.ts2
-rw-r--r--packages/backend/src/server/web/ClientServerService.ts6
-rw-r--r--packages/frontend/assets/status/error.pngbin0 -> 26966 bytes
-rw-r--r--packages/frontend/assets/status/missingpage.webpbin0 -> 6578 bytes
-rw-r--r--packages/frontend/assets/status/nothinghere.pngbin0 -> 36452 bytes
-rw-r--r--packages/frontend/src/boot/main-boot.ts28
-rw-r--r--packages/frontend/src/components/MkPostForm.vue19
-rw-r--r--packages/frontend/src/components/MkVisitorDashboard.vue1
-rw-r--r--packages/frontend/src/const.ts6
-rw-r--r--packages/frontend/src/index.html2
-rw-r--r--packages/frontend/src/pages/instance-info.vue25
-rw-r--r--packages/frontend/src/pages/user/home.vue29
-rw-r--r--packages/misskey-js/src/autogen/types.ts2
19 files changed, 121 insertions, 41 deletions
diff --git a/locales/en-US.yml b/locales/en-US.yml
index dfd236b9c5..5cfeceb442 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -143,8 +143,10 @@ markAsSensitive: "Mark as sensitive"
unmarkAsSensitive: "Unmark as sensitive"
enterFileName: "Enter filename"
mute: "Mute"
+muted: "Muted"
unmute: "Unmute"
renoteMute: "Mute Boosts"
+renoteMuted: "Boosts muted"
renoteUnmute: "Unmute Boosts"
block: "Block"
unblock: "Unblock"
@@ -265,6 +267,9 @@ noCustomEmojis: "There are no emoji"
noJobs: "There are no jobs"
federating: "Federating"
blocked: "Blocked"
+blockedByBase: "This host is blocked implicitly because a base domain is blocked. To unblock this host, first unblock the base domain(s)."
+silencedByBase: "This host is silenced implicitly because a base domain is silenced. To un-silence this host, first un-silence the base domain(s)."
+mediaSilencedByBase: "This host's media is silenced implicitly because a base domain's media is silenced. To un-silence this host, first un-silence the base domain(s)."
suspended: "Suspended"
all: "All"
subscribing: "Subscribing"
diff --git a/locales/index.d.ts b/locales/index.d.ts
index fb8d9339fc..b3699e2a9c 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -589,6 +589,10 @@ export interface Locale extends ILocale {
*/
"mute": string;
/**
+ * Muted
+ */
+ "muted": string;
+ /**
* ミュート解除
*/
"unmute": string;
@@ -597,6 +601,10 @@ export interface Locale extends ILocale {
*/
"renoteMute": string;
/**
+ * Boosts muted
+ */
+ "renoteMuted": string;
+ /**
* ブーストのミュートを解除
*/
"renoteUnmute": string;
@@ -1077,6 +1085,18 @@ export interface Locale extends ILocale {
*/
"blocked": string;
/**
+ * This host is blocked implicitly because a base domain is blocked. To unblock this host, first unblock the base domain(s).
+ */
+ "blockedByBase": string;
+ /**
+ * This host is silenced implicitly because a base domain is silenced. To un-silence this host, first un-silence the base domain(s).
+ */
+ "silencedByBase": string;
+ /**
+ * This host's media is silenced implicitly because a base domain's media is silenced. To un-silence this host, first un-silence the base domain(s).
+ */
+ "mediaSilencedByBase": string;
+ /**
* 配信停止
*/
"suspended": string;
@@ -4442,10 +4462,6 @@ export interface Locale extends ILocale {
*/
"disableFederationOk": string;
/**
- * 猫の話し方を無効にする
- */
- "disableCatSpeak": string;
- /**
* 現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。
*/
"invitationRequiredToRegister": string;
@@ -5789,7 +5805,7 @@ export interface Locale extends ILocale {
*/
"social": string;
/**
- * バッッブルタイムラインでは、管理者が選択した接続サーバーからのメモを表示できます。
+ * バブルタイムラインでは、管理者が選択した接続サーバーからの投稿を表示できます。
*/
"bubble": string;
/**
@@ -9151,7 +9167,7 @@ export interface Locale extends ILocale {
*/
"global": string;
/**
- * バッッブル
+ * バブル
*/
"bubble": string;
};
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index d86b7a73d1..e115640a6a 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -143,8 +143,10 @@ markAsSensitive: "センシティブとして設定"
unmarkAsSensitive: "センシティブを解除する"
enterFileName: "ファイル名を入力"
mute: "ミュート"
+muted: "Muted"
unmute: "ミュート解除"
renoteMute: "ブーストをミュート"
+renoteMuted: "Boosts muted"
renoteUnmute: "ブーストのミュートを解除"
block: "ブロック"
unblock: "ブロック解除"
@@ -265,6 +267,9 @@ noCustomEmojis: "絵文字はありません"
noJobs: "ジョブはありません"
federating: "連合中"
blocked: "ブロック中"
+blockedByBase: "This host is blocked implicitly because a base domain is blocked. To unblock this host, first unblock the base domain(s)."
+silencedByBase: "This host is silenced implicitly because a base domain is silenced. To un-silence this host, first un-silence the base domain(s)."
+mediaSilencedByBase: "This host's media is silenced implicitly because a base domain's media is silenced. To un-silence this host, first un-silence the base domain(s)."
suspended: "配信停止"
all: "全て"
subscribing: "購読中"
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index 55d1054de9..499a163d6c 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -526,6 +526,7 @@ export class ApRendererService {
publicKey: this.renderKey(user, keypair, '#main-key'),
isCat: user.isCat,
noindex: user.noindex,
+ indexable: !user.noindex,
speakAsCat: user.speakAsCat,
attachment: attachment.length ? attachment : undefined,
};
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index 815b20b910..86a665732a 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -545,6 +545,7 @@ const extension_context_definition = {
Emoji: 'toot:Emoji',
featured: 'toot:featured',
discoverable: 'toot:discoverable',
+ indexable: 'toot:indexable',
// schema
schema: 'http://schema.org#',
PropertyValue: 'schema:PropertyValue',
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index 7b7a7921fb..382cda301f 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -587,7 +587,7 @@ export class ApNoteService {
// ここでuriの代わりに添付されてきたNote Objectが指定されていると、サーバーフェッチを経ずにノートが生成されるが
// 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。
const createFrom = options.sentFrom?.origin === new URL(uri).origin ? value : uri;
- return await this.createNote(createFrom, options.resolver, true);
+ return await this.createNote(createFrom, options.resolver, false);
} finally {
unlock();
}
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index 5a69fbf679..dbfa31024a 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -128,7 +128,7 @@ export const meta = {
},
silencedHosts: {
type: 'array',
- optional: true,
+ optional: false,
nullable: false,
items: {
type: 'string',
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index 0af90a844b..e20707977f 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -193,9 +193,9 @@ export class ClientServerService {
icon: meta.iconUrl,
appleTouchIcon: meta.app512IconUrl,
themeColor: meta.themeColor,
- serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://launcher.moe/error.png',
- infoImageUrl: meta.infoImageUrl ?? 'https://launcher.moe/nothinghere.png',
- notFoundImageUrl: meta.notFoundImageUrl ?? 'https://launcher.moe/missingpage.webp',
+ serverErrorImageUrl: meta.serverErrorImageUrl ?? '/status/error.png',
+ infoImageUrl: meta.infoImageUrl ?? '/status/nothinghere.png',
+ notFoundImageUrl: meta.notFoundImageUrl ?? '/status/missingpage.webp',
instanceUrl: this.config.url,
randomMOTD: this.config.customMOTD ? this.config.customMOTD[Math.floor(Math.random() * this.config.customMOTD.length)] : undefined,
metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(meta)),
diff --git a/packages/frontend/assets/status/error.png b/packages/frontend/assets/status/error.png
new file mode 100644
index 0000000000..9f21236c39
--- /dev/null
+++ b/packages/frontend/assets/status/error.png
Binary files differ
diff --git a/packages/frontend/assets/status/missingpage.webp b/packages/frontend/assets/status/missingpage.webp
new file mode 100644
index 0000000000..3ac83b3110
--- /dev/null
+++ b/packages/frontend/assets/status/missingpage.webp
Binary files differ
diff --git a/packages/frontend/assets/status/nothinghere.png b/packages/frontend/assets/status/nothinghere.png
new file mode 100644
index 0000000000..5ebe210acd
--- /dev/null
+++ b/packages/frontend/assets/status/nothinghere.png
Binary files differ
diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts
index c10930a038..5ff998fac4 100644
--- a/packages/frontend/src/boot/main-boot.ts
+++ b/packages/frontend/src/boot/main-boot.ts
@@ -216,19 +216,25 @@ export async function mainBoot() {
claimAchievement('collectAchievements30');
}
- window.setInterval(() => {
- if (Math.floor(Math.random() * 20000) === 0) {
- claimAchievement('justPlainLucky');
- }
- }, 1000 * 10);
+ if (!claimedAchievements.includes('justPlainLucky')) {
+ window.setInterval(() => {
+ if (Math.floor(Math.random() * 20000) === 0) {
+ claimAchievement('justPlainLucky');
+ }
+ }, 1000 * 10);
+ }
- window.setTimeout(() => {
- claimAchievement('client30min');
- }, 1000 * 60 * 30);
+ if (!claimedAchievements.includes('client30min')) {
+ window.setTimeout(() => {
+ claimAchievement('client30min');
+ }, 1000 * 60 * 30);
+ }
- window.setTimeout(() => {
- claimAchievement('client60min');
- }, 1000 * 60 * 60);
+ if (!claimedAchievements.includes('client60min')) {
+ window.setTimeout(() => {
+ claimAchievement('client60min');
+ }, 1000 * 60 * 60);
+ }
// 邪魔
//const lastUsed = miLocalStorage.getItem('lastUsed');
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index dc3f3aa94c..add5296f0a 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -630,11 +630,22 @@ async function onPaste(ev: ClipboardEvent) {
if (paste.length > 1000) {
ev.preventDefault();
- os.confirm({
- type: 'info',
+ os.actions({
+ type: 'question',
text: i18n.ts.attachAsFileQuestion,
- }).then(({ canceled }) => {
- if (canceled) {
+ actions: [
+ {
+ value: 'yes',
+ text: i18n.ts.yes,
+ primary: true,
+ },
+ {
+ value: 'no',
+ text: i18n.ts.no,
+ },
+ ],
+ }).then(({ result }) => {
+ if (result !== 'yes') {
insertTextAtCursor(textareaEl.value, paste);
return;
}
diff --git a/packages/frontend/src/components/MkVisitorDashboard.vue b/packages/frontend/src/components/MkVisitorDashboard.vue
index b154f7a5b3..ff2e27aaf8 100644
--- a/packages/frontend/src/components/MkVisitorDashboard.vue
+++ b/packages/frontend/src/components/MkVisitorDashboard.vue
@@ -142,6 +142,7 @@ function showMenu(ev: MouseEvent) {
height: 32px;
border-radius: var(--radius-sm);
font-size: 18px;
+ z-index: 50;
}
.mainFg {
diff --git a/packages/frontend/src/const.ts b/packages/frontend/src/const.ts
index c94c0d4408..058db9b981 100644
--- a/packages/frontend/src/const.ts
+++ b/packages/frontend/src/const.ts
@@ -160,9 +160,9 @@ export const ROLE_POLICIES = [
export const CURRENT_STICKY_TOP = 'CURRENT_STICKY_TOP';
export const CURRENT_STICKY_BOTTOM = 'CURRENT_STICKY_BOTTOM';
-export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://launcher.moe/error.png';
-export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://launcher.moe/missingpage.webp';
-export const DEFAULT_INFO_IMAGE_URL = 'https://launcher.moe/nothinghere.png';
+export const DEFAULT_SERVER_ERROR_IMAGE_URL = '/status/error.png';
+export const DEFAULT_NOT_FOUND_IMAGE_URL = '/status/missingpage.webp';
+export const DEFAULT_INFO_IMAGE_URL = '/status/nothinghere.png';
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime', 'crop', 'fade', 'followmouse'];
export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
diff --git a/packages/frontend/src/index.html b/packages/frontend/src/index.html
index 733116b75f..fdeb642c70 100644
--- a/packages/frontend/src/index.html
+++ b/packages/frontend/src/index.html
@@ -20,7 +20,7 @@
worker-src 'self';
script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://challenges.cloudflare.com https://esm.sh;
style-src 'self' 'unsafe-inline';
- img-src 'self' data: blob: www.google.com xn--931a.moe launcher.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 activitypub.software secure.gravatar.com avatars.githubusercontent.com;
+ img-src 'self' data: blob: www.google.com xn--931a.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 activitypub.software secure.gravatar.com avatars.githubusercontent.com;
media-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;
connect-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 https://newassets.hcaptcha.com https://api.listenbrainz.org;
frame-src *;"
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index b5803ab3f1..5401ea51e0 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -45,11 +45,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkKeyValue>
<MkButton v-if="suspensionState === 'none'" :disabled="!instance" danger @click="stopDelivery">{{ i18n.ts._delivery.stop }}</MkButton>
<MkButton v-if="suspensionState !== 'none'" :disabled="!instance" @click="resumeDelivery">{{ i18n.ts._delivery.resume }}</MkButton>
- <MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
- <MkSwitch v-model="isSilenced" :disabled="!meta || !instance" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch>
+ <MkInfo v-if="isBaseBlocked" warn>{{ i18n.ts.blockedByBase }}</MkInfo>
+ <MkSwitch v-model="isBlocked" :disabled="!meta || !instance || isBaseBlocked" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
+ <MkInfo v-if="isBaseSilenced" warn>{{ i18n.ts.silencedByBase }}</MkInfo>
+ <MkSwitch v-model="isSilenced" :disabled="!meta || !instance || isBaseSilenced" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch>
<MkSwitch v-model="isNSFW" :disabled="!instance" @update:modelValue="toggleNSFW">{{ i18n.ts.markInstanceAsNSFW }}</MkSwitch>
<MkSwitch v-model="rejectReports" :disabled="!instance" @update:modelValue="toggleRejectReports">{{ i18n.ts.rejectReports }}</MkSwitch>
- <MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch>
+ <MkInfo v-if="isBaseMediaSilenced" warn>{{ i18n.ts.mediaSilencedByBase }}</MkInfo>
+ <MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance || isBaseMediaSilenced" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch>
<MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
<MkTextarea v-model="moderationNote" manualSave>
<template #label>{{ i18n.ts.moderationNote }}</template>
@@ -157,6 +160,7 @@ import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js';
import { dateString } from '@/filters/date.js';
import MkTextarea from '@/components/MkTextarea.vue';
+import MkInfo from '@/components/MkInfo.vue';
const props = defineProps<{
host: string;
@@ -176,6 +180,21 @@ const isMediaSilenced = ref(false);
const faviconUrl = ref<string | null>(null);
const moderationNote = ref('');
+const baseDomains = computed(() => {
+ const domains: string[] = [];
+
+ const parts = props.host.toLowerCase().split('.');
+ for (let s = 1; s < parts.length; s++) {
+ const domain = parts.slice(s).join('.');
+ domains.push(domain);
+ }
+
+ return domains;
+});
+const isBaseBlocked = computed(() => meta.value && baseDomains.value.some(d => meta.value?.blockedHosts.includes(d)));
+const isBaseSilenced = computed(() => meta.value && baseDomains.value.some(d => meta.value?.silencedHosts.includes(d)));
+const isBaseMediaSilenced = computed(() => meta.value && baseDomains.value.some(d => meta.value?.mediaSilencedHosts.includes(d)));
+
const usersPagination = {
endpoint: iAmModerator ? 'admin/show-users' : 'users' as const,
limit: 10,
diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue
index b997fe1c3f..e82ec0cb97 100644
--- a/packages/frontend/src/pages/user/home.vue
+++ b/packages/frontend/src/pages/user/home.vue
@@ -30,7 +30,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</button>
</div>
</div>
- <span v-if="$i && $i.id != user.id && user.isFollowed" class="followed">{{ i18n.ts.followsYou }}</span>
+ <div v-if="$i && $i.id != user.id" class="info-badges">
+ <span v-if="user.isFollowed">{{ i18n.ts.followsYou }}</span>
+ <span v-if="user.isMuted">{{ i18n.ts.muted }}</span>
+ <span v-if="user.isRenoteMuted">{{ i18n.ts.renoteMuted }}</span>
+ <span v-if="user.isBlocking">{{ i18n.ts.blocked }}</span>
+ </div>
<div class="actions">
<button class="menu _button" @click="menu"><i class="ti ti-dots"></i></button>
<MkFollowButton v-if="$i?.id != user.id" v-model:user="user" :inline="true" :transparent="false" :full="true" class="koudoku"/>
@@ -445,15 +450,25 @@ onUnmounted(() => {
background: linear-gradient(transparent, rgba(#000, 0.7));
}
- > .followed {
+ > .info-badges {
position: absolute;
top: 12px;
left: 12px;
- padding: 4px 8px;
- color: #fff;
- background: rgba(0, 0, 0, 0.7);
- font-size: 0.7em;
- border-radius: var(--radius-sm);
+
+ display: flex;
+ flex-direction: row;
+
+ > * {
+ padding: 4px 8px;
+ color: #fff;
+ background: rgba(0, 0, 0, 0.7);
+ font-size: 0.7em;
+ border-radius: var(--radius-sm);
+ }
+
+ > :not(:first-child) {
+ margin-left: 8px;
+ }
}
> .actions {
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 0e83bdfcca..e3bf828982 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -5199,7 +5199,7 @@ export type operations = {
enableEmail: boolean;
enableServiceWorker: boolean;
translatorAvailable: boolean;
- silencedHosts?: string[];
+ silencedHosts: string[];
mediaSilencedHosts: string[];
pinnedUsers: string[];
hiddenTags: string[];