Merge branch 'develop' into sw-notification-action
This commit is contained in:
commit
2f151cc3d2
97 changed files with 696 additions and 510 deletions
|
|
@ -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)))) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
pushNotification(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);
|
||||
pushNotification(notifieeId, 'notification', packed);
|
||||
|
||||
if (type === 'follow') sendEmailNotification.follow(notifieeId, data);
|
||||
if (type === 'receiveFollowRequest') sendEmailNotification.receiveFollowRequest(notifieeId, data);
|
||||
}, 2000);
|
||||
|
||||
return notification;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
28
src/services/send-email-notification.ts
Normal file
28
src/services/send-email-notification.ts
Normal file
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue