diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2021-02-19 21:42:47 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2021-02-19 21:42:47 +0900 |
| commit | d6c8b9b99470db45c201229b5c9235e7be3067de (patch) | |
| tree | 01e5fccad6d84cf1e7f41e0a5e3aae955f3695e0 /src/services | |
| parent | Merge branch 'develop' (diff) | |
| parent | 12.70.0 (diff) | |
| download | misskey-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.ts | 5 | ||||
| -rw-r--r-- | src/services/create-notification.ts | 27 | ||||
| -rw-r--r-- | src/services/following/create.ts | 3 | ||||
| -rw-r--r-- | src/services/following/requests/accept-all.ts | 3 | ||||
| -rw-r--r-- | src/services/messages/delete.ts | 5 | ||||
| -rw-r--r-- | src/services/note/create.ts | 5 | ||||
| -rw-r--r-- | src/services/send-email-notification.ts | 28 | ||||
| -rw-r--r-- | src/services/send-email.ts | 91 |
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); |