summaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2021-02-19 21:42:47 +0900
committersyuilo <syuilotan@yahoo.co.jp>2021-02-19 21:42:47 +0900
commitd6c8b9b99470db45c201229b5c9235e7be3067de (patch)
tree01e5fccad6d84cf1e7f41e0a5e3aae955f3695e0 /src/services
parentMerge branch 'develop' (diff)
parent12.70.0 (diff)
downloadmisskey-d6c8b9b99470db45c201229b5c9235e7be3067de.tar.gz
misskey-d6c8b9b99470db45c201229b5c9235e7be3067de.tar.bz2
misskey-d6c8b9b99470db45c201229b5c9235e7be3067de.zip
Merge branch 'develop'
Diffstat (limited to 'src/services')
-rw-r--r--src/services/add-note-to-antenna.ts5
-rw-r--r--src/services/create-notification.ts27
-rw-r--r--src/services/following/create.ts3
-rw-r--r--src/services/following/requests/accept-all.ts3
-rw-r--r--src/services/messages/delete.ts5
-rw-r--r--src/services/note/create.ts5
-rw-r--r--src/services/send-email-notification.ts28
-rw-r--r--src/services/send-email.ts91
8 files changed, 139 insertions, 28 deletions
diff --git a/src/services/add-note-to-antenna.ts b/src/services/add-note-to-antenna.ts
index f11607fd43..2c893488c3 100644
--- a/src/services/add-note-to-antenna.ts
+++ b/src/services/add-note-to-antenna.ts
@@ -3,7 +3,6 @@ import { Note } from '../models/entities/note';
import { AntennaNotes, Mutings, Notes } from '../models';
import { genId } from '../misc/gen-id';
import { isMutedUserRelated } from '../misc/is-muted-user-related';
-import { ensure } from '../prelude/ensure';
import { publishAntennaStream, publishMainStream } from './stream';
import { User } from '../models/entities/user';
@@ -34,10 +33,10 @@ export async function addNoteToAntenna(antenna: Antenna, note: Note, noteUser: U
};
if (note.replyId != null) {
- _note.reply = await Notes.findOne(note.replyId).then(ensure);
+ _note.reply = await Notes.findOneOrFail(note.replyId);
}
if (note.renoteId != null) {
- _note.renote = await Notes.findOne(note.renoteId).then(ensure);
+ _note.renote = await Notes.findOneOrFail(note.renoteId);
}
if (isMutedUserRelated(_note, new Set<string>(mutings.map(x => x.muteeId)))) {
diff --git a/src/services/create-notification.ts b/src/services/create-notification.ts
index 5dddaa5727..6cd116040a 100644
--- a/src/services/create-notification.ts
+++ b/src/services/create-notification.ts
@@ -4,6 +4,7 @@ import { Notifications, Mutings, UserProfiles } from '../models';
import { genId } from '../misc/gen-id';
import { User } from '../models/entities/user';
import { Notification } from '../models/entities/notification';
+import { sendEmailNotification } from './send-email-notification';
export async function createNotification(
notifieeId: User['id'],
@@ -38,20 +39,22 @@ export async function createNotification(
setTimeout(async () => {
const fresh = await Notifications.findOne(notification.id);
if (fresh == null) return; // 既に削除されているかもしれない
- if (!fresh.isRead) {
- //#region ただしミュートしているユーザーからの通知なら無視
- const mutings = await Mutings.find({
- muterId: notifieeId
- });
- if (data.notifierId && mutings.map(m => m.muteeId).includes(data.notifierId)) {
- return;
- }
- //#endregion
+ if (fresh.isRead) return;
- publishMainStream(notifieeId, 'unreadNotification', packed);
-
- pushSw(notifieeId, 'notification', packed);
+ //#region ただしミュートしているユーザーからの通知なら無視
+ const mutings = await Mutings.find({
+ muterId: notifieeId
+ });
+ if (data.notifierId && mutings.map(m => m.muteeId).includes(data.notifierId)) {
+ return;
}
+ //#endregion
+
+ publishMainStream(notifieeId, 'unreadNotification', packed);
+
+ pushSw(notifieeId, 'notification', packed);
+ if (type === 'follow') sendEmailNotification.follow(notifieeId, data);
+ if (type === 'receiveFollowRequest') sendEmailNotification.receiveFollowRequest(notifieeId, data);
}, 2000);
return notification;
diff --git a/src/services/following/create.ts b/src/services/following/create.ts
index c5f130f49f..c0583cdb86 100644
--- a/src/services/following/create.ts
+++ b/src/services/following/create.ts
@@ -14,7 +14,6 @@ import { instanceChart, perUserFollowingChart } from '../chart';
import { genId } from '../../misc/gen-id';
import { createNotification } from '../create-notification';
import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
-import { ensure } from '../../prelude/ensure';
const logger = new Logger('following/create');
@@ -130,7 +129,7 @@ export default async function(follower: User, followee: User, requestId?: string
if (blocked != null) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'blocked');
}
- const followeeProfile = await UserProfiles.findOne(followee.id).then(ensure);
+ const followeeProfile = await UserProfiles.findOneOrFail(followee.id);
// フォロー対象が鍵アカウントである or
// フォロワーがBotであり、フォロー対象がBotからのフォローに慎重である or
diff --git a/src/services/following/requests/accept-all.ts b/src/services/following/requests/accept-all.ts
index 70e7448aad..da39965349 100644
--- a/src/services/following/requests/accept-all.ts
+++ b/src/services/following/requests/accept-all.ts
@@ -1,7 +1,6 @@
import accept from './accept';
import { User } from '../../../models/entities/user';
import { FollowRequests, Users } from '../../../models';
-import { ensure } from '../../../prelude/ensure';
/**
* 指定したユーザー宛てのフォローリクエストをすべて承認
@@ -13,7 +12,7 @@ export default async function(user: User) {
});
for (const request of requests) {
- const follower = await Users.findOne(request.followerId).then(ensure);
+ const follower = await Users.findOneOrFail(request.followerId);
accept(user, follower);
}
}
diff --git a/src/services/messages/delete.ts b/src/services/messages/delete.ts
index 0efff85f39..c94a7b67db 100644
--- a/src/services/messages/delete.ts
+++ b/src/services/messages/delete.ts
@@ -1,5 +1,4 @@
import config from '../../config';
-import { ensure } from '../../prelude/ensure';
import { MessagingMessages, Users } from '../../models';
import { MessagingMessage } from '../../models/entities/messaging-message';
import { publishGroupMessagingStream, publishMessagingStream } from '../stream';
@@ -15,8 +14,8 @@ export async function deleteMessage(message: MessagingMessage) {
async function postDeleteMessage(message: MessagingMessage) {
if (message.recipientId) {
- const user = await Users.findOne(message.userId).then(ensure);
- const recipient = await Users.findOne(message.recipientId).then(ensure);
+ const user = await Users.findOneOrFail(message.userId);
+ const recipient = await Users.findOneOrFail(message.recipientId);
if (Users.isLocalUser(user)) publishMessagingStream(message.userId, message.recipientId, 'deleted', message.id);
if (Users.isLocalUser(recipient)) publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id);
diff --git a/src/services/note/create.ts b/src/services/note/create.ts
index 62ec92f2bc..563eaac758 100644
--- a/src/services/note/create.ts
+++ b/src/services/note/create.ts
@@ -26,7 +26,6 @@ import { notesChart, perUserNotesChart, activeUsersChart, instanceChart } from '
import { Poll, IPoll } from '../../models/entities/poll';
import { createNotification } from '../create-notification';
import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
-import { ensure } from '../../prelude/ensure';
import { checkHitAntenna } from '../../misc/check-hit-antenna';
import { checkWordMute } from '../../misc/check-word-mute';
import { addNoteToAntenna } from '../add-note-to-antenna';
@@ -200,7 +199,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
tags = tags.filter(tag => Array.from(tag || '').length <= 128).splice(0, 32);
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
- mentionedUsers.push(await Users.findOne(data.reply.userId).then(ensure));
+ mentionedUsers.push(await Users.findOneOrFail(data.reply.userId));
}
if (data.visibility == 'specified') {
@@ -213,7 +212,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
}
if (data.reply && !data.visibleUsers.some(x => x.id === data.reply!.userId)) {
- data.visibleUsers.push(await Users.findOne(data.reply.userId).then(ensure));
+ data.visibleUsers.push(await Users.findOneOrFail(data.reply.userId));
}
}
diff --git a/src/services/send-email-notification.ts b/src/services/send-email-notification.ts
new file mode 100644
index 0000000000..7579d5b674
--- /dev/null
+++ b/src/services/send-email-notification.ts
@@ -0,0 +1,28 @@
+import { UserProfiles } from '../models';
+import { User } from '../models/entities/user';
+import { sendEmail } from './send-email';
+import * as locales from '../../locales/';
+import { I18n } from '../misc/i18n';
+
+// TODO: locale ファイルをクライアント用とサーバー用で分けたい
+
+async function follow(userId: User['id'], args: {}) {
+ const userProfile = await UserProfiles.findOneOrFail({ userId: userId });
+ if (!userProfile.email || !userProfile.emailNotificationTypes.includes('follow')) return;
+ const locale = locales[userProfile.lang || 'ja-JP'];
+ const i18n = new I18n(locale);
+ sendEmail(userProfile.email, i18n.t('_email._follow.title'), 'test', 'test');
+}
+
+async function receiveFollowRequest(userId: User['id'], args: {}) {
+ const userProfile = await UserProfiles.findOneOrFail({ userId: userId });
+ if (!userProfile.email || !userProfile.emailNotificationTypes.includes('receiveFollowRequest')) return;
+ const locale = locales[userProfile.lang || 'ja-JP'];
+ const i18n = new I18n(locale);
+ sendEmail(userProfile.email, i18n.t('_email._receiveFollowRequest.title'), 'test', 'test');
+}
+
+export const sendEmailNotification = {
+ follow,
+ receiveFollowRequest,
+};
diff --git a/src/services/send-email.ts b/src/services/send-email.ts
index 5a8f92be54..c716b36715 100644
--- a/src/services/send-email.ts
+++ b/src/services/send-email.ts
@@ -5,9 +5,12 @@ import config from '../config';
export const logger = new Logger('email');
-export async function sendEmail(to: string, subject: string, text: string) {
+export async function sendEmail(to: string, subject: string, html: string, text: string) {
const meta = await fetchMeta(true);
+ const iconUrl = `${config.url}/assets/mi-white.png`;
+ const emailSettingUrl = `${config.url}/settings/email`;
+
const enableAuth = meta.smtpUser != null && meta.smtpUser !== '';
const transporter = nodemailer.createTransport({
@@ -23,11 +26,93 @@ export async function sendEmail(to: string, subject: string, text: string) {
} as any);
try {
+ // TODO: htmlサニタイズ
const info = await transporter.sendMail({
from: meta.email!,
to: to,
- subject: subject || 'Misskey',
- text: text
+ subject: subject,
+ text: text,
+ html: `<!doctype html>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ <title>${ subject }</title>
+ <style>
+ html {
+ background: #eee;
+ }
+
+ body {
+ padding: 16px;
+ margin: 0;
+ font-family: sans-serif;
+ font-size: 14px;
+ }
+
+ a {
+ text-decoration: none;
+ color: #86b300;
+ }
+ a:hover {
+ text-decoration: underline;
+ }
+
+ main {
+ max-width: 500px;
+ margin: 0 auto;
+ background: #fff;
+ color: #555;
+ }
+ main > header {
+ padding: 32px;
+ background: #86b300;
+ }
+ main > header > img {
+ max-width: 128px;
+ max-height: 28px;
+ vertical-align: bottom;
+ }
+ main > article {
+ padding: 32px;
+ }
+ main > article > h1 {
+ margin: 0 0 1em 0;
+ }
+ main > footer {
+ padding: 32px;
+ border-top: solid 1px #eee;
+ }
+
+ nav {
+ box-sizing: border-box;
+ max-width: 500px;
+ margin: 16px auto 0 auto;
+ padding: 0 32px;
+ }
+ nav > a {
+ color: #888;
+ }
+ </style>
+ </head>
+ <body>
+ <main>
+ <header>
+ <img src="${ meta.logoImageUrl || meta.iconUrl || iconUrl }"/>
+ </header>
+ <article>
+ <h1>${ subject }</h1>
+ <div>${ html }</div>
+ </article>
+ <footer>
+ <a href="${ emailSettingUrl }">${ 'Email setting' }</a>
+ </footer>
+ </main>
+ <nav>
+ <a href="${ config.url }">${ config.host }</a>
+ </nav>
+ </body>
+ </html>
+ `
});
logger.info('Message sent: %s', info.messageId);