2023-01-13 05:40:33 +01:00
import { publishMainStream } from "@/services/stream.js" ;
import { pushNotification } from "@/services/push-notification.js" ;
import {
Notifications ,
Mutings ,
NoteThreadMutings ,
UserProfiles ,
Users ,
2023-05-01 02:22:50 +02:00
Followings ,
2023-01-13 05:40:33 +01:00
} from "@/models/index.js" ;
import { genId } from "@/misc/gen-id.js" ;
import type { User } from "@/models/entities/user.js" ;
import type { Notification } from "@/models/entities/notification.js" ;
import { sendEmailNotification } from "./send-email-notification.js" ;
2023-05-01 02:22:50 +02:00
import { shouldSilenceInstance } from "@/misc/should-block-instance.js" ;
2016-12-28 23:49:51 +01:00
2019-04-07 14:50:36 +02:00
export async function createNotification (
2023-01-13 05:40:33 +01:00
notifieeId : User [ "id" ] ,
type : Notification [ "type" ] ,
data : Partial < Notification > ,
2019-04-07 14:50:36 +02:00
) {
2023-01-13 05:40:33 +01:00
if ( data . notifierId && notifieeId === data . notifierId ) {
2019-04-07 14:50:36 +02:00
return null ;
2016-12-28 23:49:51 +01:00
}
2023-05-01 02:22:50 +02:00
if (
data . notifierId &&
[ "mention" , "reply" , "renote" , "quote" , "reaction" ] . includes ( type )
) {
const notifier = await Users . findOneBy ( { id : data.notifierId } ) ;
// suppress if the notifier does not exist or is silenced.
if ( ! notifier ) return null ;
// suppress if the notifier is silenced or in a silenced instance, and not followed by the notifiee.
if (
( notifier . isSilenced ||
( Users . isRemoteUser ( notifier ) &&
( await shouldSilenceInstance ( notifier . host ) ) ) ) &&
! ( await Followings . exist ( {
where : { followerId : notifieeId , followeeId : data.notifierId } ,
} ) )
)
return null ;
}
2022-03-26 07:34:00 +01:00
const profile = await UserProfiles . findOneBy ( { userId : notifieeId } ) ;
2020-08-22 03:06:17 +02:00
2020-09-18 15:18:21 +02:00
const isMuted = profile ? . mutingNotificationTypes . includes ( type ) ;
2020-08-22 03:06:17 +02:00
2022-12-26 04:13:20 +01:00
if ( data . note != null ) {
const threadMute = await NoteThreadMutings . findOneBy ( {
userId : notifieeId ,
threadId : data.note.threadId || data . note . id ,
} ) ;
if ( threadMute ) {
return null ;
}
}
2020-03-28 10:07:41 +01:00
// Create notification
2022-01-02 18:20:30 +01:00
const notification = await Notifications . insert ( {
2019-04-07 14:50:36 +02:00
id : genId ( ) ,
2018-03-29 07:48:47 +02:00
createdAt : new Date ( ) ,
2019-04-07 14:50:36 +02:00
notifieeId : notifieeId ,
2016-12-28 23:49:51 +01:00
type : type ,
2020-08-22 03:06:17 +02:00
// 相手がこの通知をミュートしているようなら、既読を予めつけておく
isRead : isMuted ,
2021-12-09 15:58:30 +01:00
. . . data ,
2023-01-13 05:40:33 +01:00
} as Partial < Notification > ) . then ( ( x ) = >
Notifications . findOneByOrFail ( x . identifiers [ 0 ] ) ,
) ;
2016-12-28 23:49:51 +01:00
2021-03-21 14:26:45 +01:00
const packed = await Notifications . pack ( notification , { } ) ;
2018-06-21 04:35:28 +02:00
2016-12-28 23:49:51 +01:00
// Publish notification event
2023-01-13 05:40:33 +01:00
publishMainStream ( notifieeId , "notification" , packed ) ;
2018-05-28 18:22:39 +02:00
2018-10-07 19:10:46 +02:00
// 2秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する
2017-11-20 01:09:11 +01:00
setTimeout ( async ( ) = > {
2022-03-26 07:34:00 +01:00
const fresh = await Notifications . findOneBy ( { id : notification.id } ) ;
2019-04-12 18:43:22 +02:00
if ( fresh == null ) return ; // 既に削除されているかもしれない
2023-05-08 11:36:32 +02:00
// We execute this before, because the server side "read" check doesnt work well with push notifications, the app and service worker will decide themself
// when it is best to show push notifications
pushNotification ( notifieeId , "notification" , packed ) ;
2021-02-13 04:28:26 +01:00
if ( fresh . isRead ) return ;
//#region ただしミュートしているユーザーからの通知なら無視
2022-03-26 07:34:00 +01:00
const mutings = await Mutings . findBy ( {
2021-12-09 15:58:30 +01:00
muterId : notifieeId ,
2021-02-13 04:28:26 +01:00
} ) ;
2023-01-13 05:40:33 +01:00
if (
data . notifierId &&
mutings . map ( ( m ) = > m . muteeId ) . includes ( data . notifierId )
) {
2021-02-13 04:28:26 +01:00
return ;
2017-11-20 01:09:11 +01:00
}
2021-02-13 04:28:26 +01:00
//#endregion
2023-01-13 05:40:33 +01:00
publishMainStream ( notifieeId , "unreadNotification" , packed ) ;
2021-02-13 04:28:26 +01:00
2023-01-13 05:40:33 +01:00
if ( type === "follow" )
sendEmailNotification . follow (
notifieeId ,
await Users . findOneByOrFail ( { id : data.notifierId ! } ) ,
) ;
if ( type === "receiveFollowRequest" )
sendEmailNotification . receiveFollowRequest (
notifieeId ,
await Users . findOneByOrFail ( { id : data.notifierId ! } ) ,
) ;
2018-10-07 19:10:46 +02:00
} , 2000 ) ;
2019-04-07 14:50:36 +02:00
return notification ;
}