Skip to content

Commit

Permalink
編集の受信 (#2486)
Browse files Browse the repository at this point in the history
  • Loading branch information
mei23 authored Sep 30, 2023
1 parent c7eed9a commit f57c2fa
Show file tree
Hide file tree
Showing 12 changed files with 125 additions and 5 deletions.
16 changes: 16 additions & 0 deletions migration/1696051309107-note-updatedAt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {MigrationInterface, QueryRunner} from "typeorm";

export class noteUpdatedAt1696051309107 implements MigrationInterface {
name = 'noteUpdatedAt1696051309107'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "note" ADD "updatedAt" TIMESTAMP WITH TIME ZONE`);
await queryRunner.query(`COMMENT ON COLUMN "note"."updatedAt" IS 'The updated date of the Note.'`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`COMMENT ON COLUMN "note"."updatedAt" IS 'The updated date of the Note.'`);
await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "updatedAt"`);
}

}
7 changes: 7 additions & 0 deletions src/client/app/common/scripts/note-subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ export default prop => ({
this.$_ns_target.cw = null;
break;
}

case 'updated': {
Vue.set(this.$_ns_target, 'updatedAt', body.updatedAt);
Vue.set(this.$_ns_target, 'text', body.text);
Vue.set(this.$_ns_target, 'cw', body.cw);
break;
}
}
},
}
Expand Down
11 changes: 10 additions & 1 deletion src/client/app/common/views/components/note-header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<span class="mobile" v-if="note.viaMobile"><fa icon="mobile-alt"/></span>
<router-link class="created-at" :to="note | notePage">
<mk-time :time="note.createdAt"/>
{{ }}
<span :title="$t('@.edited')" v-if="note.updatedAt != null"><fa :icon="faEdit"/></span>
</router-link>
<span class="visibility" v-if="note.visibility != 'public'">
<fa v-if="note.visibility == 'home'" icon="home"/>
Expand All @@ -27,6 +29,7 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../../../i18n';
import { faEdit } from '@fortawesome/free-solid-svg-icons';
export default Vue.extend({
i18n: i18n(),
Expand All @@ -40,7 +43,13 @@ export default Vue.extend({
required: false,
default: false
}
}
},
data() {
return {
faEdit,
}
},
});
</script>

Expand Down
2 changes: 1 addition & 1 deletion src/client/app/common/views/deck/deck.notes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<template v-for="(note, i) in _notes">
<mk-note
:note="note"
:key="note.id"
:key="`${note.id}-${note.updatedAt}`"
:compact="true"
/>
<p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date">
Expand Down
4 changes: 4 additions & 0 deletions src/client/app/desktop/views/components/note-detail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
<div class="info">
<router-link class="time" :to="appearNote | notePage">
<mk-time :time="appearNote.createdAt"/>
{{ }}
<fa v-if="appearNote.updatedAt != null" :icon="faEdit"/>
</router-link>
<div class="visibility-info">
<span class="visibility" v-if="appearNote.visibility != 'public'">
Expand Down Expand Up @@ -98,6 +100,7 @@ import i18n from '../../../i18n';
import XSub from './note.sub.vue';
import noteSubscriber from '../../../common/scripts/note-subscriber';
import noteMixin from '../../../common/scripts/note-mixin';
import { faEdit } from '@fortawesome/free-solid-svg-icons';
export default Vue.extend({
i18n: i18n('desktop/views/components/note-detail.vue'),
Expand All @@ -120,6 +123,7 @@ export default Vue.extend({
data() {
return {
faEdit,
conversation: [],
conversationFetching: false,
replies: []
Expand Down
2 changes: 1 addition & 1 deletion src/client/app/desktop/views/components/notes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<!-- トランジションを有効にするとなぜかメモリリークする -->
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notes" class="notes transition" tag="div" ref="notes">
<template v-for="(note, i) in _notes">
<mk-note :note="note" :key="note.id" :compact="true" ref="note"/>
<mk-note :note="note" :key="`${note.id}-${note.updatedAt}`" :compact="true" ref="note"/>
<p class="date" :key="note.id + '_date'" v-if="i != items.length - 1 && note._date != _notes[i + 1]._date">
<span><fa icon="angle-up"/>{{ note._datetext }}</span>
<span><fa icon="angle-down"/>{{ _notes[i + 1]._datetext }}</span>
Expand Down
7 changes: 7 additions & 0 deletions src/client/app/mobile/views/components/note-detail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
<router-link class="time" :to="appearNote | notePage">
<mk-time :time="appearNote.createdAt" mode="detail"/>
</router-link>
<div class="time" v-if="appearNote.updatedAt != null">
<fa :icon="faEdit"/>
{{ }}
<mk-time :time="appearNote.updatedAt" mode="detail"/>
</div>
<div class="visibility-info">
<span class="visibility" v-if="appearNote.visibility != 'public'">
<fa v-if="appearNote.visibility == 'home'" icon="home"/>
Expand Down Expand Up @@ -94,6 +99,7 @@ import i18n from '../../../i18n';
import XSub from './note.sub.vue';
import noteSubscriber from '../../../common/scripts/note-subscriber';
import noteMixin from '../../../common/scripts/note-mixin';
import { faEdit } from '@fortawesome/free-solid-svg-icons';
export default Vue.extend({
i18n: i18n('mobile/views/components/note-detail.vue'),
Expand All @@ -116,6 +122,7 @@ export default Vue.extend({
data() {
return {
faEdit,
conversation: [],
conversationFetching: false,
replies: []
Expand Down
2 changes: 1 addition & 1 deletion src/client/app/mobile/views/components/notes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<!-- トランジションを有効にするとなぜかメモリリークする -->
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notes" class="transition" tag="div">
<template v-for="(note, i) in _notes">
<mk-note :note="note" :key="note.id"/>
<mk-note :note="note" :key="`${note.id}-${note.updatedAt}`"/>
<p class="date" :key="note.id + '_date'" v-if="i != items.length - 1 && note._date != _notes[i + 1]._date">
<span><fa icon="angle-up"/>{{ note._datetext }}</span>
<span><fa icon="angle-down"/>{{ _notes[i + 1]._datetext }}</span>
Expand Down
6 changes: 6 additions & 0 deletions src/models/entities/note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export class Note {
})
public createdAt: Date;

@Column('timestamp with time zone', {
nullable: true,
comment: 'The updated date of the Note.'
})
public updatedAt: Date | null;

@Index()
@Column({
...id(),
Expand Down
1 change: 1 addition & 0 deletions src/models/repositories/note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export class NoteRepository extends Repository<Note> {
const packed = await awaitAll({
id: note.id,
createdAt: note.createdAt.toISOString(),
updatedAt: note.updatedAt?.toISOString(),
app: note.appId ? Apps.pack(note.appId) : undefined,
userId: note.userId,
user: Users.pack(note.user || note.userId, meId),
Expand Down
5 changes: 4 additions & 1 deletion src/remote/activitypub/kernel/update/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { IRemoteUser } from '../../../../models/entities/user';
import { getApType, IUpdate, isActor } from '../../type';
import { getApType, IUpdate, isActor, isPost } from '../../type';
import { apLogger } from '../../logger';
import { updateQuestion } from '../../models/question';
import Resolver from '../../resolver';
import { updatePerson } from '../../models/person';
import updateNote from './note';

/**
* Updateアクティビティを捌きます
Expand All @@ -28,6 +29,8 @@ export default async (actor: IRemoteUser, activity: IUpdate): Promise<string> =>
} else if (getApType(object) === 'Question') {
await updateQuestion(object, resolver).catch(e => console.log(e));
return `ok: Question updated`;
} else if (isPost(object)) {
return await updateNote(actor, object);
} else {
return `skip: Unknown type: ${getApType(object)}`;
}
Expand Down
67 changes: 67 additions & 0 deletions src/remote/activitypub/kernel/update/note.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { getApLock } from "../../../../misc/app-lock";
import { extractDbHost } from "../../../../misc/convert-host";
import { Notes } from "../../../../models";
import { IRemoteUser } from "../../../../models/entities/user";
import { publishNoteStream } from "../../../../services/stream";
import DbResolver from "../../db-resolver";
import { apLogger } from "../../logger";
import { htmlToMfm } from "../../misc/html-to-mfm";
import { IPost, getApId } from "../../type";

const logger = apLogger;

export default async function(actor: IRemoteUser, note: IPost): Promise<string> {
if (typeof note.id !== 'string') return 'skip';

// Note.attributedToは署名と同じである必要がある
if (actor.uri !== note.attributedTo) {
return `skip: actor.uri !== note.attributedTo`;
}


// Note.idのホストは署名と同一である必要がある
if (extractDbHost(note.id) !== extractDbHost(actor.uri)) {
return `skip: host in actor.uri !== host in note.id`;
}

const uri = getApId(note);

logger.info(`Update the Note: ${uri}`);

const unlock = await getApLock(uri);

try {
const dbResolver = new DbResolver();

// 元ノート照合
const origin = await dbResolver.getNoteFromApId(uri);
if (!origin) return 'skip: old note is not found';

// 同じユーザーである必要がある
if (!(origin.userId === actor.id)) {
return '投稿をUpdateしようとしているユーザーは投稿の作成者ではありません';
}

// validateはinboxのハードリミットでいい

// テキストのパース
const text = note._misskey_content || (note.content ? htmlToMfm(note.content, note.tag) : null);
const cw = note.summary === '' ? null : note.summary;

// Update
const updates = {
updatedAt: new Date(),
text: text?.trim(),
cw: cw ?? null,
};

await Notes.update({ id: origin.id }, updates);

// Publish to streaming
publishNoteStream(origin.id, 'updated', updates);

return 'ok';
} finally {
unlock();
}
}

0 comments on commit f57c2fa

Please sign in to comment.