diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml
index 8f8c5a13ab..2809cd2ca4 100644
--- a/.devcontainer/docker-compose.yml
+++ b/.devcontainer/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.8'
services:
app:
- build:
+ build:
context: .
dockerfile: Dockerfile
diff --git a/.editorconfig b/.editorconfig
index a6f988f8d7..def7baa1a8 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -6,6 +6,10 @@ indent_size = 2
charset = utf-8
insert_final_newline = true
end_of_line = lf
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_style = space
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f6b3804f84..896fb6b089 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -106,7 +106,7 @@ If your language is not listed in Crowdin, please open an issue.
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
## Development
-During development, it is useful to use the
+During development, it is useful to use the
```
pnpm dev
@@ -150,7 +150,7 @@ Prepare DB/Redis for testing.
```
docker compose -f packages/backend/test/docker-compose.yml up
```
-Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`.
+Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`.
Run all test.
```
diff --git a/README.md b/README.md
index 2aae4bb865..ab4388c2eb 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
-
+
**🌎 **[Misskey](https://misskey-hub.net/)** is an open source, decentralized social media platform that's free forever! 🚀**
-
+
---
@@ -21,7 +21,7 @@
-
+
---
[![codecov](https://codecov.io/gh/misskey-dev/misskey/branch/develop/graph/badge.svg?token=R6IQZ3QJOL)](https://codecov.io/gh/misskey-dev/misskey)
diff --git a/assets/title_float.svg b/assets/title_float.svg
index 43205ac1c4..ed1749e321 100644
Binary files a/assets/title_float.svg and b/assets/title_float.svg differ
diff --git a/cypress/e2e/basic.cy.js b/cypress/e2e/basic.cy.js
index 2515c14ad6..2bf91cb009 100644
--- a/cypress/e2e/basic.cy.js
+++ b/cypress/e2e/basic.cy.js
@@ -56,7 +56,7 @@ describe('After setup instance', () => {
cy.get('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click();
cy.get('[data-cy-signup-rules-continue]').should('not.be.disabled');
cy.get('[data-cy-signup-rules-continue]').click();
-
+
cy.get('[data-cy-signup-submit]').should('be.disabled');
cy.get('[data-cy-signup-username] input').type('alice');
cy.get('[data-cy-signup-submit]').should('be.disabled');
diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts
index ab11785e28..69d83b13b0 100644
--- a/packages/backend/src/core/AccountMoveService.ts
+++ b/packages/backend/src/core/AccountMoveService.ts
@@ -295,7 +295,7 @@ export class AccountMoveService {
* dstユーザーのalsoKnownAsをfetchPersonしていき、本当にmovedToUrlをdstに指定するユーザーが存在するのかを調べる
*
* @param dst movedToUrlを指定するユーザー
- * @param check
+ * @param check
* @param instant checkがtrueであるユーザーが最初に見つかったら即座にreturnするかどうか
* @returns Promise
*/
diff --git a/packages/backend/src/core/AiService.ts b/packages/backend/src/core/AiService.ts
index 059e335eff..02501b832b 100644
--- a/packages/backend/src/core/AiService.ts
+++ b/packages/backend/src/core/AiService.ts
@@ -31,16 +31,16 @@ export class AiService {
const cpuFlags = await this.getCpuFlags();
isSupportedCpu = REQUIRED_CPU_FLAGS.every(required => cpuFlags.includes(required));
}
-
+
if (!isSupportedCpu) {
console.error('This CPU cannot use TensorFlow.');
return null;
}
-
+
const tf = await import('@tensorflow/tfjs-node');
-
+
if (this.model == null) this.model = await nsfw.load(`file://${_dirname}/../../nsfw-model/`, { size: 299 });
-
+
const buffer = await fs.promises.readFile(path);
const image = await tf.node.decodeImage(buffer, 3) as any;
try {
diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts
index d8df371916..9310fd8b52 100644
--- a/packages/backend/src/core/AntennaService.ts
+++ b/packages/backend/src/core/AntennaService.ts
@@ -99,7 +99,7 @@ export class AntennaService implements OnApplicationShutdown {
'MAXLEN', '~', '200',
'*',
'note', note.id);
-
+
this.globalEventService.publishAntennaStream(antenna.id, 'note', note);
}
@@ -112,16 +112,16 @@ export class AntennaService implements OnApplicationShutdown {
public async checkHitAntenna(antenna: Antenna, note: (Note | Packed<'Note'>), noteUser: { id: User['id']; username: string; host: string | null; }): Promise {
if (note.visibility === 'specified') return false;
if (note.visibility === 'followers') return false;
-
+
if (!antenna.withReplies && note.replyId != null) return false;
-
+
if (antenna.src === 'home') {
// TODO
} else if (antenna.src === 'list') {
const listUsers = (await this.userListJoiningsRepository.findBy({
userListId: antenna.userListId!,
})).map(x => x.userId);
-
+
if (!listUsers.includes(note.userId)) return false;
} else if (antenna.src === 'users') {
const accts = antenna.users.map(x => {
@@ -130,32 +130,32 @@ export class AntennaService implements OnApplicationShutdown {
});
if (!accts.includes(this.utilityService.getFullApAccount(noteUser.username, noteUser.host).toLowerCase())) return false;
}
-
+
const keywords = antenna.keywords
// Clean up
.map(xs => xs.filter(x => x !== ''))
.filter(xs => xs.length > 0);
-
+
if (keywords.length > 0) {
if (note.text == null && note.cw == null) return false;
const _text = (note.text ?? '') + '\n' + (note.cw ?? '');
-
+
const matched = keywords.some(and =>
and.every(keyword =>
antenna.caseSensitive
? _text.includes(keyword)
: _text.toLowerCase().includes(keyword.toLowerCase()),
));
-
+
if (!matched) return false;
}
-
+
const excludeKeywords = antenna.excludeKeywords
// Clean up
.map(xs => xs.filter(x => x !== ''))
.filter(xs => xs.length > 0);
-
+
if (excludeKeywords.length > 0) {
if (note.text == null && note.cw == null) return false;
@@ -167,16 +167,16 @@ export class AntennaService implements OnApplicationShutdown {
? _text.includes(keyword)
: _text.toLowerCase().includes(keyword.toLowerCase()),
));
-
+
if (matched) return false;
}
-
+
if (antenna.withFile) {
if (note.fileIds && note.fileIds.length === 0) return false;
}
-
+
// TODO: eval expression
-
+
return true;
}
@@ -188,7 +188,7 @@ export class AntennaService implements OnApplicationShutdown {
});
this.antennasFetched = true;
}
-
+
return this.antennas;
}
diff --git a/packages/backend/src/core/CaptchaService.ts b/packages/backend/src/core/CaptchaService.ts
index 1a52a229c5..10cfdba254 100644
--- a/packages/backend/src/core/CaptchaService.ts
+++ b/packages/backend/src/core/CaptchaService.ts
@@ -20,7 +20,7 @@ export class CaptchaService {
secret,
response,
});
-
+
const res = await this.httpRequestService.send(url, {
method: 'POST',
body: params.toString(),
@@ -28,14 +28,14 @@ export class CaptchaService {
'Content-Type': 'application/x-www-form-urlencoded',
},
}, { throwErrorWhenResponseNotOk: false });
-
+
if (!res.ok) {
throw new Error(`${res.status}`);
}
-
+
return await res.json() as CaptchaResponse;
- }
-
+ }
+
@bindThis
public async verifyRecaptcha(secret: string, response: string | null | undefined): Promise {
if (response == null) {
@@ -73,7 +73,7 @@ export class CaptchaService {
if (response == null) {
throw new Error('turnstile-failed: no response provided');
}
-
+
const result = await this.getCaptchaResponse('https://challenges.cloudflare.com/turnstile/v0/siteverify', secret, response).catch(err => {
throw new Error(`turnstile-request-failed: ${err}`);
});
diff --git a/packages/backend/src/core/CreateSystemUserService.ts b/packages/backend/src/core/CreateSystemUserService.ts
index 8f887d90f9..0bfbe2b173 100644
--- a/packages/backend/src/core/CreateSystemUserService.ts
+++ b/packages/backend/src/core/CreateSystemUserService.ts
@@ -25,27 +25,27 @@ export class CreateSystemUserService {
@bindThis
public async createSystemUser(username: string): Promise {
const password = uuid();
-
+
// Generate hash of password
const salt = await bcrypt.genSalt(8);
const hash = await bcrypt.hash(password, salt);
-
+
// Generate secret
const secret = generateNativeUserToken();
-
+
const keyPair = await genRsaKeyPair(4096);
-
+
let account!: User;
-
+
// Start transaction
await this.db.transaction(async transactionalEntityManager => {
const exist = await transactionalEntityManager.findOneBy(User, {
usernameLower: username.toLowerCase(),
host: IsNull(),
});
-
+
if (exist) throw new Error('the user is already exists');
-
+
account = await transactionalEntityManager.insert(User, {
id: this.idService.genId(),
createdAt: new Date(),
@@ -58,25 +58,25 @@ export class CreateSystemUserService {
isExplorable: false,
isBot: true,
}).then(x => transactionalEntityManager.findOneByOrFail(User, x.identifiers[0]));
-
+
await transactionalEntityManager.insert(UserKeypair, {
publicKey: keyPair.publicKey,
privateKey: keyPair.privateKey,
userId: account.id,
});
-
+
await transactionalEntityManager.insert(UserProfile, {
userId: account.id,
autoAcceptFollowed: false,
password: hash,
});
-
+
await transactionalEntityManager.insert(UsedUsername, {
createdAt: new Date(),
username: username.toLowerCase(),
});
});
-
+
return account;
}
}
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index 5f2ced77eb..661d956bd6 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -140,7 +140,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
this.globalEventService.publishBroadcastStream('emojiAdded', {
emoji: updated,
- });
+ });
}
}
@@ -194,7 +194,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
}
this.localEmojisCache.refresh();
-
+
this.globalEventService.publishBroadcastStream('emojiUpdated', {
emojis: await this.emojiEntityService.packDetailedMany(ids),
});
@@ -215,7 +215,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
emojis: await this.emojiEntityService.packDetailedMany(ids),
});
}
-
+
@bindThis
public async setLicenseBulk(ids: Emoji['id'][], license: string | null) {
await this.emojisRepository.update({
diff --git a/packages/backend/src/core/DeleteAccountService.ts b/packages/backend/src/core/DeleteAccountService.ts
index 327283106f..3a0592441b 100644
--- a/packages/backend/src/core/DeleteAccountService.ts
+++ b/packages/backend/src/core/DeleteAccountService.ts
@@ -28,11 +28,11 @@ export class DeleteAccountService {
// 物理削除する前にDelete activityを送信する
await this.userSuspendService.doPostSuspend(user).catch(e => {});
-
+
this.queueService.createDeleteAccountJob(user, {
soft: false,
});
-
+
await this.usersRepository.update(user.id, {
isDeleted: true,
});
diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts
index 59932a5b88..a04e9c1225 100644
--- a/packages/backend/src/core/EmailService.ts
+++ b/packages/backend/src/core/EmailService.ts
@@ -29,12 +29,12 @@ export class EmailService {
@bindThis
public async sendEmail(to: string, subject: string, html: string, text: string) {
const meta = await this.metaService.fetch(true);
-
+
const iconUrl = `${this.config.url}/static-assets/mi-white.png`;
const emailSettingUrl = `${this.config.url}/settings/email`;
-
+
const enableAuth = meta.smtpUser != null && meta.smtpUser !== '';
-
+
const transporter = nodemailer.createTransport({
host: meta.smtpHost,
port: meta.smtpPort,
@@ -46,7 +46,7 @@ export class EmailService {
pass: meta.smtpPass,
} : undefined,
} as any);
-
+
try {
// TODO: htmlサニタイズ
const info = await transporter.sendMail({
@@ -135,7 +135,7 @@ export class EmailService {