chore: add endpoints for retrieving call history data (#37702)
parent
3837d205df
commit
9b3fa8d7b1
@ -0,0 +1,206 @@ |
||||
import type { CallHistoryItem, IMediaCall } from '@rocket.chat/core-typings'; |
||||
import { CallHistory, MediaCalls } from '@rocket.chat/models'; |
||||
import type { PaginatedRequest, PaginatedResult } from '@rocket.chat/rest-typings'; |
||||
import { |
||||
ajv, |
||||
validateNotFoundErrorResponse, |
||||
validateBadRequestErrorResponse, |
||||
validateUnauthorizedErrorResponse, |
||||
} from '@rocket.chat/rest-typings'; |
||||
|
||||
import type { ExtractRoutesFromAPI } from '../ApiClass'; |
||||
import { API } from '../api'; |
||||
import { getPaginationItems } from '../helpers/getPaginationItems'; |
||||
|
||||
type CallHistoryList = PaginatedRequest<Record<never, never>>; |
||||
|
||||
const CallHistoryListSchema = { |
||||
type: 'object', |
||||
properties: { |
||||
count: { |
||||
type: 'number', |
||||
}, |
||||
offset: { |
||||
type: 'number', |
||||
}, |
||||
sort: { |
||||
type: 'string', |
||||
}, |
||||
}, |
||||
required: [], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
export const isCallHistoryListProps = ajv.compile<CallHistoryList>(CallHistoryListSchema); |
||||
|
||||
const callHistoryListEndpoints = API.v1.get( |
||||
'call-history.list', |
||||
{ |
||||
response: { |
||||
200: ajv.compile< |
||||
PaginatedResult<{ |
||||
items: CallHistoryItem[]; |
||||
}> |
||||
>({ |
||||
additionalProperties: false, |
||||
type: 'object', |
||||
properties: { |
||||
count: { |
||||
type: 'number', |
||||
description: 'The number of history items returned in this response.', |
||||
}, |
||||
offset: { |
||||
type: 'number', |
||||
description: 'The number of history items that were skipped in this response.', |
||||
}, |
||||
total: { |
||||
type: 'number', |
||||
description: 'The total number of history items that match the query.', |
||||
}, |
||||
success: { |
||||
type: 'boolean', |
||||
description: 'Indicates if the request was successful.', |
||||
}, |
||||
items: { |
||||
type: 'array', |
||||
items: { |
||||
$ref: '#/components/schemas/CallHistoryItem', |
||||
}, |
||||
}, |
||||
}, |
||||
required: ['count', 'offset', 'total', 'items', 'success'], |
||||
}), |
||||
400: validateBadRequestErrorResponse, |
||||
403: validateUnauthorizedErrorResponse, |
||||
}, |
||||
query: isCallHistoryListProps, |
||||
authRequired: true, |
||||
}, |
||||
async function action() { |
||||
const { offset, count } = await getPaginationItems(this.queryParams as Record<string, string | number | null | undefined>); |
||||
const { sort } = await this.parseJsonQuery(); |
||||
|
||||
const filter = { |
||||
uid: this.userId, |
||||
}; |
||||
|
||||
const { cursor, totalCount } = CallHistory.findPaginated(filter, { |
||||
sort: sort || { ts: -1 }, |
||||
skip: offset, |
||||
limit: count, |
||||
}); |
||||
const [items, total] = await Promise.all([cursor.toArray(), totalCount]); |
||||
|
||||
return API.v1.success({ |
||||
items, |
||||
count: items.length, |
||||
offset, |
||||
total, |
||||
}); |
||||
}, |
||||
); |
||||
|
||||
type CallHistoryListEndpoints = ExtractRoutesFromAPI<typeof callHistoryListEndpoints>; |
||||
|
||||
type CallHistoryInfo = { historyId: string; callId: never } | { callId: string; historyId: never }; |
||||
|
||||
const CallHistoryInfoSchema = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
historyId: { |
||||
type: 'string', |
||||
nullable: false, |
||||
}, |
||||
}, |
||||
required: ['historyId'], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
callId: { |
||||
type: 'string', |
||||
nullable: false, |
||||
}, |
||||
}, |
||||
required: ['callId'], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isCallHistoryInfoProps = ajv.compile<CallHistoryInfo>(CallHistoryInfoSchema); |
||||
|
||||
const callHistoryInfoEndpoints = API.v1.get( |
||||
'call-history.info', |
||||
{ |
||||
response: { |
||||
200: ajv.compile<{ |
||||
item: CallHistoryItem; |
||||
call?: IMediaCall; |
||||
}>({ |
||||
additionalProperties: false, |
||||
type: 'object', |
||||
properties: { |
||||
item: { |
||||
$ref: '#/components/schemas/CallHistoryItem', |
||||
description: 'The requested call history item.', |
||||
}, |
||||
call: { |
||||
type: 'object', |
||||
$ref: '#/components/schemas/IMediaCall', |
||||
description: 'The call information for the requested call history item.', |
||||
nullable: true, |
||||
}, |
||||
success: { |
||||
type: 'boolean', |
||||
description: 'Indicates if the request was successful.', |
||||
}, |
||||
}, |
||||
required: ['item', 'success'], |
||||
}), |
||||
400: validateBadRequestErrorResponse, |
||||
403: validateUnauthorizedErrorResponse, |
||||
404: validateNotFoundErrorResponse, |
||||
}, |
||||
query: isCallHistoryInfoProps, |
||||
authRequired: true, |
||||
}, |
||||
async function action() { |
||||
if (!this.queryParams.historyId && !this.queryParams.callId) { |
||||
return API.v1.failure(); |
||||
} |
||||
|
||||
const item = await (this.queryParams.historyId |
||||
? CallHistory.findOneByIdAndUid(this.queryParams.historyId, this.userId) |
||||
: CallHistory.findOneByCallIdAndUid(this.queryParams.callId, this.userId)); |
||||
|
||||
if (!item) { |
||||
return API.v1.notFound(); |
||||
} |
||||
|
||||
if (item.type === 'media-call' && item.callId) { |
||||
const call = await MediaCalls.findOneById(item.callId); |
||||
if (call) { |
||||
return API.v1.success({ |
||||
item, |
||||
call, |
||||
}); |
||||
} |
||||
} |
||||
|
||||
return API.v1.success({ item }); |
||||
}, |
||||
); |
||||
|
||||
type CallHistoryInfoEndpoints = ExtractRoutesFromAPI<typeof callHistoryInfoEndpoints>; |
||||
|
||||
declare module '@rocket.chat/rest-typings' { |
||||
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface
|
||||
interface Endpoints extends CallHistoryListEndpoints {} |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface
|
||||
interface Endpoints extends CallHistoryInfoEndpoints {} |
||||
} |
||||
@ -0,0 +1,197 @@ |
||||
import { CallHistory, MediaCalls } from '@rocket.chat/models'; |
||||
|
||||
export async function addCallHistoryTestData(uid: string, extraUid: string): Promise<void> { |
||||
const callId1 = 'rocketchat.internal.call.test'; |
||||
const callId2 = 'rocketchat.internal.call.test.2'; |
||||
const callId3 = 'rocketchat.internal.call.test.3'; |
||||
const callId4 = 'rocketchat.internal.call.test.4'; |
||||
|
||||
await CallHistory.deleteMany({ uid }); |
||||
await MediaCalls.deleteMany({ _id: { $in: [callId1, callId2, callId3, callId4] } }); |
||||
|
||||
await CallHistory.insertMany([ |
||||
{ |
||||
_id: 'rocketchat.internal.history.test', |
||||
ts: new Date(), |
||||
callId: callId1, |
||||
state: 'ended', |
||||
type: 'media-call', |
||||
duration: 10, |
||||
endedAt: new Date(), |
||||
external: false, |
||||
uid, |
||||
contactId: extraUid, |
||||
direction: 'outbound', |
||||
}, |
||||
{ |
||||
_id: 'rocketchat.internal.history.test.2', |
||||
ts: new Date(), |
||||
callId: callId2, |
||||
state: 'ended', |
||||
type: 'media-call', |
||||
duration: 10, |
||||
endedAt: new Date(), |
||||
external: false, |
||||
uid, |
||||
contactId: extraUid, |
||||
direction: 'inbound', |
||||
}, |
||||
{ |
||||
_id: 'rocketchat.internal.history.test.3', |
||||
ts: new Date(), |
||||
callId: callId3, |
||||
state: 'ended', |
||||
type: 'media-call', |
||||
duration: 10, |
||||
endedAt: new Date(), |
||||
external: true, |
||||
uid, |
||||
direction: 'outbound', |
||||
contactExtension: '1001', |
||||
}, |
||||
{ |
||||
_id: 'rocketchat.internal.history.test.4', |
||||
ts: new Date(), |
||||
callId: callId4, |
||||
state: 'ended', |
||||
type: 'media-call', |
||||
duration: 10, |
||||
endedAt: new Date(), |
||||
external: true, |
||||
uid, |
||||
direction: 'inbound', |
||||
contactExtension: '1001', |
||||
}, |
||||
]); |
||||
|
||||
await MediaCalls.insertMany([ |
||||
{ |
||||
_id: callId1, |
||||
service: 'webrtc', |
||||
kind: 'direct', |
||||
state: 'hangup', |
||||
createdBy: { |
||||
type: 'user', |
||||
id: uid, |
||||
}, |
||||
createdAt: new Date(), |
||||
caller: { |
||||
type: 'user', |
||||
id: uid, |
||||
contractId: 'contract1', |
||||
}, |
||||
callee: { |
||||
type: 'user', |
||||
id: extraUid, |
||||
contractId: 'contract2', |
||||
}, |
||||
ended: true, |
||||
endedBy: { |
||||
type: 'user', |
||||
id: uid, |
||||
}, |
||||
endedAt: new Date(), |
||||
hangupReason: 'normal', |
||||
expiresAt: new Date(), |
||||
acceptedAt: new Date(), |
||||
activatedAt: new Date(), |
||||
uids: [uid, extraUid], |
||||
}, |
||||
{ |
||||
_id: callId2, |
||||
service: 'webrtc', |
||||
kind: 'direct', |
||||
state: 'hangup', |
||||
createdBy: { |
||||
type: 'user', |
||||
id: extraUid, |
||||
}, |
||||
createdAt: new Date(), |
||||
caller: { |
||||
type: 'user', |
||||
id: extraUid, |
||||
contractId: 'contract1', |
||||
}, |
||||
callee: { |
||||
type: 'user', |
||||
id: uid, |
||||
contractId: 'contract2', |
||||
}, |
||||
ended: true, |
||||
endedBy: { |
||||
type: 'user', |
||||
id: uid, |
||||
}, |
||||
endedAt: new Date(), |
||||
hangupReason: 'normal', |
||||
expiresAt: new Date(), |
||||
acceptedAt: new Date(), |
||||
activatedAt: new Date(), |
||||
uids: [uid, extraUid], |
||||
}, |
||||
{ |
||||
_id: callId3, |
||||
service: 'webrtc', |
||||
kind: 'direct', |
||||
state: 'hangup', |
||||
createdBy: { |
||||
type: 'user', |
||||
id: uid, |
||||
}, |
||||
createdAt: new Date(), |
||||
caller: { |
||||
type: 'user', |
||||
id: uid, |
||||
contractId: 'contract1', |
||||
}, |
||||
callee: { |
||||
type: 'sip', |
||||
id: '1001', |
||||
contractId: 'contract2', |
||||
}, |
||||
ended: true, |
||||
endedBy: { |
||||
type: 'user', |
||||
id: uid, |
||||
}, |
||||
endedAt: new Date(), |
||||
hangupReason: 'normal', |
||||
expiresAt: new Date(), |
||||
acceptedAt: new Date(), |
||||
activatedAt: new Date(), |
||||
uids: [uid], |
||||
}, |
||||
{ |
||||
_id: callId4, |
||||
service: 'webrtc', |
||||
kind: 'direct', |
||||
state: 'hangup', |
||||
createdBy: { |
||||
type: 'sip', |
||||
id: '1001', |
||||
}, |
||||
createdAt: new Date(), |
||||
caller: { |
||||
type: 'sip', |
||||
id: '1001', |
||||
contractId: 'contract1', |
||||
}, |
||||
callee: { |
||||
type: 'user', |
||||
id: uid, |
||||
contractId: 'contract2', |
||||
}, |
||||
ended: true, |
||||
endedBy: { |
||||
type: 'user', |
||||
id: uid, |
||||
}, |
||||
endedAt: new Date(), |
||||
hangupReason: 'normal', |
||||
expiresAt: new Date(), |
||||
acceptedAt: new Date(), |
||||
activatedAt: new Date(), |
||||
uids: [uid], |
||||
}, |
||||
]); |
||||
} |
||||
@ -0,0 +1,235 @@ |
||||
import type { Credentials } from '@rocket.chat/api-client'; |
||||
import type { IUser } from '@rocket.chat/core-typings'; |
||||
import { expect } from 'chai'; |
||||
import { after, before, describe, it } from 'mocha'; |
||||
import type { Response } from 'supertest'; |
||||
|
||||
import { getCredentials, api, request, credentials } from '../../data/api-data'; |
||||
import { password } from '../../data/user'; |
||||
import { createUser, deleteUser, login } from '../../data/users.helper'; |
||||
|
||||
describe('[Call History]', () => { |
||||
let user2: IUser; |
||||
let userCredentials: Credentials; |
||||
|
||||
before((done) => getCredentials(done)); |
||||
|
||||
before(async () => { |
||||
user2 = await createUser(); |
||||
userCredentials = await login(user2.username, password); |
||||
}); |
||||
|
||||
after(() => deleteUser(user2)); |
||||
|
||||
describe('[/call-history.list]', () => { |
||||
it('should list all history entries for that uid', async () => { |
||||
await request |
||||
.get(api('call-history.list')) |
||||
.set(credentials) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res: Response) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.property('items').that.is.an('array'); |
||||
|
||||
expect(res.body.items).to.have.lengthOf(4); |
||||
expect(res.body).to.have.property('total', 4); |
||||
expect(res.body).to.have.property('count', 4); |
||||
|
||||
const historyIds = res.body.items.map((item: any) => item._id); |
||||
expect(historyIds).to.include('rocketchat.internal.history.test'); |
||||
expect(historyIds).to.include('rocketchat.internal.history.test.2'); |
||||
expect(historyIds).to.include('rocketchat.internal.history.test.3'); |
||||
expect(historyIds).to.include('rocketchat.internal.history.test.4'); |
||||
|
||||
const internalItem1 = res.body.items.find((item: any) => item._id === 'rocketchat.internal.history.test'); |
||||
expect(internalItem1).to.have.property('callId', 'rocketchat.internal.call.test'); |
||||
expect(internalItem1).to.have.property('state', 'ended'); |
||||
expect(internalItem1).to.have.property('type', 'media-call'); |
||||
expect(internalItem1).to.have.property('duration', 10); |
||||
expect(internalItem1).to.have.property('external', false); |
||||
expect(internalItem1).to.have.property('direction', 'outbound'); |
||||
expect(internalItem1).to.have.property('contactId'); |
||||
|
||||
const internalItem2 = res.body.items.find((item: any) => item._id === 'rocketchat.internal.history.test.2'); |
||||
expect(internalItem2).to.have.property('callId', 'rocketchat.internal.call.test.2'); |
||||
expect(internalItem2).to.have.property('state', 'ended'); |
||||
expect(internalItem2).to.have.property('type', 'media-call'); |
||||
expect(internalItem2).to.have.property('duration', 10); |
||||
expect(internalItem2).to.have.property('external', false); |
||||
expect(internalItem2).to.have.property('direction', 'inbound'); |
||||
expect(internalItem2).to.have.property('contactId'); |
||||
|
||||
const externalItem1 = res.body.items.find((item: any) => item._id === 'rocketchat.internal.history.test.3'); |
||||
expect(externalItem1).to.have.property('callId', 'rocketchat.internal.call.test.3'); |
||||
expect(externalItem1).to.have.property('state', 'ended'); |
||||
expect(externalItem1).to.have.property('type', 'media-call'); |
||||
expect(externalItem1).to.have.property('duration', 10); |
||||
expect(externalItem1).to.have.property('external', true); |
||||
expect(externalItem1).to.have.property('direction', 'outbound'); |
||||
expect(externalItem1).to.have.property('contactExtension', '1001'); |
||||
|
||||
const externalItem2 = res.body.items.find((item: any) => item._id === 'rocketchat.internal.history.test.4'); |
||||
expect(externalItem2).to.have.property('callId', 'rocketchat.internal.call.test.4'); |
||||
expect(externalItem2).to.have.property('state', 'ended'); |
||||
expect(externalItem2).to.have.property('type', 'media-call'); |
||||
expect(externalItem2).to.have.property('duration', 10); |
||||
expect(externalItem2).to.have.property('external', true); |
||||
expect(externalItem2).to.have.property('direction', 'inbound'); |
||||
expect(externalItem2).to.have.property('contactExtension', '1001'); |
||||
}); |
||||
}); |
||||
|
||||
it('should not list history entries from other users', async () => { |
||||
await request |
||||
.get(api('call-history.list')) |
||||
.set(userCredentials) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res: Response) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.property('items').that.is.an('array'); |
||||
|
||||
expect(res.body.items).to.have.lengthOf(0); |
||||
expect(res.body).to.have.property('total', 0); |
||||
expect(res.body).to.have.property('count', 0); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('[/call-history.info]', () => { |
||||
it('should return the history entry information', async () => { |
||||
await request |
||||
.get(api('call-history.info')) |
||||
.set(credentials) |
||||
.query({ |
||||
historyId: 'rocketchat.internal.history.test', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res: Response) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.property('item').that.is.an('object'); |
||||
expect(res.body).to.have.property('call').that.is.an('object'); |
||||
|
||||
const { item, call } = res.body; |
||||
expect(item).to.have.property('_id', 'rocketchat.internal.history.test'); |
||||
expect(item).to.have.property('callId', 'rocketchat.internal.call.test'); |
||||
expect(item).to.have.property('state', 'ended'); |
||||
expect(item).to.have.property('type', 'media-call'); |
||||
expect(item).to.have.property('duration', 10); |
||||
expect(item).to.have.property('external', false); |
||||
expect(item).to.have.property('direction', 'outbound'); |
||||
expect(item).to.have.property('contactId'); |
||||
expect(item).to.have.property('ts'); |
||||
expect(item).to.have.property('endedAt'); |
||||
|
||||
expect(call).to.have.property('_id', 'rocketchat.internal.call.test'); |
||||
expect(call).to.have.property('service', 'webrtc'); |
||||
expect(call).to.have.property('kind', 'direct'); |
||||
expect(call).to.have.property('state', 'hangup'); |
||||
expect(call).to.have.property('ended', true); |
||||
expect(call).to.have.property('hangupReason', 'normal'); |
||||
expect(call).to.have.property('createdBy').that.is.an('object'); |
||||
expect(call.createdBy).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('caller').that.is.an('object'); |
||||
expect(call.caller).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('callee').that.is.an('object'); |
||||
expect(call.callee).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('endedBy').that.is.an('object'); |
||||
expect(call.endedBy).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('uids').that.is.an('array'); |
||||
expect(call.uids).to.have.lengthOf(2); |
||||
}); |
||||
}); |
||||
|
||||
it('should return the history entry information when searching by call id', async () => { |
||||
await request |
||||
.get(api('call-history.info')) |
||||
.set(credentials) |
||||
.query({ |
||||
callId: 'rocketchat.internal.call.test.2', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res: Response) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.property('item').that.is.an('object'); |
||||
expect(res.body).to.have.property('call').that.is.an('object'); |
||||
|
||||
const { item, call } = res.body; |
||||
expect(item).to.have.property('_id', 'rocketchat.internal.history.test.2'); |
||||
expect(item).to.have.property('callId', 'rocketchat.internal.call.test.2'); |
||||
expect(item).to.have.property('state', 'ended'); |
||||
expect(item).to.have.property('type', 'media-call'); |
||||
expect(item).to.have.property('duration', 10); |
||||
expect(item).to.have.property('external', false); |
||||
expect(item).to.have.property('direction', 'inbound'); |
||||
expect(item).to.have.property('contactId'); |
||||
expect(item).to.have.property('ts'); |
||||
expect(item).to.have.property('endedAt'); |
||||
|
||||
expect(call).to.have.property('_id', 'rocketchat.internal.call.test.2'); |
||||
expect(call).to.have.property('service', 'webrtc'); |
||||
expect(call).to.have.property('kind', 'direct'); |
||||
expect(call).to.have.property('state', 'hangup'); |
||||
expect(call).to.have.property('ended', true); |
||||
expect(call).to.have.property('hangupReason', 'normal'); |
||||
expect(call).to.have.property('createdBy').that.is.an('object'); |
||||
expect(call.createdBy).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('caller').that.is.an('object'); |
||||
expect(call.caller).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('callee').that.is.an('object'); |
||||
expect(call.callee).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('endedBy').that.is.an('object'); |
||||
expect(call.endedBy).to.have.property('type', 'user'); |
||||
expect(call).to.have.property('uids').that.is.an('array'); |
||||
expect(call.uids).to.have.lengthOf(2); |
||||
}); |
||||
}); |
||||
|
||||
it('should fail when querying an invalid entry', async () => { |
||||
await request |
||||
.get(api('call-history.info')) |
||||
.set(credentials) |
||||
.query({ |
||||
historyId: 'something-random', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(404); |
||||
}); |
||||
|
||||
it('should fail when querying an invalid entry by call id', async () => { |
||||
await request |
||||
.get(api('call-history.info')) |
||||
.set(credentials) |
||||
.query({ |
||||
callId: 'something-random', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(404); |
||||
}); |
||||
|
||||
it('should fail when querying an entry from another user', async () => { |
||||
await request |
||||
.get(api('call-history.info')) |
||||
.set(userCredentials) |
||||
.query({ |
||||
historyId: 'rocketchat.internal.history.test', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(404); |
||||
}); |
||||
|
||||
it('should fail when querying an entry from another user by call id', async () => { |
||||
await request |
||||
.get(api('call-history.info')) |
||||
.set(userCredentials) |
||||
.query({ |
||||
callId: 'rocketchat.internal.call.test.2', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(404); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -1,10 +1,15 @@ |
||||
import typia from 'typia'; |
||||
|
||||
import type { CallHistoryItem } from './ICallHistoryItem'; |
||||
import type { ICustomSound } from './ICustomSound'; |
||||
import type { IInvite } from './IInvite'; |
||||
import type { IMessage } from './IMessage'; |
||||
import type { IOAuthApps } from './IOAuthApps'; |
||||
import type { IPermission } from './IPermission'; |
||||
import type { ISubscription } from './ISubscription'; |
||||
import type { IMediaCall } from './mediaCalls/IMediaCall'; |
||||
|
||||
export const schemas = typia.json.schemas<[ISubscription | IInvite | ICustomSound | IMessage | IOAuthApps | IPermission], '3.0'>(); |
||||
export const schemas = typia.json.schemas< |
||||
[ISubscription | IInvite | ICustomSound | IMessage | IOAuthApps | IPermission | IMediaCall, CallHistoryItem], |
||||
'3.0' |
||||
>(); |
||||
|
||||
@ -1,5 +1,18 @@ |
||||
import type { CallHistoryItem } from '@rocket.chat/core-typings'; |
||||
import type { FindOptions } from 'mongodb'; |
||||
|
||||
import type { IBaseModel } from './IBaseModel'; |
||||
|
||||
export type ICallHistoryModel = IBaseModel<CallHistoryItem>; |
||||
export interface ICallHistoryModel extends IBaseModel<CallHistoryItem> { |
||||
findOneByIdAndUid( |
||||
_id: CallHistoryItem['_id'], |
||||
uid: CallHistoryItem['uid'], |
||||
options?: FindOptions<CallHistoryItem>, |
||||
): Promise<CallHistoryItem | null>; |
||||
|
||||
findOneByCallIdAndUid( |
||||
callId: CallHistoryItem['callId'], |
||||
uid: CallHistoryItem['uid'], |
||||
options?: FindOptions<CallHistoryItem>, |
||||
): Promise<CallHistoryItem | null>; |
||||
} |
||||
|
||||
Loading…
Reference in new issue