feat(koi): bumped sharkey + added no-xpost extension
This commit is contained in:
parent
a6a2482aac
commit
710fda269a
4 changed files with 250 additions and 7 deletions
|
@ -1,6 +1,6 @@
|
|||
# based on https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/Dockerfile
|
||||
ARG NODE_VERSION=20.12.2-alpine3.19
|
||||
ARG COMMIT=717696c4728d2e507ddfbd0e4890189758ab1087
|
||||
ARG COMMIT=c344705d6708fdc725d6122d2b321cb2d01dad4b
|
||||
|
||||
FROM node:${NODE_VERSION} as build
|
||||
|
||||
|
@ -38,6 +38,7 @@ 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
|
||||
|
||||
|
|
242
hosts/koi/containers/sharkey/patches/no-xpost-extension.patch
Normal file
242
hosts/koi/containers/sharkey/patches/no-xpost-extension.patch
Normal file
|
@ -0,0 +1,242 @@
|
|||
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>
|
|
@ -39,11 +39,11 @@ index f849e94..9ba8351 100644
|
|||
@@ -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="ph-plus ph-bold ph-lg"></i>
|
||||
+ <i v-else-if="notification.type === 'unfollow'" class="ph-minus ph-bold ph-lg"></i>
|
||||
<i v-else-if="notification.type === 'receiveFollowRequest'" class="ph-clock ph-bold ph-lg"></i>
|
||||
<i v-else-if="notification.type === 'followRequestAccepted'" class="ph-check ph-bold ph-lg"></i>
|
||||
<i v-else-if="notification.type === 'renote'" class="ph-rocket-launch ph-bold ph-lg"></i>
|
||||
<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>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--- 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')
|
||||
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")
|
||||
|
||||
|
|
Loading…
Reference in a new issue