chore(koi): sharkey is no more
This commit is contained in:
parent
9bc0f4c841
commit
3e5ff3efb3
16 changed files with 1 additions and 970 deletions
|
@ -24,10 +24,10 @@
|
|||
./services/geesefs.nix
|
||||
|
||||
./containers/torrent.nix
|
||||
./containers/soulseek
|
||||
./containers/vaultwarden.nix
|
||||
./containers/sftpgo
|
||||
./containers/verdaccio
|
||||
./containers/sharkey
|
||||
./containers/pds
|
||||
./containers/navidrome
|
||||
./containers/conduwuit
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
url: https://very.stupid.fish
|
||||
port: 80
|
||||
|
||||
db:
|
||||
host: 172.17.0.1
|
||||
port: 5432
|
||||
db: misskey
|
||||
user: misskey
|
||||
pass: misskey
|
||||
|
||||
dbReplications: false
|
||||
|
||||
redis:
|
||||
host: sharkey-redis.docker
|
||||
port: 6379
|
||||
|
||||
# ┌───────────────────────────┐
|
||||
#───┘ MeiliSearch configuration └─────────────────────────────
|
||||
|
||||
meilisearch:
|
||||
host: sharkey-meili.docker
|
||||
port: 7700
|
||||
apiKey: misskeymeilisearch
|
||||
index: ''
|
||||
scope: global
|
||||
|
||||
id: 'aidx'
|
||||
|
||||
# Number of worker processes
|
||||
clusterLimit: 2
|
||||
|
||||
maxNoteLength: 30000
|
||||
|
||||
proxy: 'http://172.17.0.1:7890'
|
||||
proxyBypassHosts:
|
||||
- api.deepl.com
|
||||
- api-free.deepl.com
|
||||
- www.recaptcha.net
|
||||
- hcaptcha.com
|
||||
- challenges.cloudflare.com
|
||||
- tei.su
|
||||
|
||||
# Media Proxy
|
||||
# Reference Implementation: https://github.com/misskey-dev/media-proxy
|
||||
# * Deliver a common cache between instances
|
||||
# * Perform image compression (on a different server resource than the main process)
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: true)
|
||||
# Proxy remote files by this instance or mediaProxy to prevent remote files from running in remote domains.
|
||||
proxyRemoteFiles: true
|
||||
|
||||
# Movie Thumbnail Generation URL
|
||||
# There is no reference implementation.
|
||||
# For example, Misskey will point to the following URL:
|
||||
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
|
||||
#videoThumbnailGenerator: https://example.com
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
|
||||
checkActivityPubGetSignature: false
|
||||
|
||||
# For security reasons, uploading attachments from the intranet is prohibited,
|
||||
# but exceptions can be made from the following settings. Default value is "undefined".
|
||||
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
|
||||
#allowedPrivateNetworks: [
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
customMOTD: ['meow']
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
maxFileSize: 262144000
|
|
@ -1,108 +0,0 @@
|
|||
# based on https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/Dockerfile
|
||||
ARG NODE_VERSION=20.12.2-alpine3.19
|
||||
|
||||
FROM node:${NODE_VERSION} as build
|
||||
|
||||
|
||||
RUN apk add git linux-headers build-base patch
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
RUN apk add --update python3 && ln -sf python3 /usr/bin/python
|
||||
RUN apk add py3-pip py3-setuptools
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
# begin fetch
|
||||
ARG COMMIT=c344705d6708fdc725d6122d2b321cb2d01dad4b
|
||||
RUN git clone https://activitypub.software/TransFem-org/Sharkey.git /sharkey --depth=1 && \
|
||||
cd /sharkey && \
|
||||
git fetch --depth=1 origin ${COMMIT} && \
|
||||
git checkout ${COMMIT} && \
|
||||
git submodule update --init --recursive
|
||||
# end fetch
|
||||
|
||||
WORKDIR /sharkey
|
||||
|
||||
RUN echo a 1 && git rev-parse HEAD
|
||||
|
||||
RUN pnpm config set fetch-retries 5
|
||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||
pnpm i --frozen-lockfile --aggregate-output
|
||||
|
||||
# begin patch
|
||||
COPY patches /patches
|
||||
|
||||
RUN git apply /patches/zond.patch
|
||||
RUN git apply /patches/software.patch
|
||||
RUN git apply /patches/stats.patch
|
||||
RUN git apply /patches/limits.patch
|
||||
RUN git apply /patches/unfollow-notification.patch
|
||||
RUN git apply /patches/webhook-notification.patch
|
||||
# motivation: https://very.stupid.fish/notes/9shhrn2qncid008s
|
||||
RUN git apply /patches/index-everything.patch
|
||||
RUN git apply /patches/no-remote-users.patch
|
||||
RUN git apply /patches/no-xpost-extension.patch
|
||||
RUN cp -f /patches/robots.txt packages/backend/assets/robots.txt
|
||||
# end patch
|
||||
|
||||
RUN pnpm build
|
||||
RUN node scripts/trim-deps.mjs
|
||||
RUN mv packages/frontend/assets sharkey-assets
|
||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||
pnpm prune
|
||||
RUN rm -r node_modules packages/frontend packages/sw
|
||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||
pnpm i --prod --frozen-lockfile --aggregate-output
|
||||
RUN rm -rf .git
|
||||
|
||||
# begin post-build patch
|
||||
RUN node /patches/patch-locale.js
|
||||
# end post-build patch
|
||||
|
||||
FROM node:${NODE_VERSION}
|
||||
|
||||
ARG UID="1104"
|
||||
ARG GID="1104"
|
||||
|
||||
RUN apk add ffmpeg tini jemalloc \
|
||||
&& corepack enable \
|
||||
&& addgroup -g "${GID}" sharkey \
|
||||
&& adduser -D -u "${UID}" -G sharkey -h /sharkey sharkey \
|
||||
&& find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /u+s -exec chmod u-s {} \; \
|
||||
&& find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /g+s -exec chmod g-s {} \;
|
||||
|
||||
USER sharkey
|
||||
WORKDIR /sharkey
|
||||
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/node_modules ./node_modules
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/node_modules ./packages/backend/node_modules
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-reversi/node_modules ./packages/misskey-reversi/node_modules
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-bubble-game/node_modules ./packages/misskey-bubble-game/node_modules
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/megalodon/node_modules ./packages/megalodon/node_modules
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/built ./built
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-js/built ./packages/misskey-js/built
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-reversi/built ./packages/misskey-reversi/built
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/built ./packages/backend/built
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/megalodon/lib ./packages/megalodon/lib
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/fluent-emojis ./fluent-emojis
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/tossface-emojis/dist ./tossface-emojis/dist
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/sharkey-assets ./packages/frontend/assets
|
||||
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/package.json ./package.json
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/pnpm-workspace.yaml ./pnpm-workspace.yaml
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/package.json ./packages/backend/package.json
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/scripts/check_connect.js ./packages/backend/scripts/check_connect.js
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/ormconfig.js ./packages/backend/ormconfig.js
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/migration ./packages/backend/migration
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/assets ./packages/backend/assets
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/megalodon/package.json ./packages/megalodon/package.json
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-js/package.json ./packages/misskey-js/package.json
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-reversi/package.json ./packages/misskey-reversi/package.json
|
||||
COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-bubble-game/package.json ./packages/misskey-bubble-game/package.json
|
||||
|
||||
ENV LD_PRELOAD=/usr/lib/libjemalloc.so.2
|
||||
ENV NODE_ENV=production
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
CMD ["pnpm", "run", "migrateandstart"]
|
|
@ -1,78 +0,0 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
UID = 1104;
|
||||
context = pkgs.copyPathToStore ./.;
|
||||
in {
|
||||
users.users.misskey = {
|
||||
isNormalUser = true;
|
||||
uid = UID;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /srv/Sharkey 0777 root root -"
|
||||
];
|
||||
|
||||
services.postgresql.ensureUsers = [
|
||||
{ name = "misskey"; ensureDBOwnership = true; }
|
||||
];
|
||||
services.postgresql.ensureDatabases = [ "misskey" ];
|
||||
desu.postgresql.ensurePasswords.misskey = "misskey";
|
||||
|
||||
virtualisation.oci-containers.containers.sharkey-redis = {
|
||||
image = "docker.io/redis:7.0-alpine";
|
||||
volumes = [
|
||||
"/srv/Sharkey/redis:/data"
|
||||
];
|
||||
user = builtins.toString UID;
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.sharkey-meili = {
|
||||
image = "getmeili/meilisearch:v1.3.4";
|
||||
volumes = [
|
||||
"/srv/Sharkey/meili_data:/meili_data"
|
||||
];
|
||||
environment = {
|
||||
MEILI_NO_ANALYTICS = "true";
|
||||
MEILI_ENV = "production";
|
||||
MEILI_MASTER_KEY = "misskeymeilisearch";
|
||||
};
|
||||
user = builtins.toString UID;
|
||||
};
|
||||
|
||||
# not really reproducible but fuck it i figured it's the best way lol.
|
||||
# im **not** rewriting that 100 lines dockerfile
|
||||
systemd.services.docker-sharkey.serviceConfig.ExecStartPre = [
|
||||
(pkgs.writeShellScript "build-sharkey" ''
|
||||
docker build -t local/sharkey ${context}
|
||||
'')
|
||||
];
|
||||
systemd.services.docker-sharkey.after = [ "postgresql.service" ];
|
||||
virtualisation.oci-containers.containers.sharkey = {
|
||||
dependsOn = [ "sharkey-redis" "sharkey-meili" ];
|
||||
image = "local/sharkey";
|
||||
volumes = [
|
||||
"/srv/Sharkey/files:/sharkey/files"
|
||||
"${context}/.config:/sharkey/.config:ro"
|
||||
];
|
||||
environment = {
|
||||
NODE_ENV = "production";
|
||||
};
|
||||
user = builtins.toString UID;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."very.stupid.fish" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "stupid.fish";
|
||||
http2 = true;
|
||||
|
||||
extraConfig = ''
|
||||
client_max_body_size 250M;
|
||||
'';
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://sharkey.docker$request_uri";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts
|
||||
index 631d707..cf537fd 100644
|
||||
--- a/packages/backend/src/core/NoteCreateService.ts
|
||||
+++ b/packages/backend/src/core/NoteCreateService.ts
|
||||
@@ -952,7 +952,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||
}
|
||||
|
||||
// Register to search database
|
||||
- if (!user.noindex) this.index(note);
|
||||
+ this.index(note);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
@@ -1051,7 +1051,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||
}
|
||||
|
||||
// Register to search database
|
||||
- if (!user.noindex) this.index(note);
|
||||
+ this.index(note);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts
|
||||
index a01dfec..8fd3138 100644
|
||||
--- a/packages/backend/src/core/NoteEditService.ts
|
||||
+++ b/packages/backend/src/core/NoteEditService.ts
|
||||
@@ -728,7 +728,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||
}
|
||||
|
||||
// Register to search database
|
||||
- if (!user.noindex) this.index(note);
|
||||
+ this.index(note);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
diff --git a/packages/backend/src/core/SearchService.ts b/packages/backend/src/core/SearchService.ts
|
||||
index 6dc3e85..087bd36 100644
|
||||
--- a/packages/backend/src/core/SearchService.ts
|
||||
+++ b/packages/backend/src/core/SearchService.ts
|
||||
@@ -115,7 +115,6 @@ export class SearchService {
|
||||
@bindThis
|
||||
public async indexNote(note: MiNote): Promise<void> {
|
||||
if (note.text == null && note.cw == null) return;
|
||||
- if (!['home', 'public'].includes(note.visibility)) return;
|
||||
|
||||
if (this.meilisearch) {
|
||||
switch (this.meilisearchIndexScope) {
|
|
@ -1,20 +0,0 @@
|
|||
diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts
|
||||
index 02c2777..cd46330 100644
|
||||
--- a/packages/backend/src/const.ts
|
||||
+++ b/packages/backend/src/const.ts
|
||||
@@ -15,13 +15,13 @@ export const USER_ACTIVE_THRESHOLD = 1000 * 60 * 60 * 24 * 3; // 3days
|
||||
* Maximum note text length that can be stored in DB.
|
||||
* Surrogate pairs count as one
|
||||
*/
|
||||
-export const DB_MAX_NOTE_TEXT_LENGTH = 8192;
|
||||
+export const DB_MAX_NOTE_TEXT_LENGTH = 32768;
|
||||
|
||||
/**
|
||||
* Maximum image description length that can be stored in DB.
|
||||
* Surrogate pairs count as one
|
||||
*/
|
||||
-export const DB_MAX_IMAGE_COMMENT_LENGTH = 8192;
|
||||
+export const DB_MAX_IMAGE_COMMENT_LENGTH = 32768;
|
||||
//#endregion
|
||||
|
||||
// ブラウザで直接表示することを許可するファイルの種類のリスト
|
|
@ -1,71 +0,0 @@
|
|||
diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts
|
||||
index bd81989..8aaf8ca 100644
|
||||
--- a/packages/backend/src/server/api/endpoints/users/show.ts
|
||||
+++ b/packages/backend/src/server/api/endpoints/users/show.ts
|
||||
@@ -97,6 +97,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
const isModerator = await this.roleService.isModerator(me);
|
||||
ps.username = ps.username?.trim();
|
||||
|
||||
+ const authed = me !== null
|
||||
+
|
||||
if (ps.userIds) {
|
||||
if (ps.userIds.length === 0) {
|
||||
return [];
|
||||
@@ -112,7 +114,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
const _users: MiUser[] = [];
|
||||
for (const id of ps.userIds) {
|
||||
- const user = users.find(x => x.id === id);
|
||||
- if (user != null) _users.push(user);
|
||||
+ const user = users.find(x => x.id === id)
|
||||
+ if (user && (authed || user.host === null)) {
|
||||
+ _users.push(user);
|
||||
+ }
|
||||
}
|
||||
|
||||
const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailed' })
|
||||
@@ -137,6 +142,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
}
|
||||
|
||||
+ if (!authed && user.host !== null) {
|
||||
+ throw new ApiError({
|
||||
+ code: 'X_REMOTE_REDIRECT',
|
||||
+ message: 'Redirect to remote user',
|
||||
+ id: 'X_REMOTE_REDIRECT',
|
||||
+ }, user.uri);
|
||||
+ }
|
||||
+
|
||||
if (user.host == null) {
|
||||
if (me == null && ip != null) {
|
||||
this.perUserPvChart.commitByVisitor(user, ip);
|
||||
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
|
||||
index cb41c4f..8199e3c 100644
|
||||
--- a/packages/backend/src/server/web/ClientServerService.ts
|
||||
+++ b/packages/backend/src/server/web/ClientServerService.ts
|
||||
@@ -526,6 +526,11 @@ export class ClientServerService {
|
||||
|
||||
if (user != null) {
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
|
||||
+ if (user.host !== null) {
|
||||
+ reply.redirect(301, profile.url);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
const meta = await this.metaService.fetch();
|
||||
const me = profile.fields
|
||||
? profile.fields
|
||||
diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue
|
||||
index ebe4176..0cd39f3 100644
|
||||
--- a/packages/frontend/src/pages/user/index.vue
|
||||
+++ b/packages/frontend/src/pages/user/index.vue
|
||||
@@ -70,6 +70,10 @@ function fetchUser(): void {
|
||||
misskeyApi('users/show', Misskey.acct.parse(props.acct)).then(u => {
|
||||
user.value = u;
|
||||
}).catch(err => {
|
||||
+ if (err.code === 'X_REMOTE_REDIRECT') {
|
||||
+ location.replace(err.info);
|
||||
+ return;
|
||||
+ }
|
||||
error.value = err;
|
||||
});
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
diff --git a/packages/backend/migration/1722103475000-no-xpost.js b/packages/backend/migration/1722103475000-no-xpost.js
|
||||
new file mode 100644
|
||||
index 0000000..8818c37
|
||||
--- /dev/null
|
||||
+++ b/packages/backend/migration/1722103475000-no-xpost.js
|
||||
@@ -0,0 +1,16 @@
|
||||
+/*
|
||||
+ * SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
+ * SPDX-License-Identifier: AGPL-3.0-only
|
||||
+ */
|
||||
+
|
||||
+export class NoXpost1722103475000 {
|
||||
+ name = 'NoXpost1722103475000'
|
||||
+
|
||||
+ async up(queryRunner) {
|
||||
+ await queryRunner.query(`ALTER TABLE "note" ADD "noXpost" boolean NOT NULL DEFAULT false`);
|
||||
+ }
|
||||
+
|
||||
+ async down(queryRunner) {
|
||||
+ await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "noXpost"`);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts
|
||||
index 41efa76..87a388e 100644
|
||||
--- a/packages/backend/src/core/NoteCreateService.ts
|
||||
+++ b/packages/backend/src/core/NoteCreateService.ts
|
||||
@@ -149,6 +149,7 @@ type Option = {
|
||||
uri?: string | null;
|
||||
url?: string | null;
|
||||
app?: MiApp | null;
|
||||
+ noXpost?: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -625,6 +626,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||
renoteUserId: data.renote ? data.renote.userId : null,
|
||||
renoteUserHost: data.renote ? data.renote.userHost : null,
|
||||
userHost: user.host,
|
||||
+ noXpost: data.noXpost,
|
||||
});
|
||||
|
||||
// should really not happen, but better safe than sorry
|
||||
diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts
|
||||
index 0cb58d0..00b4be3 100644
|
||||
--- a/packages/backend/src/core/NoteEditService.ts
|
||||
+++ b/packages/backend/src/core/NoteEditService.ts
|
||||
@@ -141,6 +141,7 @@ type Option = {
|
||||
app?: MiApp | null;
|
||||
updatedAt?: Date | null;
|
||||
editcount?: boolean | null;
|
||||
+ noXpost?: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -494,6 +495,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||
renoteUserId: data.renote ? data.renote.userId : null,
|
||||
renoteUserHost: data.renote ? data.renote.userHost : null,
|
||||
userHost: user.host,
|
||||
+ noXpost: data.noXpost,
|
||||
});
|
||||
|
||||
if (data.uri != null) note.uri = data.uri;
|
||||
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
|
||||
index 90784fd..0f9769f 100644
|
||||
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
|
||||
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
|
||||
@@ -467,6 +467,7 @@ export class ApRendererService {
|
||||
attachment: files.map(x => this.renderDocument(x)),
|
||||
sensitive: note.cw != null || files.some(file => file.isSensitive),
|
||||
tag,
|
||||
+ 'desu:no-xpost': note.noXpost,
|
||||
...asPoll,
|
||||
};
|
||||
}
|
||||
@@ -759,6 +760,7 @@ export class ApRendererService {
|
||||
attachment: files.map(x => this.renderDocument(x)),
|
||||
sensitive: note.cw != null || files.some(file => file.isSensitive),
|
||||
tag,
|
||||
+ 'desu:no-xpost': note.noXpost,
|
||||
...asPoll,
|
||||
};
|
||||
}
|
||||
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
|
||||
index 8edd8a1..4518b27 100644
|
||||
--- a/packages/backend/src/core/activitypub/type.ts
|
||||
+++ b/packages/backend/src/core/activitypub/type.ts
|
||||
@@ -122,6 +122,7 @@ export interface IPost extends IObject {
|
||||
quoteUrl?: string;
|
||||
quoteUri?: string;
|
||||
updated?: string;
|
||||
+ 'desu:no-xpost'?: boolean;
|
||||
}
|
||||
|
||||
export interface IQuestion extends IObject {
|
||||
diff --git a/packages/backend/src/models/Note.ts b/packages/backend/src/models/Note.ts
|
||||
index b11e2ec..8cf6787 100644
|
||||
--- a/packages/backend/src/models/Note.ts
|
||||
+++ b/packages/backend/src/models/Note.ts
|
||||
@@ -235,6 +235,11 @@ export class MiNote {
|
||||
comment: '[Denormalized]',
|
||||
})
|
||||
public renoteUserHost: string | null;
|
||||
+
|
||||
+ @Column('boolean', {
|
||||
+ default: false,
|
||||
+ })
|
||||
+ public noXpost: boolean;
|
||||
//#endregion
|
||||
|
||||
constructor(data: Partial<MiNote>) {
|
||||
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
|
||||
index 626f03b..451f2d8 100644
|
||||
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
|
||||
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
|
||||
@@ -155,6 +155,7 @@ export const paramDef = {
|
||||
noExtractMentions: { type: 'boolean', default: false },
|
||||
noExtractHashtags: { type: 'boolean', default: false },
|
||||
noExtractEmojis: { type: 'boolean', default: false },
|
||||
+ noXpost: { type: 'boolean', default: false },
|
||||
replyId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
renoteId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
channelId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
@@ -396,6 +397,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
apMentions: ps.noExtractMentions ? [] : undefined,
|
||||
apHashtags: ps.noExtractHashtags ? [] : undefined,
|
||||
apEmojis: ps.noExtractEmojis ? [] : undefined,
|
||||
+ noXpost: ps.noXpost,
|
||||
});
|
||||
|
||||
return {
|
||||
diff --git a/packages/backend/src/server/api/endpoints/notes/edit.ts b/packages/backend/src/server/api/endpoints/notes/edit.ts
|
||||
index 835cbc1..ee2c787 100644
|
||||
--- a/packages/backend/src/server/api/endpoints/notes/edit.ts
|
||||
+++ b/packages/backend/src/server/api/endpoints/notes/edit.ts
|
||||
@@ -203,6 +203,7 @@ export const paramDef = {
|
||||
noExtractMentions: { type: 'boolean', default: false },
|
||||
noExtractHashtags: { type: 'boolean', default: false },
|
||||
noExtractEmojis: { type: 'boolean', default: false },
|
||||
+ noXpost: { type: 'boolean', default: false },
|
||||
replyId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
renoteId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
channelId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
@@ -447,6 +448,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
apMentions: ps.noExtractMentions ? [] : undefined,
|
||||
apHashtags: ps.noExtractHashtags ? [] : undefined,
|
||||
apEmojis: ps.noExtractEmojis ? [] : undefined,
|
||||
+ noXpost: ps.noXpost,
|
||||
});
|
||||
|
||||
return {
|
||||
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
|
||||
index 57ed045..0d71611 100644
|
||||
--- a/packages/frontend/src/components/MkPostForm.vue
|
||||
+++ b/packages/frontend/src/components/MkPostForm.vue
|
||||
@@ -203,6 +203,7 @@ const recentHashtags = ref(JSON.parse(miLocalStorage.getItem('hashtags') ?? '[]'
|
||||
const imeText = ref('');
|
||||
const showingOptions = ref(false);
|
||||
const textAreaReadOnly = ref(false);
|
||||
+const noXpost = ref(false);
|
||||
|
||||
const draftKey = computed((): string => {
|
||||
let key = props.channel ? `channel:${props.channel.id}` : '';
|
||||
@@ -471,6 +472,7 @@ function setVisibility() {
|
||||
|
||||
os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
|
||||
currentVisibility: visibility.value,
|
||||
+ currentNoXpost: noXpost.value,
|
||||
isSilenced: $i.isSilenced,
|
||||
localOnly: localOnly.value,
|
||||
src: visibilityButton.value,
|
||||
@@ -482,6 +484,9 @@ function setVisibility() {
|
||||
defaultStore.set('visibility', visibility.value);
|
||||
}
|
||||
},
|
||||
+ changeNoXpost: v => {
|
||||
+ noXpost.value = v;
|
||||
+ },
|
||||
}, 'closed');
|
||||
}
|
||||
|
||||
@@ -810,6 +815,7 @@ async function post(ev?: MouseEvent) {
|
||||
visibleUserIds: visibility.value === 'specified' ? visibleUsers.value.map(u => u.id) : undefined,
|
||||
reactionAcceptance: reactionAcceptance.value,
|
||||
editId: props.editId ? props.editId : undefined,
|
||||
+ noXpost: noXpost.value,
|
||||
};
|
||||
|
||||
if (withHashtags.value && hashtags.value && hashtags.value.trim() !== '') {
|
||||
diff --git a/packages/frontend/src/components/MkVisibilityPicker.vue b/packages/frontend/src/components/MkVisibilityPicker.vue
|
||||
index e0aec8b..db25745 100644
|
||||
--- a/packages/frontend/src/components/MkVisibilityPicker.vue
|
||||
+++ b/packages/frontend/src/components/MkVisibilityPicker.vue
|
||||
@@ -37,6 +37,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<span :class="$style.itemDescription">{{ i18n.ts._visibility.specifiedDescription }}</span>
|
||||
</div>
|
||||
</button>
|
||||
+ <MkSwitch :modelValue="noXpost" @update:modelValue="noXpostChanged" :disabled="localOnly">
|
||||
+ do not cross-post
|
||||
+ </MkSwitch>
|
||||
</div>
|
||||
</MkModal>
|
||||
</template>
|
||||
@@ -45,12 +48,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
import { nextTick, shallowRef, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkModal from '@/components/MkModal.vue';
|
||||
+import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const modal = shallowRef<InstanceType<typeof MkModal>>();
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
currentVisibility: typeof Misskey.noteVisibilities[number];
|
||||
+ currentNoXpost: boolean;
|
||||
isSilenced: boolean;
|
||||
localOnly: boolean;
|
||||
src?: HTMLElement;
|
||||
@@ -60,10 +65,12 @@ const props = withDefaults(defineProps<{
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'changeVisibility', v: typeof Misskey.noteVisibilities[number]): void;
|
||||
+ (ev: 'changeNoXpost', v: boolean): void;
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const v = ref(props.currentVisibility);
|
||||
+const noXpost = ref(props.currentNoXpost)
|
||||
|
||||
function choose(visibility: typeof Misskey.noteVisibilities[number]): void {
|
||||
v.value = visibility;
|
||||
@@ -72,6 +79,11 @@ function choose(visibility: typeof Misskey.noteVisibilities[number]): void {
|
||||
if (modal.value) modal.value.close();
|
||||
});
|
||||
}
|
||||
+
|
||||
+function noXpostChanged(v: boolean): void {
|
||||
+ noXpost.value = v;
|
||||
+ emit('changeNoXpost', v);
|
||||
+}
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
|
@ -1,72 +0,0 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const LOCALES_DIR = '/sharkey/built/_frontend_dist_/locales'
|
||||
|
||||
const locales = fs.readdirSync(LOCALES_DIR)
|
||||
const enLocale = locales.find(locale => locale.startsWith('en-US.') && locale.endsWith('.json'))
|
||||
if (!enLocale) {
|
||||
throw new Error('en-US locale not found')
|
||||
}
|
||||
|
||||
function parseInterpolations(str) {
|
||||
const regex = /{([^}]+)}/g
|
||||
const matches = str.match(regex)
|
||||
if (!matches) {
|
||||
return { parts: [str], variables: [] }
|
||||
}
|
||||
|
||||
const parts = []
|
||||
const variables = []
|
||||
|
||||
let lastIndex = 0
|
||||
for (const match of matches) {
|
||||
const index = str.indexOf(match)
|
||||
const part = str.slice(lastIndex, index)
|
||||
parts.push(part)
|
||||
|
||||
const variable = match.slice(1, -1)
|
||||
variables.push(variable)
|
||||
|
||||
lastIndex = index + match.length
|
||||
}
|
||||
|
||||
const lastPart = str.slice(lastIndex)
|
||||
parts.push(lastPart)
|
||||
|
||||
return { parts, variables }
|
||||
}
|
||||
|
||||
function unparseInterpolations({ parts, variables }) {
|
||||
let str = parts[0]
|
||||
for (let i = 0; i < variables.length; i++) {
|
||||
str += `{${variables[i]}}${parts[i + 1]}`
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
const enLocaleFull = path.join(LOCALES_DIR, enLocale)
|
||||
const json = JSON.parse(fs.readFileSync(enLocaleFull, 'utf8'))
|
||||
|
||||
// recursively make every string lowercase
|
||||
function patchObject(obj) {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (typeof value === 'object') {
|
||||
patchObject(value)
|
||||
continue
|
||||
}
|
||||
|
||||
if (typeof value !== 'string') {
|
||||
continue
|
||||
}
|
||||
|
||||
const { parts, variables } = parseInterpolations(value)
|
||||
const lowercasedParts = parts.map(part => part.toLowerCase())
|
||||
const newValue = unparseInterpolations({ parts: lowercasedParts, variables })
|
||||
obj[key] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
patchObject(json)
|
||||
|
||||
fs.writeFileSync(enLocaleFull, JSON.stringify(json, null))
|
|
@ -1,37 +0,0 @@
|
|||
user-agent: *
|
||||
disallow: /
|
||||
|
||||
# explicit disallows because some bots are assholes that need that
|
||||
|
||||
User-Agent: Googlebot
|
||||
Disallow: /
|
||||
|
||||
User-Agent: Storebot-Google
|
||||
Disallow: /
|
||||
|
||||
User-Agent: GoogleOther
|
||||
Disallow: /
|
||||
|
||||
User-Agent: Google-Extended
|
||||
Disallow: /
|
||||
|
||||
User-agent: CCBot
|
||||
Disallow: /
|
||||
|
||||
User-agent: ChatGPT-User
|
||||
Disallow: /
|
||||
|
||||
User-agent: GPTBot
|
||||
Disallow: /
|
||||
|
||||
User-agent: Google-Extended
|
||||
Disallow: /
|
||||
|
||||
User-agent: Omgilibot
|
||||
Disallow: /
|
||||
|
||||
User-Agent: FacebookBot
|
||||
Disallow: /
|
||||
|
||||
User-agent: Amazonbot
|
||||
Disallow: /
|
|
@ -1,12 +0,0 @@
|
|||
--- a/packages/backend/src/server/NodeinfoServerService.ts
|
||||
+++ b/packages/backend/src/server/NodeinfoServerService.ts
|
||||
@@ -76,7 +76,7 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const document: any = {
|
||||
software: {
|
||||
- name: 'sharkey',
|
||||
+ name: 'fishkey',
|
||||
version: this.config.version,
|
||||
homepage: nodeinfo_homepage,
|
||||
repository: meta.repositoryUrl,
|
||||
},
|
|
@ -1,29 +0,0 @@
|
|||
--- a/packages/backend/src/server/api/endpoints/stats.ts
|
||||
+++ b/packages/backend/src/server/api/endpoints/stats.ts
|
||||
@@ -75,9 +75,9 @@
|
||||
const originalNotesCount = notesChart.local.total[0];
|
||||
|
||||
const usersChart = await this.usersChart.getChart('hour', 1, null);
|
||||
- const usersCount = usersChart.local.total[0] + usersChart.remote.total[0];
|
||||
- const originalUsersCount = usersChart.local.total[0];
|
||||
+ const usersCount = 1 + usersChart.remote.total[0];
|
||||
+ const originalUsersCount = 1;
|
||||
|
||||
const [
|
||||
reactionsCount,
|
||||
//originalReactionsCount,
|
||||
|
||||
--- a/packages/backend/src/server/NodeinfoServerService.ts
|
||||
+++ b/packages/backend/src/server/NodeinfoServerService.ts
|
||||
@@ -50,10 +50,9 @@
|
||||
const now = Date.now();
|
||||
|
||||
const notesChart = await this.notesChart.getChart('hour', 1, null);
|
||||
const localPosts = notesChart.local.total[0];
|
||||
|
||||
- const usersChart = await this.usersChart.getChart('hour', 1, null);
|
||||
- const total = usersChart.local.total[0];
|
||||
+ const total = 1;
|
||||
|
||||
const [
|
||||
meta,
|
|
@ -1,64 +0,0 @@
|
|||
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
|
||||
index deeecde..2770ecb 100644
|
||||
--- a/packages/backend/src/core/UserFollowingService.ts
|
||||
+++ b/packages/backend/src/core/UserFollowingService.ts
|
||||
@@ -388,6 +388,7 @@ export class UserFollowingService implements OnModuleInit {
|
||||
this.cacheService.userFollowingsCache.refresh(follower.id);
|
||||
|
||||
this.decrementFollowing(following.follower, following.followee);
|
||||
+ this.notificationService.createNotification(followee.id, 'unfollow', {}, follower.id);
|
||||
|
||||
if (!silent && this.userEntityService.isLocalUser(follower)) {
|
||||
// Publish unfollow event
|
||||
diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts
|
||||
index 4ed71a1..0bbd0ca 100644
|
||||
--- a/packages/backend/src/models/Notification.ts
|
||||
+++ b/packages/backend/src/models/Notification.ts
|
||||
@@ -15,7 +15,7 @@ export type MiNotification = {
|
||||
notifierId: MiUser['id'];
|
||||
noteId: MiNote['id'];
|
||||
} | {
|
||||
- type: 'follow';
|
||||
+ type: 'follow' | 'unfollow';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
notifierId: MiUser['id'];
|
||||
diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue
|
||||
index f849e94..9ba8351 100644
|
||||
--- a/packages/frontend/src/components/MkNotification.vue
|
||||
+++ b/packages/frontend/src/components/MkNotification.vue
|
||||
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<img v-else-if="notification.icon" :class="[$style.icon, $style.icon_app]" :src="notification.icon" alt=""/>
|
||||
<div
|
||||
:class="[$style.subIcon, {
|
||||
- [$style.t_follow]: notification.type === 'follow',
|
||||
+ [$style.t_follow]: notification.type === 'follow' || notification.type === 'unfollow',
|
||||
[$style.t_followRequestAccepted]: notification.type === 'followRequestAccepted',
|
||||
[$style.t_receiveFollowRequest]: notification.type === 'receiveFollowRequest',
|
||||
[$style.t_renote]: notification.type === 'renote',
|
||||
@@ -30,6 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
}]"
|
||||
> <!-- we re-use t_pollEnded for "edited" instead of making an identical style -->
|
||||
<i v-if="notification.type === 'follow'" class="ti ti-plus"></i>
|
||||
+ <i v-else-if="notification.type === 'unfollow'" class="ti ti-minus"></i>
|
||||
<i v-else-if="notification.type === 'receiveFollowRequest'" class="ti ti-clock"></i>
|
||||
<i v-else-if="notification.type === 'followRequestAccepted'" class="ti ti-check"></i>
|
||||
<i v-else-if="notification.type === 'renote'" class="ti ti-repeat"></i>
|
||||
@@ -61,6 +62,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<span v-else-if="notification.type === 'achievementEarned'">{{ i18n.ts._notification.achievementEarned }}</span>
|
||||
<span v-else-if="notification.type === 'test'">{{ i18n.ts._notification.testNotification }}</span>
|
||||
<MkA v-else-if="notification.type === 'follow' || notification.type === 'mention' || notification.type === 'reply' || notification.type === 'renote' || notification.type === 'quote' || notification.type === 'reaction' || notification.type === 'receiveFollowRequest' || notification.type === 'followRequestAccepted'" v-user-preview="notification.user.id" :class="$style.headerName" :to="userPage(notification.user)"><MkUserName :user="notification.user"/></MkA>
|
||||
+ <MkA v-else-if="notification.type === 'unfollow'" v-user-preview="notification.user.id" :class="$style.headerName" :to="userPage(notification.user)"><MkUserName :user="notification.user"/></MkA>
|
||||
<span v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'">{{ i18n.tsx._notification.likedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }}</span>
|
||||
<span v-else-if="notification.type === 'reaction:grouped'">{{ i18n.tsx._notification.reactedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }}</span>
|
||||
<span v-else-if="notification.type === 'renote:grouped'">{{ i18n.tsx._notification.renotedBySomeUsers({ n: notification.users.length }) }}</span>
|
||||
@@ -105,6 +107,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<template v-else-if="notification.type === 'follow'">
|
||||
<span :class="$style.text" style="opacity: 0.6;">{{ i18n.ts.youGotNewFollower }}</span>
|
||||
</template>
|
||||
+ <template v-else-if="notification.type === 'unfollow'">
|
||||
+ <span :class="$style.text" style="opacity: 0.6;">unfollowed you</span>
|
||||
+ </template>
|
||||
<span v-else-if="notification.type === 'followRequestAccepted'" :class="$style.text" style="opacity: 0.6;">{{ i18n.ts.followRequestAccepted }}</span>
|
||||
<template v-else-if="notification.type === 'receiveFollowRequest'">
|
||||
<span :class="$style.text" style="opacity: 0.6;">{{ i18n.ts.receiveFollowRequest }}</span>
|
|
@ -1,105 +0,0 @@
|
|||
diff --git a/packages/backend/src/core/NotificationService.ts b/packages/backend/src/core/NotificationService.ts
|
||||
index 68ad92f..69b04c1 100644
|
||||
--- a/packages/backend/src/core/NotificationService.ts
|
||||
+++ b/packages/backend/src/core/NotificationService.ts
|
||||
@@ -21,6 +21,8 @@ import type { Config } from '@/config.js';
|
||||
import { UserListService } from '@/core/UserListService.js';
|
||||
import type { FilterUnionByProperty } from '@/types.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
+import { WebhookService } from './WebhookService.js';
|
||||
+import { QueueService } from './QueueService.js';
|
||||
|
||||
@Injectable()
|
||||
export class NotificationService implements OnApplicationShutdown {
|
||||
@@ -42,6 +44,8 @@ export class NotificationService implements OnApplicationShutdown {
|
||||
private pushNotificationService: PushNotificationService,
|
||||
private cacheService: CacheService,
|
||||
private userListService: UserListService,
|
||||
+ private webhookService: WebhookService,
|
||||
+ private queueService: QueueService,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -175,6 +179,13 @@ export class NotificationService implements OnApplicationShutdown {
|
||||
const latestReadNotificationId = await this.redisClient.get(`latestReadNotification:${notifieeId}`);
|
||||
if (latestReadNotificationId && (latestReadNotificationId >= (await redisIdPromise)!)) return;
|
||||
|
||||
+ const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === notifieeId && x.on.includes('notification'));
|
||||
+ for (const webhook of webhooks) {
|
||||
+ this.queueService.webhookDeliver(webhook, 'notification', {
|
||||
+ notification: packed
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
this.globalEventService.publishMainStream(notifieeId, 'unreadNotification', packed);
|
||||
this.pushNotificationService.pushNotification(notifieeId, 'notification', packed);
|
||||
|
||||
diff --git a/packages/backend/src/models/Webhook.ts b/packages/backend/src/models/Webhook.ts
|
||||
index 2a727f8..c4d490e 100644
|
||||
--- a/packages/backend/src/models/Webhook.ts
|
||||
+++ b/packages/backend/src/models/Webhook.ts
|
||||
@@ -7,7 +7,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typ
|
||||
import { id } from './util/id.js';
|
||||
import { MiUser } from './User.js';
|
||||
|
||||
-export const webhookEventTypes = ['mention', 'unfollow', 'follow', 'followed', 'note', 'reply', 'renote', 'reaction', 'edited'] as const;
|
||||
+export const webhookEventTypes = ['mention', 'unfollow', 'follow', 'followed', 'note', 'reply', 'renote', 'reaction', 'edited', 'notification'] as const;
|
||||
|
||||
@Entity('webhook')
|
||||
export class MiWebhook {
|
||||
diff --git a/packages/frontend/src/pages/settings/webhook.edit.vue b/packages/frontend/src/pages/settings/webhook.edit.vue
|
||||
index 99326c8..fbfabc4 100644
|
||||
--- a/packages/frontend/src/pages/settings/webhook.edit.vue
|
||||
+++ b/packages/frontend/src/pages/settings/webhook.edit.vue
|
||||
@@ -29,6 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<MkSwitch v-model="event_renote">{{ i18n.ts._webhookSettings._events.renote }}</MkSwitch>
|
||||
<MkSwitch v-model="event_reaction">{{ i18n.ts._webhookSettings._events.reaction }}</MkSwitch>
|
||||
<MkSwitch v-model="event_mention">{{ i18n.ts._webhookSettings._events.mention }}</MkSwitch>
|
||||
+ <MkSwitch v-model="event_notification">on notification</MkSwitch>
|
||||
</div>
|
||||
</FormSection>
|
||||
|
||||
@@ -75,6 +76,7 @@ const event_reply = ref(webhook.on.includes('reply'));
|
||||
const event_renote = ref(webhook.on.includes('renote'));
|
||||
const event_reaction = ref(webhook.on.includes('reaction'));
|
||||
const event_mention = ref(webhook.on.includes('mention'));
|
||||
+const event_notification = ref(webhook.on.includes('notification'));
|
||||
|
||||
async function save(): Promise<void> {
|
||||
const events = [];
|
||||
@@ -85,6 +87,7 @@ async function save(): Promise<void> {
|
||||
if (event_renote.value) events.push('renote');
|
||||
if (event_reaction.value) events.push('reaction');
|
||||
if (event_mention.value) events.push('mention');
|
||||
+ if (event_notification.value) events.push('notification');
|
||||
|
||||
os.apiWithDialog('i/webhooks/update', {
|
||||
name: name.value,
|
||||
diff --git a/packages/frontend/src/pages/settings/webhook.new.vue b/packages/frontend/src/pages/settings/webhook.new.vue
|
||||
index 2993863..c2db510 100644
|
||||
--- a/packages/frontend/src/pages/settings/webhook.new.vue
|
||||
+++ b/packages/frontend/src/pages/settings/webhook.new.vue
|
||||
@@ -29,6 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<MkSwitch v-model="event_renote">{{ i18n.ts._webhookSettings._events.renote }}</MkSwitch>
|
||||
<MkSwitch v-model="event_reaction">{{ i18n.ts._webhookSettings._events.reaction }}</MkSwitch>
|
||||
<MkSwitch v-model="event_mention">{{ i18n.ts._webhookSettings._events.mention }}</MkSwitch>
|
||||
+ <MkSwitch v-model="event_notification">on notification</MkSwitch>
|
||||
</div>
|
||||
</FormSection>
|
||||
|
||||
@@ -59,6 +60,7 @@ const event_reply = ref(true);
|
||||
const event_renote = ref(true);
|
||||
const event_reaction = ref(true);
|
||||
const event_mention = ref(true);
|
||||
+const event_notification = ref(true);
|
||||
|
||||
async function create(): Promise<void> {
|
||||
const events = [];
|
||||
@@ -69,6 +71,7 @@ async function create(): Promise<void> {
|
||||
if (event_renote.value) events.push('renote');
|
||||
if (event_reaction.value) events.push('reaction');
|
||||
if (event_mention.value) events.push('mention');
|
||||
+ if (event_notification.value) events.push('notification');
|
||||
|
||||
os.apiWithDialog('i/webhooks/create', {
|
||||
name: name.value,
|
|
@ -1,9 +0,0 @@
|
|||
--- a/packages/backend/src/server/web/views/base.pug
|
||||
+++ b/packages/backend/src/server/web/views/base.pug
|
||||
@@ -44,5 +44,6 @@
|
||||
link(rel='stylesheet' href=`/static-assets/fonts/sharkey-icons/style.css?version=${version}`)
|
||||
link(rel='modulepreload' href=`/vite/${clientEntry.file}`)
|
||||
+ script(src='https://zond.tei.su/script.js' data-website-id="9629ae3b-b086-4be1-acd2-82e2a4a58c2a")
|
||||
|
||||
if !config.clientManifestExists
|
||||
script(type="module" src="/vite/@vite/client")
|
|
@ -8,7 +8,6 @@ let
|
|||
10.42.0.2 torrent.stupid.fish
|
||||
10.42.0.2 koi.stupid.fish
|
||||
10.42.0.2 hass.stupid.fish
|
||||
10.42.0.2 very.stupid.fish
|
||||
10.42.0.8 bnuuy.stupid.fish
|
||||
10.42.0.2 puffer.stupid.fish
|
||||
10.42.0.2 puffer-webdav.stupid.fish
|
||||
|
|
Loading…
Reference in a new issue