@@ -743,6 +743,162 @@ const dmCreateResponseSchema = ajv.compile<{ room: IRoom & { rid: string } }>({
743743 additionalProperties : false ,
744744} ) ;
745745
746+ const paginatedMessagesResponseSchema = ajv . compile < { messages : IMessage [ ] ; offset : number ; count : number ; total : number } > ( {
747+ type : 'object' ,
748+ properties : {
749+ messages : { type : 'array' , items : { type : 'object' } } ,
750+ offset : { type : 'number' } ,
751+ count : { type : 'number' } ,
752+ total : { type : 'number' } ,
753+ success : { type : 'boolean' , enum : [ true ] } ,
754+ } ,
755+ required : [ 'messages' , 'offset' , 'count' , 'total' , 'success' ] ,
756+ additionalProperties : false ,
757+ } ) ;
758+
759+ const paginatedImsResponseSchema = ajv . compile < { ims : IRoom [ ] ; offset : number ; count : number ; total : number } > ( {
760+ type : 'object' ,
761+ properties : {
762+ ims : { type : 'array' , items : { type : 'object' } } ,
763+ offset : { type : 'number' } ,
764+ count : { type : 'number' } ,
765+ total : { type : 'number' } ,
766+ success : { type : 'boolean' , enum : [ true ] } ,
767+ } ,
768+ required : [ 'ims' , 'offset' , 'count' , 'total' , 'success' ] ,
769+ additionalProperties : false ,
770+ } ) ;
771+
772+ const dmMessagesOthersEndpointsProps = {
773+ authRequired : true as const ,
774+ permissionsRequired : [ 'view-room-administration' ] ,
775+ response : {
776+ 200 : paginatedMessagesResponseSchema ,
777+ 400 : validateBadRequestErrorResponse ,
778+ 401 : validateUnauthorizedErrorResponse ,
779+ 403 : validateForbiddenErrorResponse ,
780+ } ,
781+ } ;
782+
783+ const dmMessagesOthersAction = < Path extends string > ( _name : Path ) : TypedAction < typeof dmMessagesOthersEndpointsProps , Path > =>
784+ async function action ( ) {
785+ if ( settings . get ( 'API_Enable_Direct_Message_History_EndPoint' ) !== true ) {
786+ throw new Meteor . Error ( 'error-endpoint-disabled' , 'This endpoint is disabled' , {
787+ route : '/api/v1/im.messages.others' ,
788+ } ) ;
789+ }
790+
791+ const { roomId } = this . queryParams ;
792+ if ( ! roomId ) {
793+ throw new Meteor . Error ( 'error-roomid-param-not-provided' , 'The parameter "roomId" is required' ) ;
794+ }
795+
796+ const room = await Rooms . findOneById < Pick < IRoom , '_id' | 't' > > ( roomId , { projection : { _id : 1 , t : 1 } } ) ;
797+ if ( ! room || room ?. t !== 'd' ) {
798+ throw new Meteor . Error ( 'error-room-not-found' , `No direct message room found by the id of: ${ roomId } ` ) ;
799+ }
800+
801+ const { offset, count } = await getPaginationItems ( this . queryParams ) ;
802+ const { sort, fields, query } = await this . parseJsonQuery ( ) ;
803+ const ourQuery = Object . assign ( { } , query , { rid : room . _id } ) ;
804+
805+ const { cursor, totalCount } = Messages . findPaginated < IMessage > ( ourQuery , {
806+ sort : sort || { ts : - 1 } ,
807+ skip : offset ,
808+ limit : count ,
809+ projection : fields ,
810+ } ) ;
811+
812+ const [ msgs , total ] = await Promise . all ( [ cursor . toArray ( ) , totalCount ] ) ;
813+
814+ if ( ! msgs ) {
815+ throw new Meteor . Error ( 'error-no-messages' , 'No messages found' ) ;
816+ }
817+
818+ return API . v1 . success ( {
819+ messages : await normalizeMessagesForUser ( msgs , this . userId ) ,
820+ offset,
821+ count : msgs . length ,
822+ total,
823+ } ) ;
824+ } ;
825+
826+ const dmListEndpointsProps = {
827+ authRequired : true as const ,
828+ response : {
829+ 200 : paginatedImsResponseSchema ,
830+ 400 : validateBadRequestErrorResponse ,
831+ 401 : validateUnauthorizedErrorResponse ,
832+ } ,
833+ } ;
834+
835+ const dmListAction = < Path extends string > ( _name : Path ) : TypedAction < typeof dmListEndpointsProps , Path > =>
836+ async function action ( ) {
837+ const { offset, count } = await getPaginationItems ( this . queryParams ) ;
838+ const { sort = { name : 1 } , fields } = await this . parseJsonQuery ( ) ;
839+
840+ // TODO: CACHE: Add Breaking notice since we removed the query param
841+
842+ const subscriptions = await Subscriptions . find ( { 'u._id' : this . userId , 't' : 'd' } , { projection : { rid : 1 } } )
843+ . map ( ( item ) => item . rid )
844+ . toArray ( ) ;
845+
846+ const { cursor, totalCount } = Rooms . findPaginated (
847+ { t : 'd' , _id : { $in : subscriptions } } ,
848+ {
849+ sort,
850+ skip : offset ,
851+ limit : count ,
852+ projection : fields ,
853+ } ,
854+ ) ;
855+
856+ const [ ims , total ] = await Promise . all ( [ cursor . toArray ( ) , totalCount ] ) ;
857+
858+ return API . v1 . success ( {
859+ ims : await Promise . all ( ims . map ( ( room : IRoom ) => composeRoomWithLastMessage ( room , this . userId ) ) ) ,
860+ offset,
861+ count : ims . length ,
862+ total,
863+ } ) ;
864+ } ;
865+
866+ const dmListEveryoneEndpointsProps = {
867+ authRequired : true as const ,
868+ permissionsRequired : [ 'view-room-administration' ] ,
869+ response : {
870+ 200 : paginatedImsResponseSchema ,
871+ 400 : validateBadRequestErrorResponse ,
872+ 401 : validateUnauthorizedErrorResponse ,
873+ 403 : validateForbiddenErrorResponse ,
874+ } ,
875+ } ;
876+
877+ const dmListEveryoneAction = < Path extends string > ( _name : Path ) : TypedAction < typeof dmListEveryoneEndpointsProps , Path > =>
878+ async function action ( ) {
879+ const { offset, count } : { offset : number ; count : number } = await getPaginationItems ( this . queryParams ) ;
880+ const { sort, fields, query } = await this . parseJsonQuery ( ) ;
881+
882+ const { cursor, totalCount } = Rooms . findPaginated (
883+ { ...query , t : 'd' } ,
884+ {
885+ sort : sort || { name : 1 } ,
886+ skip : offset ,
887+ limit : count ,
888+ projection : fields ,
889+ } ,
890+ ) ;
891+
892+ const [ rooms , total ] = await Promise . all ( [ cursor . toArray ( ) , totalCount ] ) ;
893+
894+ return API . v1 . success ( {
895+ ims : await Promise . all ( rooms . map ( ( room : IRoom ) => composeRoomWithLastMessage ( room , this . userId ) ) ) ,
896+ offset,
897+ count : rooms . length ,
898+ total,
899+ } ) ;
900+ } ;
901+
746902const dmEndpoints = API . v1
747903 . post ( 'im.delete' , dmDeleteEndpointsProps , dmDeleteAction ( 'im.delete' ) )
748904 . post ( 'dm.delete' , dmDeleteEndpointsProps , dmDeleteAction ( 'dm.delete' ) )
@@ -809,121 +965,13 @@ const dmEndpoints = API.v1
809965 . get ( 'dm.messages' , dmMessagesEndpointsProps , dmMessagesAction ( 'dm.messages' ) )
810966 . get ( 'im.messages' , dmMessagesEndpointsProps , dmMessagesAction ( 'im.messages' ) )
811967 . get ( 'dm.history' , dmHistoryEndpointsProps , dmHistoryAction ( 'dm.history' ) )
812- . get ( 'im.history' , dmHistoryEndpointsProps , dmHistoryAction ( 'im.history' ) ) ;
813-
814- API . v1 . addRoute (
815- [ 'dm.messages.others' , 'im.messages.others' ] ,
816- { authRequired : true , permissionsRequired : [ 'view-room-administration' ] } ,
817- {
818- async get ( ) {
819- if ( settings . get ( 'API_Enable_Direct_Message_History_EndPoint' ) !== true ) {
820- throw new Meteor . Error ( 'error-endpoint-disabled' , 'This endpoint is disabled' , {
821- route : '/api/v1/im.messages.others' ,
822- } ) ;
823- }
824-
825- const { roomId } = this . queryParams ;
826- if ( ! roomId ) {
827- throw new Meteor . Error ( 'error-roomid-param-not-provided' , 'The parameter "roomId" is required' ) ;
828- }
829-
830- const room = await Rooms . findOneById < Pick < IRoom , '_id' | 't' > > ( roomId , { projection : { _id : 1 , t : 1 } } ) ;
831- if ( ! room || room ?. t !== 'd' ) {
832- throw new Meteor . Error ( 'error-room-not-found' , `No direct message room found by the id of: ${ roomId } ` ) ;
833- }
834-
835- const { offset, count } = await getPaginationItems ( this . queryParams ) ;
836- const { sort, fields, query } = await this . parseJsonQuery ( ) ;
837- const ourQuery = Object . assign ( { } , query , { rid : room . _id } ) ;
838-
839- const { cursor, totalCount } = Messages . findPaginated < IMessage > ( ourQuery , {
840- sort : sort || { ts : - 1 } ,
841- skip : offset ,
842- limit : count ,
843- projection : fields ,
844- } ) ;
845-
846- const [ msgs , total ] = await Promise . all ( [ cursor . toArray ( ) , totalCount ] ) ;
847-
848- if ( ! msgs ) {
849- throw new Meteor . Error ( 'error-no-messages' , 'No messages found' ) ;
850- }
851-
852- return API . v1 . success ( {
853- messages : await normalizeMessagesForUser ( msgs , this . userId ) ,
854- offset,
855- count : msgs . length ,
856- total,
857- } ) ;
858- } ,
859- } ,
860- ) ;
861-
862- API . v1 . addRoute (
863- [ 'dm.list' , 'im.list' ] ,
864- { authRequired : true } ,
865- {
866- async get ( ) {
867- const { offset, count } = await getPaginationItems ( this . queryParams ) ;
868- const { sort = { name : 1 } , fields } = await this . parseJsonQuery ( ) ;
869-
870- // TODO: CACHE: Add Breaking notice since we removed the query param
871-
872- const subscriptions = await Subscriptions . find ( { 'u._id' : this . userId , 't' : 'd' } , { projection : { rid : 1 } } )
873- . map ( ( item ) => item . rid )
874- . toArray ( ) ;
875-
876- const { cursor, totalCount } = Rooms . findPaginated (
877- { t : 'd' , _id : { $in : subscriptions } } ,
878- {
879- sort,
880- skip : offset ,
881- limit : count ,
882- projection : fields ,
883- } ,
884- ) ;
885-
886- const [ ims , total ] = await Promise . all ( [ cursor . toArray ( ) , totalCount ] ) ;
887-
888- return API . v1 . success ( {
889- ims : await Promise . all ( ims . map ( ( room : IRoom ) => composeRoomWithLastMessage ( room , this . userId ) ) ) ,
890- offset,
891- count : ims . length ,
892- total,
893- } ) ;
894- } ,
895- } ,
896- ) ;
897-
898- API . v1 . addRoute (
899- [ 'dm.list.everyone' , 'im.list.everyone' ] ,
900- { authRequired : true , permissionsRequired : [ 'view-room-administration' ] } ,
901- {
902- async get ( ) {
903- const { offset, count } : { offset : number ; count : number } = await getPaginationItems ( this . queryParams ) ;
904- const { sort, fields, query } = await this . parseJsonQuery ( ) ;
905-
906- const { cursor, totalCount } = Rooms . findPaginated (
907- { ...query , t : 'd' } ,
908- {
909- sort : sort || { name : 1 } ,
910- skip : offset ,
911- limit : count ,
912- projection : fields ,
913- } ,
914- ) ;
915-
916- const [ rooms , total ] = await Promise . all ( [ cursor . toArray ( ) , totalCount ] ) ;
917-
918- return API . v1 . success ( {
919- ims : await Promise . all ( rooms . map ( ( room : IRoom ) => composeRoomWithLastMessage ( room , this . userId ) ) ) ,
920- offset,
921- count : rooms . length ,
922- total,
923- } ) ;
924- } ,
925- } ,
926- ) ;
968+ . get ( 'im.history' , dmHistoryEndpointsProps , dmHistoryAction ( 'im.history' ) )
969+ . get ( 'dm.messages.others' , dmMessagesOthersEndpointsProps , dmMessagesOthersAction ( 'dm.messages.others' ) )
970+ . get ( 'im.messages.others' , dmMessagesOthersEndpointsProps , dmMessagesOthersAction ( 'im.messages.others' ) )
971+ . get ( 'dm.list' , dmListEndpointsProps , dmListAction ( 'dm.list' ) )
972+ . get ( 'im.list' , dmListEndpointsProps , dmListAction ( 'im.list' ) )
973+ . get ( 'dm.list.everyone' , dmListEveryoneEndpointsProps , dmListEveryoneAction ( 'dm.list.everyone' ) )
974+ . get ( 'im.list.everyone' , dmListEveryoneEndpointsProps , dmListEveryoneAction ( 'im.list.everyone' ) ) ;
927975
928976export type DmEndpoints = ExtractRoutesFromAPI < typeof dmEndpoints > ;
929977
0 commit comments