1 // This file is part of Moodle - http://moodle.org/
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 * Retrieves messages from the server.
19 * @module core_message/message_repository
20 * @class message_repository
22 * @copyright 2016 Ryan Wyllie <ryan@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {
27 var CONVERSATION_TYPES = {
33 * Retrieve a list of messages from the server.
35 * @param {object} args The request arguments:
36 * @return {object} jQuery promise
38 var query = function(args) {
39 // Normalise the arguments to use limit/offset rather than limitnum/limitfrom.
40 if (typeof args.limit === 'undefined') {
44 if (typeof args.offset === 'undefined') {
48 if (typeof args.type === 'undefined') {
52 if (typeof args.favouritesonly === 'undefined') {
53 args.favouritesonly = false;
56 args.limitfrom = args.offset;
57 args.limitnum = args.limit;
63 methodname: 'core_message_data_for_messagearea_conversations',
67 var promise = Ajax.call([request])[0];
69 promise.fail(Notification.exception);
75 * Count the number of unread conversations (one or more messages from a user)
78 * @param {object} args The request arguments:
79 * @return {object} jQuery promise
81 var countUnreadConversations = function(args) {
83 methodname: 'core_message_get_unread_conversations_count',
87 var promise = Ajax.call([request])[0];
89 promise.fail(Notification.exception);
95 * Mark all of unread messages for a user as read.
97 * @param {object} args The request arguments:
98 * @return {object} jQuery promise
100 var markAllAsRead = function(args) {
102 methodname: 'core_message_mark_all_messages_as_read',
106 var promise = Ajax.call([request])[0];
108 promise.fail(Notification.exception);
114 * Get contacts for given user.
116 * @param {int} userId The user id
117 * @param {int} limit Limit for results
118 * @param {int} offset Offset for results
119 * @return {object} jQuery promise
121 var getContacts = function(userId, limit, offset) {
126 if (typeof limit !== 'undefined') {
127 args.limitnum = limit;
130 if (typeof offset !== 'undefined') {
131 args.limitfrom = offset;
135 methodname: 'core_message_data_for_messagearea_contacts',
139 return Ajax.call([request])[0];
143 * Request profile information as a user for a given user.
145 * @param {int} userId The requesting user
146 * @param {int} profileUserId The id of the user who's profile is being requested
147 * @return {object} jQuery promise
149 var getProfile = function(userId, profileUserId) {
151 methodname: 'core_message_data_for_messagearea_get_profile',
153 currentuserid: userId,
154 otheruserid: profileUserId
158 return Ajax.call([request])[0];
164 * @param {int} userId The requesting user
165 * @param {int} blockedUserId Id of user to block
166 * @return {object} jQuery promise
168 var blockUser = function(userId, blockedUserId) {
171 methodname: 'core_message_block_user',
174 blockeduserid: blockedUserId
178 methodname: 'core_message_get_member_info',
180 referenceuserid: userId,
181 userids: [blockedUserId],
182 includecontactrequests: true,
183 includeprivacyinfo: true
188 // Wrap both requests in a single promise so that we can catch an error
189 // from either request.
190 return $.when.apply(null, Ajax.call(requests)).then(function(reponse1, profiles) {
191 // Only return the profile.
192 return profiles.length ? profiles[0] : {};
199 * @param {int} userId The requesting user
200 * @param {int} unblockedUserId Id of user to unblock
201 * @return {object} jQuery promise
203 var unblockUser = function(userId, unblockedUserId) {
206 methodname: 'core_message_unblock_user',
209 unblockeduserid: unblockedUserId
213 methodname: 'core_message_get_member_info',
215 referenceuserid: userId,
216 userids: [unblockedUserId],
217 includecontactrequests: true,
218 includeprivacyinfo: true
223 // Wrap both requests in a single promise so that we can catch an error
224 // from either request.
225 return $.when.apply(null, Ajax.call(requests)).then(function(reponse1, profiles) {
226 // Only return the profile.
227 return profiles.length ? profiles[0] : {};
232 * Create a request to add a user as a contact.
234 * @param {int} userId The requesting user
235 * @param {int[]} requestUserIds List of user ids to add
236 * @return {object} jQuery promise
238 var createContactRequest = function(userId, requestUserIds) {
240 methodname: 'core_message_create_contact_request',
243 requesteduserid: requestUserIds
247 return Ajax.call([request])[0];
251 * Remove a list of users as contacts.
253 * @param {int} userId The requesting user
254 * @param {int[]} contactUserIds List of user ids to add
255 * @return {object} jQuery promise
257 var deleteContacts = function(userId, contactUserIds) {
260 methodname: 'core_message_delete_contacts',
263 userids: contactUserIds
267 methodname: 'core_message_get_member_info',
269 referenceuserid: userId,
270 userids: contactUserIds,
271 includecontactrequests: true,
272 includeprivacyinfo: true
277 return $.when.apply(null, Ajax.call(requests)).then(function(response1, profiles) {
278 // Return all of the profiles as an array.
284 * Get messages between two users.
286 * @param {int} currentUserId The requesting user
287 * @param {int} conversationId Other user in the conversation
288 * @param {int} limit Limit for results
289 * @param {int} offset Offset for results
290 * @param {bool} newestFirst Order results by newest first
291 * @param {int} timeFrom Only return messages after this timestamp
292 * @return {object} jQuery promise
294 var getMessages = function(currentUserId, conversationId, limit, offset, newestFirst, timeFrom) {
296 currentuserid: currentUserId,
297 convid: conversationId,
298 newest: newestFirst ? true : false
301 if (typeof limit !== 'undefined') {
302 args.limitnum = limit;
305 if (typeof offset !== 'undefined') {
306 args.limitfrom = offset;
309 if (typeof timeFrom !== 'undefined') {
310 args.timefrom = timeFrom;
314 methodname: 'core_message_get_conversation_messages',
317 return Ajax.call([request])[0];
323 * @param {int} userId The requesting user
324 * @param {string} searchString Search string
325 * @param {int} limit Limit for results
326 * @param {int} offset Offset for results
327 * @return {object} jQuery promise
329 var searchUsers = function(userId, searchString, limit, offset) {
335 if (typeof limit !== 'undefined') {
336 args.limitnum = limit;
339 if (typeof offset !== 'undefined') {
340 args.limitfrom = offset;
344 methodname: 'core_message_message_search_users',
348 return Ajax.call([request])[0];
352 * Search for messages.
354 * @param {int} userId The requesting user
355 * @param {string} searchString Search string
356 * @param {int} limit Limit for results
357 * @param {int} offset Offset for results
358 * @return {object} jQuery promise
360 var searchMessages = function(userId, searchString, limit, offset) {
366 if (typeof limit !== 'undefined') {
367 args.limitnum = limit;
370 if (typeof offset !== 'undefined') {
371 args.limitfrom = offset;
375 methodname: 'core_message_data_for_messagearea_search_messages',
379 return Ajax.call([request])[0];
383 * Send a list of messages to a user.
385 * @param {int} toUserId The recipient user id
386 * @param {string[]} messages List of messages to send
387 * @return {object} jQuery promise
389 var sendMessagesToUser = function(toUserId, messages) {
390 var formattedMessages = messages.map(function(message) {
397 methodname: 'core_message_send_instant_messages',
399 messages: formattedMessages
403 return Ajax.call([request])[0]
404 .then(function(results) {
405 // Error handling for the weird way the old function works.
406 var errors = results.reduce(function(carry, result) {
407 if (result.errormessage) {
408 carry.push(result.errormessage);
414 throw new Error(errors.join("\n"));
419 .then(function(results) {
420 // Format the results to match the other send message function.
421 return results.map(function(result) {
425 timecreated: result.timecreated,
426 useridfrom: result.useridfrom,
427 conversationid: result.conversationid
434 * Send a single message to a user.
436 * @param {int} toUserId The recipient user id
437 * @param {string} text The message text
438 * @return {object} jQuery promise
440 var sendMessageToUser = function(toUserId, text) {
441 return sendMessagesToUser(toUserId, [text])
442 .then(function(results) {
448 * Send messages to a conversation.
450 * @param {int} conversationId The conversation id
451 * @param {string[]} messages List of messages to send
452 * @return {object} jQuery promise
454 var sendMessagesToConversation = function(conversationId, messages) {
455 var formattedMessages = messages.map(function(message) {
461 methodname: 'core_message_send_messages_to_conversation',
463 conversationid: conversationId,
464 messages: formattedMessages
468 return Ajax.call([request])[0];
472 * Send a message to a conversation.
474 * @param {int} conversationId The conversation id
475 * @param {string} text The message text
476 * @return {object} jQuery promise
478 var sendMessageToConversation = function(conversationId, text) {
479 return sendMessagesToConversation(conversationId, [text])
480 .then(function(result) {
486 * Save message preferences.
488 * @param {int} userId The owner of the preferences
489 * @param {object[]} preferences New preferences values
490 * @return {object} jQuery promise
492 var savePreferences = function(userId, preferences) {
494 methodname: 'core_user_update_user_preferences',
497 preferences: preferences
500 return Ajax.call([request])[0];
504 * Get the user's preferences.
506 * @param {int} userId The target user
507 * @return {object} jQuery promise
509 var getPreferences = function(userId) {
511 methodname: 'core_user_get_user_preferences',
516 return Ajax.call([request])[0];
520 * Delete a list of messages.
522 * @param {int} userId The user to delete messages for
523 * @param {int[]} messageIds List of message ids to delete
524 * @return {object} jQuery promise
526 var deleteMessages = function(userId, messageIds) {
527 return Ajax.call(messageIds.map(function(messageId) {
529 methodname: 'core_message_delete_message',
531 messageid: messageId,
539 * Delete a conversation between two users.
541 * @param {int} userId The user to delete messages for
542 * @param {int} otherUserId The other member of the conversation
543 * @return {object} jQuery promise
545 var deleteCoversation = function(userId, otherUserId) {
547 methodname: 'core_message_delete_conversation',
550 otheruserid: otherUserId
553 return Ajax.call([request])[0];
557 * Get the list of contact requests for a user.
559 * @param {int} userId The user id
560 * @return {object} jQuery promise
562 var getContactRequests = function(userId) {
564 methodname: 'core_message_get_contact_requests',
569 return Ajax.call([request])[0];
573 * Accept a contact request.
575 * @param {int} sendingUserId The user that sent the request
576 * @param {int} recipientUserId The user that received the request
577 * @return {object} jQuery promise
579 var acceptContactRequest = function(sendingUserId, recipientUserId) {
582 methodname: 'core_message_confirm_contact_request',
584 userid: sendingUserId,
585 requesteduserid: recipientUserId
589 methodname: 'core_message_get_member_info',
591 referenceuserid: recipientUserId,
592 userids: [sendingUserId],
593 includecontactrequests: true,
594 includeprivacyinfo: true
599 // Wrap both requests in a single promise so that we can catch an error
600 // from either request.
601 return $.when.apply(null, Ajax.call(requests)).then(function(reponse1, profiles) {
602 // Only return the profile.
603 return profiles.length ? profiles[0] : {};
608 * Decline a contact request.
610 * @param {int} sendingUserId The user that sent the request
611 * @param {int} recipientUserId The user that received the request
612 * @return {object} jQuery promise
614 var declineContactRequest = function(sendingUserId, recipientUserId) {
617 methodname: 'core_message_decline_contact_request',
619 userid: sendingUserId,
620 requesteduserid: recipientUserId
624 methodname: 'core_message_get_member_info',
626 referenceuserid: recipientUserId,
627 userids: [sendingUserId],
628 includecontactrequests: true,
629 includeprivacyinfo: true
634 // Wrap both requests in a single promise so that we can catch an error
635 // from either request.
636 return $.when.apply(null, Ajax.call(requests)).then(function(reponse1, profiles) {
637 // Only return the profile.
638 return profiles.length ? profiles[0] : {};
643 * Get a conversation.
645 * @param {int} loggedInUserId The logged in user
646 * @param {int} conversationId The conversation id
647 * @param {bool} includeContactRequests Incldue contact requests between members
648 * @param {bool} includePrivacyInfo Include privacy info for members
649 * @param {int} memberLimit Limit for members
650 * @param {int} memberOffset Offset for members
651 * @param {int} messageLimit Limit for messages
652 * @param {int} messageOffset Offset for messages
653 * @param {bool} newestMessagesFirst Order the messages by newest first
654 * @return {object} jQuery promise
656 var getConversation = function(
659 includeContactRequests,
668 userid: loggedInUserId,
669 conversationid: conversationId
672 if (typeof includeContactRequests != 'undefined' && includeContactRequests !== null) {
673 args.includecontactrequests = includeContactRequests;
676 if (typeof includePrivacyInfo != 'undefined' && includePrivacyInfo !== null) {
677 args.includeprivacyinfo = includePrivacyInfo;
680 if (typeof memberLimit != 'undefined' && memberLimit !== null) {
681 args.memberlimit = memberLimit;
684 if (typeof memberOffset != 'undefined' && memberOffset !== null) {
685 args.memberoffset = memberOffset;
688 if (typeof messageLimit != 'undefined' && messageLimit !== null) {
689 args.messagelimit = messageLimit;
692 if (typeof messageOffset != 'undefined' && messageOffset !== null) {
693 args.messageoffset = messageOffset;
696 if (typeof newestMessagesFirst != 'undefined' && newestMessagesFirst !== null) {
697 args.newestmessagesfirst = newestMessagesFirst;
701 methodname: 'core_message_get_conversation',
705 return Ajax.call([request])[0];
709 * Get a conversation between users.
711 * @param {int} loggedInUserId The logged in user
712 * @param {int} otherUserId The other user id
713 * @param {bool} includeContactRequests Incldue contact requests between members
714 * @param {bool} includePrivacyInfo Include privacy info for members
715 * @param {int} memberLimit Limit for members
716 * @param {int} memberOffset Offset for members
717 * @param {int} messageLimit Limit for messages
718 * @param {int} messageOffset Offset for messages
719 * @param {bool} newestMessagesFirst Order the messages by newest first
720 * @return {object} jQuery promise
722 var getConversationBetweenUsers = function(
725 includeContactRequests,
734 userid: loggedInUserId,
735 otheruserid: otherUserId
738 if (typeof includeContactRequests != 'undefined' && includeContactRequests !== null) {
739 args.includecontactrequests = includeContactRequests;
742 if (typeof includePrivacyInfo != 'undefined' && includePrivacyInfo !== null) {
743 args.includeprivacyinfo = includePrivacyInfo;
746 if (typeof memberLimit != 'undefined' && memberLimit !== null) {
747 args.memberlimit = memberLimit;
750 if (typeof memberOffset != 'undefined' && memberOffset !== null) {
751 args.memberoffset = memberOffset;
754 if (typeof messageLimit != 'undefined' && messageLimit !== null) {
755 args.messagelimit = messageLimit;
758 if (typeof messageOffset != 'undefined' && messageOffset !== null) {
759 args.messageoffset = messageOffset;
762 if (typeof newestMessagesFirst != 'undefined' && newestMessagesFirst !== null) {
763 args.newestmessagesfirst = newestMessagesFirst;
767 methodname: 'core_message_get_conversation_between_users',
771 return Ajax.call([request])[0];
775 * Get the conversations for a user.
777 * @param {int} userId The logged in user
778 * @param {int|null} type The type of conversation to get
779 * @param {int} limit Limit for results
780 * @param {int} offset Offset for results
781 * @param {bool|null} favourites If favourites should be included or not
782 * @return {object} jQuery promise
784 var getConversations = function(
796 if (typeof limit != 'undefined' && limit !== null) {
797 args.limitnum = limit;
800 if (typeof offset != 'undefined' && offset !== null) {
801 args.limitfrom = offset;
804 if (typeof favourites != 'undefined' && favourites !== null) {
805 args.favourites = favourites;
809 methodname: 'core_message_get_conversations',
813 return Ajax.call([request])[0]
814 .then(function(result) {
815 if (result.conversations.length) {
816 result.conversations = result.conversations.map(function(conversation) {
817 if (conversation.type == CONVERSATION_TYPES.PRIVATE) {
818 var otherUser = conversation.members.length ? conversation.members[0] : null;
821 conversation.name = conversation.name ? conversation.name : otherUser.fullname;
822 conversation.imageurl = conversation.imageurl ? conversation.imageurl : otherUser.profileimageurl;
835 * Get the conversations for a user.
837 * @param {int} conversationId The conversation id
838 * @param {int} loggedInUserId The logged in user
839 * @param {int} limit Limit for results
840 * @param {int} offset Offset for results
841 * @param {bool} includeContactRequests If contact requests should be included in result
842 * @return {object} jQuery promise
844 var getConversationMembers = function(conversationId, loggedInUserId, limit, offset, includeContactRequests) {
846 userid: loggedInUserId,
847 conversationid: conversationId
850 if (typeof limit != 'undefined' && limit !== null) {
851 args.limitnum = limit;
854 if (typeof offset != 'undefined' && offset !== null) {
855 args.limitfrom = offset;
858 if (typeof includeContactRequests != 'undefined' && includeContactRequests !== null) {
859 args.includecontactrequests = includeContactRequests;
863 methodname: 'core_message_get_conversation_members',
867 return Ajax.call([request])[0];
871 * Set a list of conversations to set as favourites for the given user.
873 * @param {int} userId The user id
874 * @param {array} conversationIds List of conversation ids to set as favourite
875 * @return {object} jQuery promise
877 var setFavouriteConversations = function(userId, conversationIds) {
880 methodname: 'core_message_set_favourite_conversations',
883 conversations: conversationIds
886 return Ajax.call([request])[0];
890 * Set a list of conversations to unset as favourites for the given user.
892 * @param {int} userId The user id
893 * @param {array} conversationIds List of conversation ids to unset as favourite
894 * @return {object} jQuery promise
896 var unsetFavouriteConversations = function(userId, conversationIds) {
899 methodname: 'core_message_unset_favourite_conversations',
902 conversations: conversationIds
905 return Ajax.call([request])[0];
909 * Get a list of user's member info.
911 * @param {int} referenceUserId The user id
912 * @param {array} userIds List of user ids to get
913 * @param {bool} includeContactRequests Include contact requests between users in response
914 * @param {bool} includePrivacyInfo Include privacy info for reference user in response
915 * @return {object} jQuery promise
917 var getMemberInfo = function(referenceUserId, userIds, includeContactRequests, includePrivacyInfo) {
919 referenceuserid: referenceUserId,
923 if (typeof includeContactRequests != 'undefined') {
924 args.includecontactrequests = includeContactRequests;
927 if (typeof includePrivacyInfo != 'undefined') {
928 args.includeprivacyinfo = includePrivacyInfo;
932 methodname: 'core_message_get_member_info',
935 return Ajax.call([request])[0];
939 * Get a list of user's member info.
941 * @param {int} userId The user id to mark as read for
942 * @param {int} conversationId The conversation to mark as read
943 * @return {object} jQuery promise
945 var markAllConversationMessagesAsRead = function(userId, conversationId) {
948 methodname: 'core_message_mark_all_conversation_messages_as_read',
951 conversationid: conversationId
954 return Ajax.call([request])[0];
959 countUnreadConversations: countUnreadConversations,
960 markAllAsRead: markAllAsRead,
961 getContacts: getContacts,
962 getProfile: getProfile,
963 blockUser: blockUser,
964 unblockUser: unblockUser,
965 createContactRequest: createContactRequest,
966 deleteContacts: deleteContacts,
967 getMessages: getMessages,
968 searchUsers: searchUsers,
969 searchMessages: searchMessages,
970 sendMessagesToUser: sendMessagesToUser,
971 sendMessageToUser: sendMessageToUser,
972 sendMessagesToConversation: sendMessagesToConversation,
973 sendMessageToConversation: sendMessageToConversation,
974 savePreferences: savePreferences,
975 getPreferences: getPreferences,
976 deleteMessages: deleteMessages,
977 deleteCoversation: deleteCoversation,
978 getContactRequests: getContactRequests,
979 acceptContactRequest: acceptContactRequest,
980 declineContactRequest: declineContactRequest,
981 getConversation: getConversation,
982 getConversationBetweenUsers: getConversationBetweenUsers,
983 getConversations: getConversations,
984 getConversationMembers: getConversationMembers,
985 setFavouriteConversations: setFavouriteConversations,
986 unsetFavouriteConversations: unsetFavouriteConversations,
987 getMemberInfo: getMemberInfo,
988 markAllConversationMessagesAsRead: markAllConversationMessagesAsRead