summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2020-02-15 01:03:59 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2020-02-15 01:03:59 +0900
commit65c0b6c7da1a16c2c81d19800d9aea7b7dfae4b9 (patch)
tree7e16caf5d7e09b0a6486be2e6e961f6d0bd4b456
parentImprove doc page (diff)
downloadmisskey-65c0b6c7da1a16c2c81d19800d9aea7b7dfae4b9.tar.gz
misskey-65c0b6c7da1a16c2c81d19800d9aea7b7dfae4b9.tar.bz2
misskey-65c0b6c7da1a16c2c81d19800d9aea7b7dfae4b9.zip
Resolve #5939
Diffstat (limited to '')
-rw-r--r--CHANGELOG.md1
-rw-r--r--locales/ja-JP.yml1
-rw-r--r--migration/1581695816408-user-group-antenna.ts28
-rw-r--r--src/client/pages/my-antennas/index.antenna.vue19
-rw-r--r--src/client/pages/my-antennas/index.vue1
-rw-r--r--src/misc/check-hit-antenna.ts11
-rw-r--r--src/models/entities/antenna.ts17
-rw-r--r--src/models/repositories/antenna.ts4
-rw-r--r--src/server/api/endpoints/antennas/create.ts25
-rw-r--r--src/server/api/endpoints/antennas/update.ts25
10 files changed, 123 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89378f61e1..5e81b43d3b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@ ChangeLog
unreleased
-------------------
### ✨Improvements
+* アンテナの受信ソースにグループを指定できるように
* 時計ウィジェットを追加
### 🐛Fixes
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 1751bc9f8f..f883e72632 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -487,6 +487,7 @@ _antennaSources:
homeTimeline: "フォローしているユーザーのノート"
users: "指定した一人または複数のユーザーのノート"
userList: "指定したリストのユーザーのノート"
+ userGroup: "指定したグループのユーザーのノート"
_weekday:
sunday: "日曜日"
diff --git a/migration/1581695816408-user-group-antenna.ts b/migration/1581695816408-user-group-antenna.ts
new file mode 100644
index 0000000000..15eb2fe11b
--- /dev/null
+++ b/migration/1581695816408-user-group-antenna.ts
@@ -0,0 +1,28 @@
+import {MigrationInterface, QueryRunner} from "typeorm";
+
+export class userGroupAntenna1581695816408 implements MigrationInterface {
+ name = 'userGroupAntenna1581695816408'
+
+ public async up(queryRunner: QueryRunner): Promise<any> {
+ await queryRunner.query(`ALTER TABLE "antenna" ADD "userGroupJoiningId" character varying(32)`, undefined);
+ await queryRunner.query(`ALTER TYPE "public"."antenna_src_enum" RENAME TO "antenna_src_enum_old"`, undefined);
+ await queryRunner.query(`CREATE TYPE "antenna_src_enum" AS ENUM('home', 'all', 'users', 'list', 'group')`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "src" TYPE "antenna_src_enum" USING "src"::"text"::"antenna_src_enum"`, undefined);
+ await queryRunner.query(`DROP TYPE "antenna_src_enum_old"`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "users"`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" ADD "users" character varying(1024) array NOT NULL DEFAULT '{}'::varchar[]`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" ADD CONSTRAINT "FK_ccbf5a8c0be4511133dcc50ddeb" FOREIGN KEY ("userGroupJoiningId") REFERENCES "user_group_joining"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<any> {
+ await queryRunner.query(`ALTER TABLE "antenna" DROP CONSTRAINT "FK_ccbf5a8c0be4511133dcc50ddeb"`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "users"`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" ADD "users" character varying array NOT NULL DEFAULT '{}'`, undefined);
+ await queryRunner.query(`CREATE TYPE "antenna_src_enum_old" AS ENUM('home', 'all', 'users', 'list')`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "src" TYPE "antenna_src_enum_old" USING "src"::"text"::"antenna_src_enum_old"`, undefined);
+ await queryRunner.query(`DROP TYPE "antenna_src_enum"`, undefined);
+ await queryRunner.query(`ALTER TYPE "antenna_src_enum_old" RENAME TO "antenna_src_enum"`, undefined);
+ await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "userGroupJoiningId"`, undefined);
+ }
+
+}
diff --git a/src/client/pages/my-antennas/index.antenna.vue b/src/client/pages/my-antennas/index.antenna.vue
index 7ee916a1c0..d0259a55c6 100644
--- a/src/client/pages/my-antennas/index.antenna.vue
+++ b/src/client/pages/my-antennas/index.antenna.vue
@@ -11,12 +11,17 @@
<option value="home">{{ $t('_antennaSources.homeTimeline') }}</option>
<option value="users">{{ $t('_antennaSources.users') }}</option>
<option value="list">{{ $t('_antennaSources.userList') }}</option>
+ <option value="group">{{ $t('_antennaSources.userGroup') }}</option>
</mk-select>
<mk-select v-model="userListId" v-if="src === 'list'">
<template #label>{{ $t('userList') }}</template>
<option v-for="list in userLists" :value="list.id" :key="list.id">{{ list.name }}</option>
</mk-select>
- <mk-textarea v-model="users" v-if="src === 'users'">
+ <mk-select v-model="userGroupId" v-else-if="src === 'group'">
+ <template #label>{{ $t('userGroup') }}</template>
+ <option v-for="group in userGroups" :value="group.id" :key="group.id">{{ group.name }}</option>
+ </mk-select>
+ <mk-textarea v-model="users" v-else-if="src === 'users'">
<span>{{ $t('users') }}</span>
<template #desc>{{ $t('antennaUsersDescription') }} <button class="_textButton" @click="addUser">{{ $t('addUser') }}</button></template>
</mk-textarea>
@@ -67,6 +72,7 @@ export default Vue.extend({
name: '',
src: '',
userListId: null,
+ userGroupId: null,
users: '',
keywords: '',
caseSensitive: false,
@@ -74,6 +80,7 @@ export default Vue.extend({
withFile: false,
notify: false,
userLists: null,
+ userGroups: null,
faSave, faTrash
};
},
@@ -83,6 +90,13 @@ export default Vue.extend({
if (this.src === 'list' && this.userLists === null) {
this.userLists = await this.$root.api('users/lists/list');
}
+
+ if (this.src === 'group' && this.userGroups === null) {
+ const groups1 = await this.$root.api('users/groups/owned');
+ const groups2 = await this.$root.api('users/groups/joined');
+
+ this.userGroups = [...groups1, ...groups2];
+ }
}
},
@@ -90,6 +104,7 @@ export default Vue.extend({
this.name = this.antenna.name;
this.src = this.antenna.src;
this.userListId = this.antenna.userListId;
+ this.userGroupId = this.antenna.userGroupId;
this.users = this.antenna.users.join('\n');
this.keywords = this.antenna.keywords.map(x => x.join(' ')).join('\n');
this.caseSensitive = this.antenna.caseSensitive;
@@ -105,6 +120,7 @@ export default Vue.extend({
name: this.name,
src: this.src,
userListId: this.userListId,
+ userGroupId: this.userGroupId,
withReplies: this.withReplies,
withFile: this.withFile,
notify: this.notify,
@@ -119,6 +135,7 @@ export default Vue.extend({
name: this.name,
src: this.src,
userListId: this.userListId,
+ userGroupId: this.userGroupId,
withReplies: this.withReplies,
withFile: this.withFile,
notify: this.notify,
diff --git a/src/client/pages/my-antennas/index.vue b/src/client/pages/my-antennas/index.vue
index 0c70d63d5d..8ac70ac378 100644
--- a/src/client/pages/my-antennas/index.vue
+++ b/src/client/pages/my-antennas/index.vue
@@ -50,6 +50,7 @@ export default Vue.extend({
name: '',
src: 'all',
userListId: null,
+ userGroupId: null,
users: [],
keywords: [],
withReplies: false,
diff --git a/src/misc/check-hit-antenna.ts b/src/misc/check-hit-antenna.ts
index b527d34354..c229a07ebe 100644
--- a/src/misc/check-hit-antenna.ts
+++ b/src/misc/check-hit-antenna.ts
@@ -1,9 +1,10 @@
import { Antenna } from '../models/entities/antenna';
import { Note } from '../models/entities/note';
import { User } from '../models/entities/user';
-import { UserListJoinings } from '../models';
+import { UserListJoinings, UserGroupJoinings } from '../models';
import parseAcct from './acct/parse';
import { getFullApAccount } from './convert-host';
+import { ensure } from '../prelude/ensure';
export async function checkHitAntenna(antenna: Antenna, note: Note, noteUser: User, followers: User['id'][]): Promise<boolean> {
if (note.visibility === 'specified') return false;
@@ -22,6 +23,14 @@ export async function checkHitAntenna(antenna: Antenna, note: Note, noteUser: Us
})).map(x => x.userId);
if (!listUsers.includes(note.userId)) return false;
+ } else if (antenna.src === 'group') {
+ const joining = await UserGroupJoinings.findOne(antenna.userGroupJoiningId!).then(ensure);
+
+ const groupUsers = (await UserGroupJoinings.find({
+ userGroupId: joining.userGroupId
+ })).map(x => x.userId);
+
+ if (!groupUsers.includes(note.userId)) return false;
} else if (antenna.src === 'users') {
const accts = antenna.users.map(x => {
const { username, host } = parseAcct(x);
diff --git a/src/models/entities/antenna.ts b/src/models/entities/antenna.ts
index e9971c6c07..7c2027b6ec 100644
--- a/src/models/entities/antenna.ts
+++ b/src/models/entities/antenna.ts
@@ -2,6 +2,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typ
import { User } from './user';
import { id } from '../id';
import { UserList } from './user-list';
+import { UserGroupJoining } from './user-group-joining';
@Entity()
export class Antenna {
@@ -32,8 +33,8 @@ export class Antenna {
})
public name: string;
- @Column('enum', { enum: ['home', 'all', 'users', 'list'] })
- public src: 'home' | 'all' | 'users' | 'list';
+ @Column('enum', { enum: ['home', 'all', 'users', 'list', 'group'] })
+ public src: 'home' | 'all' | 'users' | 'list' | 'group';
@Column({
...id(),
@@ -47,6 +48,18 @@ export class Antenna {
@JoinColumn()
public userList: UserList | null;
+ @Column({
+ ...id(),
+ nullable: true
+ })
+ public userGroupJoiningId: UserGroupJoining['id'] | null;
+
+ @ManyToOne(type => UserGroupJoining, {
+ onDelete: 'CASCADE'
+ })
+ @JoinColumn()
+ public userGroupJoining: UserGroupJoining | null;
+
@Column('varchar', {
length: 1024, array: true,
default: '{}'
diff --git a/src/models/repositories/antenna.ts b/src/models/repositories/antenna.ts
index c47a7ea35c..9f8aa11347 100644
--- a/src/models/repositories/antenna.ts
+++ b/src/models/repositories/antenna.ts
@@ -2,7 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
import { Antenna } from '../entities/antenna';
import { ensure } from '../../prelude/ensure';
import { SchemaType } from '../../misc/schema';
-import { AntennaNotes } from '..';
+import { AntennaNotes, UserGroupJoinings } from '..';
export type PackedAntenna = SchemaType<typeof packedAntennaSchema>;
@@ -14,6 +14,7 @@ export class AntennaRepository extends Repository<Antenna> {
const antenna = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
const hasUnreadNote = (await AntennaNotes.findOne({ antennaId: antenna.id, read: false })) != null;
+ const userGroupJoining = antenna.userGroupJoiningId ? await UserGroupJoinings.findOne(antenna.userGroupJoiningId) : null;
return {
id: antenna.id,
@@ -22,6 +23,7 @@ export class AntennaRepository extends Repository<Antenna> {
keywords: antenna.keywords,
src: antenna.src,
userListId: antenna.userListId,
+ userGroupId: userGroupJoining ? userGroupJoining.userGroupId : null,
users: antenna.users,
caseSensitive: antenna.caseSensitive,
notify: antenna.notify,
diff --git a/src/server/api/endpoints/antennas/create.ts b/src/server/api/endpoints/antennas/create.ts
index 0e00eda1a4..26915c19b3 100644
--- a/src/server/api/endpoints/antennas/create.ts
+++ b/src/server/api/endpoints/antennas/create.ts
@@ -1,7 +1,7 @@
import $ from 'cafy';
import define from '../../define';
import { genId } from '../../../../misc/gen-id';
-import { Antennas, UserLists } from '../../../../models';
+import { Antennas, UserLists, UserGroupJoinings } from '../../../../models';
import { ID } from '../../../../misc/cafy-id';
import { ApiError } from '../../error';
@@ -18,13 +18,17 @@ export const meta = {
},
src: {
- validator: $.str.or(['home', 'all', 'users', 'list'])
+ validator: $.str.or(['home', 'all', 'users', 'list', 'group'])
},
userListId: {
validator: $.nullable.optional.type(ID),
},
+ userGroupId: {
+ validator: $.nullable.optional.type(ID),
+ },
+
keywords: {
validator: $.arr($.arr($.str))
},
@@ -55,12 +59,19 @@ export const meta = {
message: 'No such user list.',
code: 'NO_SUCH_USER_LIST',
id: '95063e93-a283-4b8b-9aa5-bcdb8df69a7f'
+ },
+
+ noSuchUserGroup: {
+ message: 'No such user group.',
+ code: 'NO_SUCH_USER_GROUP',
+ id: 'aa3c0b9a-8cae-47c0-92ac-202ce5906682'
}
}
};
export default define(meta, async (ps, user) => {
let userList;
+ let userGroupJoining;
if (ps.src === 'list') {
userList = await UserLists.findOne({
@@ -71,6 +82,15 @@ export default define(meta, async (ps, user) => {
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
+ } else if (ps.src === 'group') {
+ userGroupJoining = await UserGroupJoinings.findOne({
+ userGroupId: ps.userGroupId,
+ userId: user.id,
+ });
+
+ if (userGroupJoining == null) {
+ throw new ApiError(meta.errors.noSuchUserGroup);
+ }
}
const antenna = await Antennas.save({
@@ -80,6 +100,7 @@ export default define(meta, async (ps, user) => {
name: ps.name,
src: ps.src,
userListId: userList ? userList.id : null,
+ userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
keywords: ps.keywords,
users: ps.users,
caseSensitive: ps.caseSensitive,
diff --git a/src/server/api/endpoints/antennas/update.ts b/src/server/api/endpoints/antennas/update.ts
index 28875d0f08..b4e7168888 100644
--- a/src/server/api/endpoints/antennas/update.ts
+++ b/src/server/api/endpoints/antennas/update.ts
@@ -2,7 +2,7 @@ import $ from 'cafy';
import { ID } from '../../../../misc/cafy-id';
import define from '../../define';
import { ApiError } from '../../error';
-import { Antennas, UserLists } from '../../../../models';
+import { Antennas, UserLists, UserGroupJoinings } from '../../../../models';
export const meta = {
tags: ['antennas'],
@@ -21,13 +21,17 @@ export const meta = {
},
src: {
- validator: $.str.or(['home', 'all', 'users', 'list'])
+ validator: $.str.or(['home', 'all', 'users', 'list', 'group'])
},
userListId: {
validator: $.nullable.optional.type(ID),
},
+ userGroupId: {
+ validator: $.nullable.optional.type(ID),
+ },
+
keywords: {
validator: $.arr($.arr($.str))
},
@@ -64,6 +68,12 @@ export const meta = {
message: 'No such user list.',
code: 'NO_SUCH_USER_LIST',
id: '1c6b35c9-943e-48c2-81e4-2844989407f7'
+ },
+
+ noSuchUserGroup: {
+ message: 'No such user group.',
+ code: 'NO_SUCH_USER_GROUP',
+ id: '109ed789-b6eb-456e-b8a9-6059d567d385'
}
}
};
@@ -80,6 +90,7 @@ export default define(meta, async (ps, user) => {
}
let userList;
+ let userGroupJoining;
if (ps.src === 'list') {
userList = await UserLists.findOne({
@@ -90,12 +101,22 @@ export default define(meta, async (ps, user) => {
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
+ } else if (ps.src === 'group') {
+ userGroupJoining = await UserGroupJoinings.findOne({
+ userGroupId: ps.userGroupId,
+ userId: user.id,
+ });
+
+ if (userGroupJoining == null) {
+ throw new ApiError(meta.errors.noSuchUserGroup);
+ }
}
await Antennas.update(antenna.id, {
name: ps.name,
src: ps.src,
userListId: userList ? userList.id : null,
+ userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
keywords: ps.keywords,
users: ps.users,
caseSensitive: ps.caseSensitive,