activity.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import {
  2. Types, Document, Model, Schema,
  3. } from 'mongoose';
  4. import { getOrCreateModel, getModelSafely } from '@growi/core';
  5. import loggerFactory from '../../utils/logger';
  6. import ActivityDefine from '../util/activityDefine';
  7. import activityEvent from '../events/activity';
  8. import Subscription from './subscription';
  9. const logger = loggerFactory('growi:models:activity');
  10. export interface ActivityDocument extends Document {
  11. _id: Types.ObjectId
  12. user: Types.ObjectId | any
  13. targetModel: string
  14. target: string
  15. action: string
  16. event: Types.ObjectId
  17. eventModel: string
  18. createdAt: Date
  19. getNotificationTargetUsers(): Promise<any[]>
  20. }
  21. export interface ActivityModel extends Model<ActivityDocument> {
  22. getActionUsersFromActivities(activities: ActivityDocument[]): any[]
  23. }
  24. // TODO: add revision id
  25. const activitySchema = new Schema<ActivityDocument, ActivityModel>({
  26. user: {
  27. type: Schema.Types.ObjectId,
  28. ref: 'User',
  29. index: true,
  30. require: true,
  31. },
  32. targetModel: {
  33. type: String,
  34. require: true,
  35. enum: ActivityDefine.getSupportTargetModelNames(),
  36. },
  37. target: {
  38. type: Schema.Types.ObjectId,
  39. refPath: 'targetModel',
  40. require: true,
  41. },
  42. action: {
  43. type: String,
  44. require: true,
  45. enum: ActivityDefine.getSupportActionNames(),
  46. },
  47. event: {
  48. type: Schema.Types.ObjectId,
  49. refPath: 'eventModel',
  50. },
  51. eventModel: {
  52. type: String,
  53. enum: ActivityDefine.getSupportEventModelNames(),
  54. },
  55. createdAt: {
  56. type: Date,
  57. default: Date.now,
  58. },
  59. });
  60. activitySchema.index({ target: 1, action: 1 });
  61. activitySchema.index({
  62. user: 1, target: 1, action: 1, createdAt: 1,
  63. }, { unique: true });
  64. activitySchema.methods.getNotificationTargetUsers = async function() {
  65. const User = getModelSafely('User') || require('~/server/models/user')();
  66. const { user: actionUser, target } = this;
  67. const [subscribeUsers, unsubscribeUsers] = await Promise.all([
  68. Subscription.getSubscription((target as any) as Types.ObjectId),
  69. Subscription.getUnsubscription((target as any) as Types.ObjectId),
  70. ]);
  71. const unique = array => Object.values(array.reduce((objects, object) => ({ ...objects, [object.toString()]: object }), {}));
  72. const filter = (array, pull) => {
  73. const ids = pull.map(object => object.toString());
  74. return array.filter(object => !ids.includes(object.toString()));
  75. };
  76. const notificationUsers = filter(unique([...subscribeUsers]), [...unsubscribeUsers, actionUser]);
  77. const activeNotificationUsers = await User.find({
  78. _id: { $in: notificationUsers },
  79. status: User.STATUS_ACTIVE,
  80. }).distinct('_id');
  81. return activeNotificationUsers;
  82. };
  83. activitySchema.post('save', async(savedActivity: ActivityDocument) => {
  84. let targetUsers: Types.ObjectId[] = [];
  85. try {
  86. targetUsers = await savedActivity.getNotificationTargetUsers();
  87. }
  88. catch (err) {
  89. logger.error(err);
  90. }
  91. activityEvent.emit('create', targetUsers, savedActivity);
  92. });
  93. export default getOrCreateModel<ActivityDocument, ActivityModel>('Activity', activitySchema);