forked from FoundKeyGang/FoundKey
Compare commits
11 commits
30cd417380
...
c4a330dd9e
Author | SHA1 | Date | |
---|---|---|---|
c4a330dd9e | |||
a0f0bac1ca | |||
af003fc0fe | |||
94cd10365d | |||
0addcddd6c | |||
64c4973eca | |||
7272bde464 | |||
7c9e118ff1 | |||
bed8286175 | |||
f00b3cc378 | |||
21ab8e75ee |
19 changed files with 131 additions and 99 deletions
|
@ -20,10 +20,11 @@ export async function checkWordMute(note: NoteLike, me: UserLike | null | undefi
|
|||
const text = ((note.cw ?? '') + '\n' + (note.text ?? '')).trim();
|
||||
|
||||
if (text === '') return false;
|
||||
const textLower = text.toLowerCase();
|
||||
|
||||
const matched = mutedWords.some(filter => {
|
||||
if (Array.isArray(filter)) {
|
||||
return filter.every(keyword => text.includes(keyword));
|
||||
return filter.every(keyword => textLower.includes(keyword.toLowerCase()));
|
||||
} else {
|
||||
// represents RegExp
|
||||
const regexp = filter.match(/^\/(.+)\/(.*)$/);
|
||||
|
|
|
@ -10,52 +10,49 @@ const logger = queueLogger.createSubLogger('check-expired');
|
|||
export async function checkExpired(job: Bull.Job<Record<string, unknown>>, done: any): Promise<void> {
|
||||
logger.info('Checking expired data...');
|
||||
|
||||
const expiredMutings = await Mutings.createQueryBuilder('muting')
|
||||
.where('muting.expiresAt IS NOT NULL')
|
||||
.andWhere('muting.expiresAt < :now', { now: new Date() })
|
||||
.innerJoinAndSelect('muting.mutee', 'mutee')
|
||||
.getMany();
|
||||
|
||||
if (expiredMutings.length > 0) {
|
||||
await Mutings.delete({
|
||||
id: In(expiredMutings.map(m => m.id)),
|
||||
});
|
||||
|
||||
for (const m of expiredMutings) {
|
||||
publishUserEvent(m.muterId, 'unmute', m.mutee!);
|
||||
}
|
||||
}
|
||||
|
||||
const OlderThan = (millis: number) => {
|
||||
return LessThan(new Date(new Date().getTime() - millis));
|
||||
};
|
||||
|
||||
await Signins.delete({
|
||||
createdAt: OlderThan(2 * MONTH),
|
||||
});
|
||||
await Promise.all([
|
||||
Mutings.createQueryBuilder('muting')
|
||||
.where('muting.expiresAt IS NOT NULL')
|
||||
.andWhere('muting.expiresAt < :now', { now: new Date() })
|
||||
.innerJoinAndSelect('muting.mutee', 'mutee')
|
||||
.getMany()
|
||||
.then(async (expiredMutings) => {
|
||||
if (expiredMutings.length > 0) {
|
||||
await Mutings.delete({
|
||||
id: In(expiredMutings.map(m => m.id)),
|
||||
});
|
||||
|
||||
await AttestationChallenges.delete({
|
||||
createdAt: OlderThan(5 * MINUTE),
|
||||
});
|
||||
|
||||
await PasswordResetRequests.delete({
|
||||
// this timing should be the same as in @/server/api/endpoints/reset-password.ts
|
||||
createdAt: OlderThan(30 * MINUTE),
|
||||
});
|
||||
|
||||
await AuthSessions.delete({
|
||||
createdAt: OlderThan(15 * MINUTE),
|
||||
});
|
||||
|
||||
await Notifications.delete({
|
||||
isRead: true,
|
||||
createdAt: OlderThan(3 * MONTH),
|
||||
});
|
||||
|
||||
await Users.delete({
|
||||
// delete users where the deletion status reference count has come down to zero
|
||||
isDeleted: 0,
|
||||
});
|
||||
for (const m of expiredMutings) {
|
||||
publishUserEvent(m.muterId, 'unmute', m.mutee!);
|
||||
}
|
||||
}
|
||||
}),
|
||||
Signins.delete({
|
||||
createdAt: OlderThan(2 * MONTH),
|
||||
}),
|
||||
AttestationChallenges.delete({
|
||||
createdAt: OlderThan(5 * MINUTE),
|
||||
}),
|
||||
PasswordResetRequests.delete({
|
||||
// this timing should be the same as in @/server/api/endpoints/reset-password.ts
|
||||
createdAt: OlderThan(30 * MINUTE),
|
||||
}),
|
||||
AuthSessions.delete({
|
||||
createdAt: OlderThan(15 * MINUTE),
|
||||
}),
|
||||
Notifications.delete({
|
||||
isRead: true,
|
||||
createdAt: OlderThan(3 * MONTH),
|
||||
}),
|
||||
Users.delete({
|
||||
// delete users where the deletion status reference count has come down to zero
|
||||
isDeleted: 0,
|
||||
}),
|
||||
]);
|
||||
|
||||
logger.succ('Deleted expired data.');
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ export function validateNote(object: IObject): Error | null {
|
|||
/**
|
||||
* Function to process the content of a note, reusable in createNote and updateNote.
|
||||
*/
|
||||
async function processContent(note: IPost, quoteUri: string | null):
|
||||
async function processContent(actor: IRemoteUser, note: IPost, quoteUri: string | null, resolver: Resolver):
|
||||
Promise<{
|
||||
cw: string | null,
|
||||
files: DriveFile[],
|
||||
|
@ -78,10 +78,10 @@ async function processContent(note: IPost, quoteUri: string | null):
|
|||
const limit = promiseLimit(2);
|
||||
|
||||
const attachments = toArray(note.attachment);
|
||||
const files = note.attachment
|
||||
const files = attachments
|
||||
// If the note is marked as sensitive, the images should be marked sensitive too.
|
||||
.map(attach => attach.sensitive |= note.sensitive)
|
||||
? (await Promise.all(note.attachment.map(x => limit(() => resolveImage(actor, x, resolver)) as Promise<DriveFile>)))
|
||||
? (await Promise.all(attachments.map(x => limit(() => resolveImage(actor, x, resolver)) as Promise<DriveFile>)))
|
||||
.filter(image => image != null)
|
||||
: [];
|
||||
|
||||
|
@ -258,7 +258,7 @@ export async function createNote(value: string | IObject, resolver: Resolver, si
|
|||
|
||||
const poll = await extractPollFromQuestion(note, resolver).catch(() => undefined);
|
||||
|
||||
const processedContent = await processContent(note, quote?.uri);
|
||||
const processedContent = await processContent(actor, note, quote?.uri, resolver);
|
||||
|
||||
if (isTalk) {
|
||||
for (const recipient of visibleUsers) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { toPuny } from '@/misc/convert-host.js';
|
|||
import { Emojis } from '@/models/index.js';
|
||||
import { Emoji } from '@/models/entities/emoji.js';
|
||||
import { apLogger } from '@/remote/activitypub/logger.js';
|
||||
import { genId } from '@/misc/gen-id.js';
|
||||
|
||||
export function extractApHashtags(tags: IObject | IObject[] | null | undefined): string[] {
|
||||
if (tags == null) return [];
|
||||
|
|
|
@ -17,27 +17,56 @@ export const renderActivity = (x: any): IActivity | null => {
|
|||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1',
|
||||
{
|
||||
xsd: 'http://www.w3.org/2001/XMLSchema#',
|
||||
// as non-standards
|
||||
manuallyApprovesFollowers: 'as:manuallyApprovesFollowers',
|
||||
sensitive: 'as:sensitive',
|
||||
manuallyApprovesFollowers: {
|
||||
'@id': 'as:manuallyApprovesFollowers',
|
||||
'@type': 'xsd:boolean',
|
||||
},
|
||||
sensitive: {
|
||||
'@id': 'as:sensitive',
|
||||
'@type': 'xsd:boolean',
|
||||
},
|
||||
Hashtag: 'as:Hashtag',
|
||||
// Mastodon
|
||||
toot: 'http://joinmastodon.org/ns#',
|
||||
Emoji: 'toot:Emoji',
|
||||
featured: 'toot:featured',
|
||||
discoverable: 'toot:discoverable',
|
||||
featured: {
|
||||
'@id': 'toot:featured',
|
||||
'@type': '@id',
|
||||
},
|
||||
discoverable: {
|
||||
'@id': 'toot:discoverable',
|
||||
'@type': 'xsd:boolean',
|
||||
},
|
||||
// Fedibird
|
||||
fedibird: 'http://fedibird.com/ns#',
|
||||
quoteUri: 'fedibird:quoteUri',
|
||||
quoteUri: {
|
||||
'@id': 'http://fedibird.com/ns#quoteUri',
|
||||
'@type': '@id',
|
||||
},
|
||||
// schema
|
||||
schema: 'http://schema.org#',
|
||||
PropertyValue: 'schema:PropertyValue',
|
||||
value: 'schema:value',
|
||||
schema: 'http://schema.org/',
|
||||
PropertyValue: {
|
||||
'@id': 'schema:PropertyValue',
|
||||
'@context': {
|
||||
'value': 'schema:value',
|
||||
'name': 'schema:name',
|
||||
},
|
||||
},
|
||||
// Misskey
|
||||
misskey: 'https://misskey-hub.net/ns#',
|
||||
'_misskey_quote': 'misskey:_misskey_quote',
|
||||
'_misskey_talk': 'misskey:_misskey_talk',
|
||||
'isCat': 'misskey:isCat',
|
||||
'_misskey_quote': {
|
||||
'@id': 'misskey:_misskey_quote',
|
||||
'@type': '@id',
|
||||
},
|
||||
'_misskey_talk': {
|
||||
'@id': 'misskey:_misskey_talk',
|
||||
'@type': 'xsd:boolean',
|
||||
},
|
||||
'isCat': {
|
||||
'@id': 'misskey:isCat',
|
||||
'@type': 'xsd:boolean',
|
||||
},
|
||||
// vcard
|
||||
vcard: 'http://www.w3.org/2006/vcard/ns#',
|
||||
},
|
||||
|
|
|
@ -31,13 +31,13 @@ export default class Logger {
|
|||
* @param color Log message color
|
||||
* @param store Whether to store messages
|
||||
*/
|
||||
constructor(domain: string, color?: KEYWORD, store = true, minLevel: Level = LOG_LEVELS.info) {
|
||||
constructor(domain: string, color?: KEYWORD, store = true, minLevel?: Level) {
|
||||
this.domain = {
|
||||
name: domain,
|
||||
color,
|
||||
};
|
||||
this.store = store;
|
||||
this.minLevel = minLevel;
|
||||
this.minLevel = minLevel ?? envOption.logLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ export default class Logger {
|
|||
* @param store Whether to store messages
|
||||
* @returns A Logger instance whose parent logger is this instance.
|
||||
*/
|
||||
public createSubLogger(domain: string, color?: KEYWORD, store = true, minLevel: Level = LOG_LEVELS.info): Logger {
|
||||
public createSubLogger(domain: string, color?: KEYWORD, store = true, minLevel?: Level): Logger {
|
||||
const logger = new Logger(domain, color, store, minLevel);
|
||||
logger.parentLogger = this;
|
||||
return logger;
|
||||
|
|
|
@ -4,11 +4,12 @@ import * as assert from 'assert';
|
|||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, startServer, shutdownServer } from './utils.js';
|
||||
|
||||
describe('API visibility', () => {
|
||||
describe('API visibility', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
p = await startServer();
|
||||
});
|
||||
|
||||
|
|
|
@ -4,14 +4,15 @@ import * as assert from 'assert';
|
|||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, react, uploadFile, startServer, shutdownServer } from './utils.js';
|
||||
|
||||
describe('API', () => {
|
||||
describe('API', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
let alice: any;
|
||||
let bob: any;
|
||||
let carol: any;
|
||||
|
||||
before(async function() {
|
||||
this.timeout(0);
|
||||
before(async () => {
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
|
|
|
@ -4,7 +4,9 @@ import * as assert from 'assert';
|
|||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, startServer, shutdownServer } from './utils.js';
|
||||
|
||||
describe('Block', () => {
|
||||
describe('Block', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
// alice blocks bob
|
||||
|
@ -13,8 +15,6 @@ describe('Block', () => {
|
|||
let carol: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
|
|
|
@ -16,14 +16,15 @@ const AP = 'application/activity+json; charset=utf-8';
|
|||
const JSON = 'application/json; charset=utf-8';
|
||||
const HTML = 'text/html; charset=utf-8';
|
||||
|
||||
describe('Fetch resource', () => {
|
||||
describe('Fetch resource', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
let alice: any;
|
||||
let alicesPost: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
alicesPost = await post(alice, {
|
||||
|
|
|
@ -4,7 +4,9 @@ import * as assert from 'assert';
|
|||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, react, connectStream, startServer, shutdownServer, simpleGet } from './utils.js';
|
||||
|
||||
describe('FF visibility', () => {
|
||||
describe('FF visibility', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
let alice: any;
|
||||
|
@ -12,8 +14,6 @@ describe('FF visibility', () => {
|
|||
let follower: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
|
|
|
@ -4,7 +4,9 @@ import * as assert from 'assert';
|
|||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, react, startServer, shutdownServer, waitFire } from './utils.js';
|
||||
|
||||
describe('Mute', () => {
|
||||
describe('Mute', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
// alice mutes carol
|
||||
|
@ -13,8 +15,6 @@ describe('Mute', () => {
|
|||
let carol: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
|
|
|
@ -5,7 +5,9 @@ import * as childProcess from 'child_process';
|
|||
import { Note } from '../src/models/entities/note.js';
|
||||
import { async, signup, request, post, uploadUrl, startServer, shutdownServer, initTestDb, api } from './utils.js';
|
||||
|
||||
describe('Note', () => {
|
||||
describe('Note', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
let Notes: any;
|
||||
|
||||
|
@ -13,8 +15,6 @@ describe('Note', () => {
|
|||
let bob: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
p = await startServer();
|
||||
const connection = await initTestDb(true);
|
||||
Notes = connection.getRepository(Note);
|
||||
|
|
|
@ -5,7 +5,9 @@ import * as childProcess from 'child_process';
|
|||
import * as sinon from 'sinon';
|
||||
import { async, signup, startServer, shutdownServer, initTestDb } from '../utils.js';
|
||||
|
||||
describe('Creating a block activity', () => {
|
||||
describe('Creating a block activity', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
// alice blocks bob
|
||||
|
@ -14,8 +16,6 @@ describe('Creating a block activity', () => {
|
|||
let carol: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
await initTestDb();
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
|
|
|
@ -24,7 +24,9 @@ describe('Streaming', () => {
|
|||
});
|
||||
};
|
||||
|
||||
describe('Streaming', () => {
|
||||
describe('Streaming', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
// Local users
|
||||
let ayano: any;
|
||||
let kyoko: any;
|
||||
|
@ -38,8 +40,6 @@ describe('Streaming', () => {
|
|||
let list: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
p = await startServer();
|
||||
const connection = await initTestDb(true);
|
||||
Followings = connection.getRepository(Following);
|
||||
|
@ -410,7 +410,7 @@ describe('Streaming', () => {
|
|||
let fooCount = 0;
|
||||
let barCount = 0;
|
||||
let fooBarCount = 0;
|
||||
|
||||
|
||||
const ws = await connectStream(chitose, 'hashtag', ({ type, body }) => {
|
||||
if (type == 'note') {
|
||||
if (body.text === '#foo') fooCount++;
|
||||
|
@ -422,19 +422,19 @@ describe('Streaming', () => {
|
|||
['foo', 'bar'],
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
post(chitose, {
|
||||
text: '#foo',
|
||||
});
|
||||
|
||||
|
||||
post(chitose, {
|
||||
text: '#bar',
|
||||
});
|
||||
|
||||
|
||||
post(chitose, {
|
||||
text: '#foo #bar',
|
||||
});
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
assert.strictEqual(fooCount, 0);
|
||||
assert.strictEqual(barCount, 0);
|
||||
|
|
|
@ -4,7 +4,9 @@ import * as assert from 'assert';
|
|||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, react, connectStream, startServer, shutdownServer } from './utils.js';
|
||||
|
||||
describe('Note thread mute', () => {
|
||||
describe('Note thread mute', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
let alice: any;
|
||||
|
@ -12,8 +14,6 @@ describe('Note thread mute', () => {
|
|||
let carol: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
|
|
|
@ -4,7 +4,9 @@ import * as assert from 'assert';
|
|||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, uploadUrl, startServer, shutdownServer } from './utils.js';
|
||||
|
||||
describe('users/notes', () => {
|
||||
describe('users/notes', function() {
|
||||
this.timeout(20*60*1000);
|
||||
|
||||
let p: childProcess.ChildProcess;
|
||||
|
||||
let alice: any;
|
||||
|
@ -13,8 +15,6 @@ describe('users/notes', () => {
|
|||
let jpgPngNote: any;
|
||||
|
||||
before(async () => {
|
||||
this.timeout(0);
|
||||
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg');
|
||||
|
|
|
@ -10,7 +10,7 @@ import * as foundkey from 'foundkey-js';
|
|||
import fetch from 'node-fetch';
|
||||
import FormData from 'form-data';
|
||||
import { DataSource } from 'typeorm';
|
||||
import loadConfig from '../src/config/load.js';
|
||||
import { loadConfig } from '../src/config/load.js';
|
||||
import { entities } from '../src/db/postgre.js';
|
||||
import got from 'got';
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ export function checkWordMute(note: Record<string, any>, me: Record<string, any>
|
|||
const text = ((note.cw ?? '') + '\n' + (note.text ?? '')).trim();
|
||||
|
||||
if (text === '') return false;
|
||||
const textLower = text.toLowerCase();
|
||||
|
||||
const matched = mutedWords.some(filter => {
|
||||
if (Array.isArray(filter)) {
|
||||
|
@ -13,7 +14,7 @@ export function checkWordMute(note: Record<string, any>, me: Record<string, any>
|
|||
const filteredFilter = filter.filter(keyword => keyword !== '');
|
||||
if (filteredFilter.length === 0) return false;
|
||||
|
||||
return filteredFilter.every(keyword => text.includes(keyword));
|
||||
return filteredFilter.every(keyword => textLower.includes(keyword.toLowerCase()));
|
||||
} else {
|
||||
// represents RegExp
|
||||
const regexp = filter.match(/^\/(.+)\/(.*)$/);
|
||||
|
|
Loading…
Reference in a new issue