Merge branch 'misskey-dev:develop' into limitserver
This commit is contained in:
commit
1a222693e3
|
|
@ -17,7 +17,7 @@
|
|||
- AiScript: `Mk:apiExternal`の送信先は連合中のサーバーに限定されるようになりました。
|
||||
|
||||
### General
|
||||
-
|
||||
- Feat: アンテナでローカルの投稿のみ収集できるようになりました
|
||||
|
||||
### Client
|
||||
- Enhance: TLの返信表示オプションを記憶するように
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class AntennaLocalOnly1697436246389 {
|
||||
name = 'AntennaLocalOnly1697436246389'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "antenna" ADD "localOnly" boolean NOT NULL DEFAULT false`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "localOnly"`);
|
||||
}
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ export class AccountMoveService {
|
|||
{ muteeId: dst.id, expiresAt: IsNull() },
|
||||
).then(mutings => mutings.map(muting => muting.muterId));
|
||||
|
||||
const newMutings: Map<string, { muterId: string; muteeId: string; createdAt: Date; expiresAt: Date | null; }> = new Map();
|
||||
const newMutings: Map<string, { muterId: string; muteeId: string; expiresAt: Date | null; }> = new Map();
|
||||
|
||||
// 重複しないようにIDを生成
|
||||
const genId = (): string => {
|
||||
|
|
@ -194,7 +194,6 @@ export class AccountMoveService {
|
|||
if (existingMutingsMuterUserIds.includes(muting.muterId)) continue; // skip if already muted indefinitely
|
||||
newMutings.set(genId(), {
|
||||
...muting,
|
||||
createdAt: new Date(),
|
||||
muteeId: dst.id,
|
||||
});
|
||||
}
|
||||
|
|
@ -228,7 +227,7 @@ export class AccountMoveService {
|
|||
},
|
||||
}).then(memberships => memberships.map(membership => membership.userListId));
|
||||
|
||||
const newMemberships: Map<string, { createdAt: Date; userId: string; userListId: string; userListUserId: string; }> = new Map();
|
||||
const newMemberships: Map<string, { userId: string; userListId: string; userListUserId: string; }> = new Map();
|
||||
|
||||
// 重複しないようにIDを生成
|
||||
const genId = (): string => {
|
||||
|
|
@ -241,7 +240,6 @@ export class AccountMoveService {
|
|||
for (const membership of oldMemberships) {
|
||||
if (existingUserListIds.includes(membership.userListId)) continue; // skip if dst exists in this user's list
|
||||
newMemberships.set(genId(), {
|
||||
createdAt: new Date(),
|
||||
userId: dst.id,
|
||||
userListId: membership.userListId,
|
||||
userListUserId: membership.userListUserId,
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ export class AntennaService implements OnApplicationShutdown {
|
|||
if (note.visibility === 'specified') return false;
|
||||
if (note.visibility === 'followers') return false;
|
||||
|
||||
if (antenna.localOnly && noteUser.host != null) return false;
|
||||
|
||||
if (!antenna.withReplies && note.replyId != null) return false;
|
||||
|
||||
if (antenna.src === 'home') {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export class AntennaEntityService {
|
|||
userListId: antenna.userListId,
|
||||
users: antenna.users,
|
||||
caseSensitive: antenna.caseSensitive,
|
||||
localOnly: antenna.localOnly,
|
||||
notify: antenna.notify,
|
||||
withReplies: antenna.withReplies,
|
||||
withFile: antenna.withFile,
|
||||
|
|
|
|||
|
|
@ -93,4 +93,9 @@ export class MiAntenna {
|
|||
default: true,
|
||||
})
|
||||
public isActive: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public localOnly: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,11 @@ export const packedAntennaSchema = {
|
|||
optional: false, nullable: false,
|
||||
default: false,
|
||||
},
|
||||
localOnly: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
default: false,
|
||||
},
|
||||
notify: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ export class ExportAntennasProcessorService {
|
|||
return this.utilityService.getFullApAccount(u.username, u.host); // acct
|
||||
}) : null,
|
||||
caseSensitive: antenna.caseSensitive,
|
||||
localOnly: antenna.localOnly,
|
||||
withReplies: antenna.withReplies,
|
||||
withFile: antenna.withFile,
|
||||
notify: antenna.notify,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ const validate = new Ajv().compile({
|
|||
type: 'string',
|
||||
} },
|
||||
caseSensitive: { type: 'boolean' },
|
||||
localOnly: { type: 'boolean' },
|
||||
withReplies: { type: 'boolean' },
|
||||
withFile: { type: 'boolean' },
|
||||
notify: { type: 'boolean' },
|
||||
|
|
@ -86,6 +87,7 @@ export class ImportAntennasProcessorService {
|
|||
excludeKeywords: antenna.excludeKeywords,
|
||||
users: (antenna.src === 'list' && antenna.userListAccts !== null ? antenna.userListAccts : antenna.users).filter(Boolean),
|
||||
caseSensitive: antenna.caseSensitive,
|
||||
localOnly: antenna.localOnly,
|
||||
withReplies: antenna.withReplies,
|
||||
withFile: antenna.withFile,
|
||||
notify: antenna.notify,
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
}
|
||||
|
||||
switch (ps.sort) {
|
||||
case '+createdAt': query.orderBy('ticket.createdAt', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('ticket.createdAt', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('ticket.id', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('ticket.id', 'ASC'); break;
|
||||
case '+usedAt': query.orderBy('ticket.usedAt', 'DESC', 'NULLS LAST'); break;
|
||||
case '-usedAt': query.orderBy('ticket.usedAt', 'ASC', 'NULLS FIRST'); break;
|
||||
default: query.orderBy('ticket.id', 'DESC'); break;
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
switch (ps.sort) {
|
||||
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
||||
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.id', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.id', 'ASC'); break;
|
||||
case '+updatedAt': query.orderBy('user.updatedAt', 'DESC', 'NULLS LAST'); break;
|
||||
case '-updatedAt': query.orderBy('user.updatedAt', 'ASC', 'NULLS FIRST'); break;
|
||||
case '+lastActiveDate': query.orderBy('user.lastActiveDate', 'DESC', 'NULLS LAST'); break;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ export const paramDef = {
|
|||
type: 'string',
|
||||
} },
|
||||
caseSensitive: { type: 'boolean' },
|
||||
localOnly: { type: 'boolean' },
|
||||
withReplies: { type: 'boolean' },
|
||||
withFile: { type: 'boolean' },
|
||||
notify: { type: 'boolean' },
|
||||
|
|
@ -122,6 +123,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
excludeKeywords: ps.excludeKeywords,
|
||||
users: ps.users,
|
||||
caseSensitive: ps.caseSensitive,
|
||||
localOnly: ps.localOnly,
|
||||
withReplies: ps.withReplies,
|
||||
withFile: ps.withFile,
|
||||
notify: ps.notify,
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ export const paramDef = {
|
|||
type: 'string',
|
||||
} },
|
||||
caseSensitive: { type: 'boolean' },
|
||||
localOnly: { type: 'boolean' },
|
||||
withReplies: { type: 'boolean' },
|
||||
withFile: { type: 'boolean' },
|
||||
notify: { type: 'boolean' },
|
||||
|
|
@ -116,6 +117,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
excludeKeywords: ps.excludeKeywords,
|
||||
users: ps.users,
|
||||
caseSensitive: ps.caseSensitive,
|
||||
localOnly: ps.localOnly,
|
||||
withReplies: ps.withReplies,
|
||||
withFile: ps.withFile,
|
||||
notify: ps.notify,
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
}
|
||||
|
||||
switch (ps.sort) {
|
||||
case '+createdAt': query.orderBy('file.createdAt', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('file.createdAt', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('file.id', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('file.id', 'ASC'); break;
|
||||
case '+name': query.orderBy('file.name', 'DESC'); break;
|
||||
case '-name': query.orderBy('file.name', 'ASC'); break;
|
||||
case '+size': query.orderBy('file.size', 'DESC'); break;
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
switch (ps.sort) {
|
||||
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
||||
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.id', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.id', 'ASC'); break;
|
||||
case '+updatedAt': query.orderBy('user.updatedAt', 'DESC'); break;
|
||||
case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
switch (ps.sort) {
|
||||
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
||||
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.id', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.id', 'ASC'); break;
|
||||
case '+updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'DESC'); break;
|
||||
case '-updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'ASC'); break;
|
||||
default: query.orderBy('user.id', 'ASC'); break;
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ describe('アンテナ', () => {
|
|||
users: [''],
|
||||
withFile: false,
|
||||
withReplies: false,
|
||||
localOnly: false,
|
||||
} as Antenna;
|
||||
assert.deepStrictEqual(response, expected);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ describe('Account Move', () => {
|
|||
excludeKeywords: [],
|
||||
users: [],
|
||||
caseSensitive: false,
|
||||
localOnly: false,
|
||||
withReplies: false,
|
||||
withFile: false,
|
||||
notify: false,
|
||||
|
|
@ -431,6 +432,7 @@ describe('Account Move', () => {
|
|||
excludeKeywords: [],
|
||||
users: [eve.id],
|
||||
caseSensitive: false,
|
||||
localOnly: false,
|
||||
withReplies: false,
|
||||
withFile: false,
|
||||
notify: false,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ describe('AnnouncementService', () => {
|
|||
function createUser(data: Partial<MiUser> = {}) {
|
||||
const un = secureRndstr(16);
|
||||
return usersRepository.insert({
|
||||
id: genAidx(new Date()),
|
||||
id: genAidx(Date.now()),
|
||||
username: un,
|
||||
usernameLower: un,
|
||||
...data,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ describe('RoleService', () => {
|
|||
function createUser(data: Partial<MiUser> = {}) {
|
||||
const un = secureRndstr(16);
|
||||
return usersRepository.insert({
|
||||
id: genAidx(new Date()),
|
||||
id: genAidx(Date.now()),
|
||||
username: un,
|
||||
usernameLower: un,
|
||||
...data,
|
||||
|
|
@ -47,7 +47,7 @@ describe('RoleService', () => {
|
|||
|
||||
function createRole(data: Partial<MiRole> = {}) {
|
||||
return rolesRepository.insert({
|
||||
id: genAidx(new Date()),
|
||||
id: genAidx(Date.now()),
|
||||
updatedAt: new Date(),
|
||||
lastUsedAt: new Date(),
|
||||
description: '',
|
||||
|
|
@ -196,10 +196,10 @@ describe('RoleService', () => {
|
|||
|
||||
test('conditional role', async () => {
|
||||
const user1 = await createUser({
|
||||
createdAt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 365)),
|
||||
id: genAidx(Date.now() - (1000 * 60 * 60 * 24 * 365)),
|
||||
});
|
||||
const user2 = await createUser({
|
||||
createdAt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 365)),
|
||||
id: genAidx(Date.now() - (1000 * 60 * 60 * 24 * 365)),
|
||||
followersCount: 10,
|
||||
});
|
||||
await createRole({
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import { secureRndstr } from '@/misc/secure-rndstr.js';
|
|||
import { DownloadService } from '@/core/DownloadService.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import type { MiRemoteUser } from '@/models/User.js';
|
||||
import { genAidx } from '@/misc/id/aidx.js';
|
||||
import { MockResolver } from '../misc/mock-resolver.js';
|
||||
|
||||
const host = 'https://host1.test';
|
||||
|
|
@ -200,7 +201,7 @@ describe('ActivityPub', () => {
|
|||
describe('Renderer', () => {
|
||||
test('Render an announce with visibility: followers', () => {
|
||||
rendererService.renderAnnounce(null, {
|
||||
createdAt: new Date(0),
|
||||
id: genAidx(Date.now()),
|
||||
visibility: 'followers',
|
||||
} as MiNote);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,44 +14,44 @@ import { ulidRegExp, parseUlid } from '@/misc/id/ulid.js';
|
|||
|
||||
describe('misc:id', () => {
|
||||
test('aid', () => {
|
||||
const date = new Date();
|
||||
const date = Date.now();
|
||||
const gotAid = genAid(date);
|
||||
expect(gotAid).toMatch(aidRegExp);
|
||||
expect(parseAid(gotAid).date.getTime()).toBe(date.getTime());
|
||||
expect(parseAid(gotAid).date.getTime()).toBe(date);
|
||||
});
|
||||
|
||||
test('aidx', () => {
|
||||
const date = new Date();
|
||||
const date = Date.now();
|
||||
const gotAidx = genAidx(date);
|
||||
expect(gotAidx).toMatch(aidxRegExp);
|
||||
expect(parseAidx(gotAidx).date.getTime()).toBe(date.getTime());
|
||||
expect(parseAidx(gotAidx).date.getTime()).toBe(date);
|
||||
});
|
||||
|
||||
test('meid', () => {
|
||||
const date = new Date();
|
||||
const date = Date.now();
|
||||
const gotMeid = genMeid(date);
|
||||
expect(gotMeid).toMatch(meidRegExp);
|
||||
expect(parseMeid(gotMeid).date.getTime()).toBe(date.getTime());
|
||||
expect(parseMeid(gotMeid).date.getTime()).toBe(date);
|
||||
});
|
||||
|
||||
test('meidg', () => {
|
||||
const date = new Date();
|
||||
const date = Date.now();
|
||||
const gotMeidg = genMeidg(date);
|
||||
expect(gotMeidg).toMatch(meidgRegExp);
|
||||
expect(parseMeidg(gotMeidg).date.getTime()).toBe(date.getTime());
|
||||
expect(parseMeidg(gotMeidg).date.getTime()).toBe(date);
|
||||
});
|
||||
|
||||
test('objectid', () => {
|
||||
const date = new Date();
|
||||
const date = Date.now();
|
||||
const gotObjectId = genObjectId(date);
|
||||
expect(gotObjectId).toMatch(objectIdRegExp);
|
||||
expect(Math.floor(parseObjectId(gotObjectId).date.getTime() / 1000)).toBe(Math.floor(date.getTime() / 1000));
|
||||
expect(Math.floor(parseObjectId(gotObjectId).date.getTime() / 1000)).toBe(Math.floor(date / 1000));
|
||||
});
|
||||
|
||||
test('ulid', () => {
|
||||
const date = new Date();
|
||||
const gotUlid = ulid(date.getTime());
|
||||
const date = Date.now();
|
||||
const gotUlid = ulid(date);
|
||||
expect(gotUlid).toMatch(ulidRegExp);
|
||||
expect(parseUlid(gotUlid).date.getTime()).toBe(date.getTime());
|
||||
expect(parseUlid(gotUlid).date.getTime()).toBe(date);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import XAntenna from './editor.vue';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { antennasCache } from '@/cache';
|
||||
import { antennasCache } from '@/cache.js';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
|
@ -27,6 +27,7 @@ let draft = $ref({
|
|||
excludeKeywords: [],
|
||||
withReplies: false,
|
||||
caseSensitive: false,
|
||||
localOnly: false,
|
||||
withFile: false,
|
||||
notify: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #label>{{ i18n.ts.antennaExcludeKeywords }}</template>
|
||||
<template #caption>{{ i18n.ts.antennaKeywordsDescription }}</template>
|
||||
</MkTextarea>
|
||||
<MkSwitch v-model="localOnly">{{ i18n.ts.localOnly }}</MkSwitch>
|
||||
<MkSwitch v-model="caseSensitive">{{ i18n.ts.caseSensitive }}</MkSwitch>
|
||||
<MkSwitch v-model="withFile">{{ i18n.ts.withFileAntenna }}</MkSwitch>
|
||||
<MkSwitch v-model="notify">{{ i18n.ts.notifyAntenna }}</MkSwitch>
|
||||
|
|
@ -75,6 +76,7 @@ let users: string = $ref(props.antenna.users.join('\n'));
|
|||
let keywords: string = $ref(props.antenna.keywords.map(x => x.join(' ')).join('\n'));
|
||||
let excludeKeywords: string = $ref(props.antenna.excludeKeywords.map(x => x.join(' ')).join('\n'));
|
||||
let caseSensitive: boolean = $ref(props.antenna.caseSensitive);
|
||||
let localOnly: boolean = $ref(props.antenna.localOnly);
|
||||
let withReplies: boolean = $ref(props.antenna.withReplies);
|
||||
let withFile: boolean = $ref(props.antenna.withFile);
|
||||
let notify: boolean = $ref(props.antenna.notify);
|
||||
|
|
@ -95,6 +97,7 @@ async function saveAntenna() {
|
|||
withFile,
|
||||
notify,
|
||||
caseSensitive,
|
||||
localOnly,
|
||||
users: users.trim().split('\n').map(x => x.trim()),
|
||||
keywords: keywords.trim().split('\n').map(x => x.trim().split(' ')),
|
||||
excludeKeywords: excludeKeywords.trim().split('\n').map(x => x.trim().split(' ')),
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ type Antenna = {
|
|||
userGroupId: ID | null;
|
||||
users: string[];
|
||||
caseSensitive: boolean;
|
||||
localOnly: boolean;
|
||||
notify: boolean;
|
||||
withReplies: boolean;
|
||||
withFile: boolean;
|
||||
|
|
@ -2984,7 +2985,7 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u
|
|||
// src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts
|
||||
// src/api.types.ts:630:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts
|
||||
// src/entities.ts:107:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts
|
||||
// src/entities.ts:600:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
|
||||
// src/entities.ts:601:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
|
||||
// src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
|
|
|||
|
|
@ -470,6 +470,7 @@ export type Antenna = {
|
|||
userGroupId: ID | null; // TODO
|
||||
users: string[]; // TODO
|
||||
caseSensitive: boolean;
|
||||
localOnly: boolean;
|
||||
notify: boolean;
|
||||
withReplies: boolean;
|
||||
withFile: boolean;
|
||||
|
|
|
|||
Loading…
Reference in New Issue