Commit abd23961 authored by Tim Kinnane's avatar Tim Kinnane

feat(driver): Room and message methods and interfaces

parent 07824b9f
......@@ -61,6 +61,10 @@ More to come...
| `ADMIN_PASS` | Admin user password for API |
| `ROCKETCHAT_USER` | Bot password for tests |
| `ROCKETCHAT_PASS` | Bot username for tests |
| `ROOM_CACHE_SIZE` | Size of cache (LRU) for room (ID or name) lookups |
| `ROOM_CACHE_MAX_AGE` | Max age of cache for room lookups |
| `DM_ROOM_CACHE_SIZE` | Size of cache for Direct Message room lookups |
| `DM_ROOM_CACHE_MAX_AGE` | Max age of cache for DM lookups |
These are only required in test and development, assuming in production they
will be passed from the adapter implementing this package.
......
......@@ -12,54 +12,98 @@ BRH:0
end_of_record
TN:
SF:/Volumes/x/code/rocketchat-bot-driver/src/lib/driver.ts
FN:61,connect
FN:62,(anonymous_3)
FN:69,(anonymous_4)
FN:70,(anonymous_5)
FN:72,(anonymous_6)
FN:79,(anonymous_7)
FNF:6
FNH:5
FN:13,setupMethodCache
FN:83,connect
FN:84,(anonymous_4)
FN:91,(anonymous_5)
FN:92,(anonymous_6)
FN:94,(anonymous_7)
FN:101,(anonymous_8)
FN:113,getRoomId
FN:118,getRoomName
FN:126,getDirectMessageRoomId
FN:131,joinRoom
FN:139,prepareMessage
FNF:12
FNH:6
FNDA:7,setupMethodCache
FNDA:7,connect
FNDA:7,(anonymous_3)
FNDA:4,(anonymous_4)
FNDA:0,(anonymous_5)
FNDA:4,(anonymous_6)
FNDA:7,(anonymous_4)
FNDA:4,(anonymous_5)
FNDA:0,(anonymous_6)
FNDA:4,(anonymous_7)
FNDA:4,(anonymous_8)
FNDA:0,getRoomId
FNDA:0,getRoomName
FNDA:0,getDirectMessageRoomId
FNDA:0,joinRoom
FNDA:0,prepareMessage
DA:1,1
DA:2,1
DA:3,1
DA:4,1
DA:6,1
DA:17,1
DA:36,1
DA:61,1
DA:62,7
DA:63,7
DA:64,7
DA:68,7
DA:69,7
DA:70,7
DA:71,7
DA:72,7
DA:73,4
DA:74,4
DA:77,4
DA:79,7
DA:81,4
DA:82,3
DA:83,3
LF:23
LH:23
BRDA:61,0,0,1
BRDA:77,1,0,3
BRDA:77,1,1,1
BRDA:81,2,0,1
BRDA:81,2,1,3
BRDA:83,3,0,2
BRDA:83,3,1,1
BRF:7
BRH:7
DA:7,1
DA:14,7
DA:15,7
DA:23,7
DA:38,1
DA:57,1
DA:83,1
DA:84,7
DA:85,7
DA:86,7
DA:90,7
DA:91,7
DA:92,7
DA:93,7
DA:94,7
DA:95,4
DA:96,4
DA:99,4
DA:101,7
DA:103,4
DA:104,3
DA:105,3
DA:113,1
DA:114,0
DA:118,1
DA:119,0
DA:126,1
DA:127,0
DA:131,1
DA:132,0
DA:139,1
DA:141,0
DA:142,0
DA:148,0
DA:149,0
DA:150,0
DA:152,0
LF:41
LH:31
BRDA:16,0,0,7
BRDA:16,0,1,7
BRDA:17,1,0,7
BRDA:17,1,1,7
BRDA:20,2,0,7
BRDA:20,2,1,7
BRDA:21,3,0,7
BRDA:21,3,1,7
BRDA:24,4,0,7
BRDA:24,4,1,7
BRDA:25,5,0,7
BRDA:25,5,1,7
BRDA:83,6,0,1
BRDA:99,7,0,3
BRDA:99,7,1,1
BRDA:103,8,0,1
BRDA:103,8,1,3
BRDA:105,9,0,2
BRDA:105,9,1,1
BRDA:141,10,0,0
BRDA:141,10,1,0
BRF:21
BRH:19
end_of_record
TN:
SF:/Volumes/x/code/rocketchat-bot-driver/src/lib/methodCache.ts
......@@ -73,21 +117,21 @@ FN:77,(anonymous_7)
FNF:7
FNH:7
FNDA:18,use
FNDA:6,create
FNDA:27,create
FNDA:18,call
FNDA:1,get
FNDA:1,clear
FNDA:15,clearAll
FNDA:46,(anonymous_7)
FNDA:91,(anonymous_7)
DA:1,1
DA:5,1
DA:6,1
DA:15,1
DA:16,18
DA:25,1
DA:26,6
DA:27,6
DA:28,6
DA:26,27
DA:27,27
DA:28,27
DA:36,1
DA:37,18
DA:38,18
......@@ -103,7 +147,7 @@ DA:67,1
DA:68,1
DA:69,0
DA:76,1
DA:77,46
DA:77,91
LF:25
LH:24
BRDA:25,0,0,4
......
......@@ -2,7 +2,7 @@ import { EventEmitter } from 'events'
/**
* Patch in mock Asteroid type
* @todo Update with typing from definately typed (when available)
* @todo Update with typing from definitely typed (when available)
*/
export interface IAsteroid extends EventEmitter {
ddp: { on: (event: string, func: (doc: any) => void) => void }
......@@ -21,7 +21,7 @@ export interface IAsteroid extends EventEmitter {
/**
* Patch in Asteroid subscription type
* @todo Update with typing from definately typed (when available)
* @todo Update with typing from definitely typed (when available)
*/
export interface ISubscription extends EventEmitter {
id: string
......@@ -29,7 +29,7 @@ export interface ISubscription extends EventEmitter {
/**
* Patch in Asteroid user options type
* @todo Update with typing from definately typed (when available)
* @todo Update with typing from definitely typed (when available)
*/
export interface IUserOptions {
username?: string,
......
/** @todo contribute these to @types/rocketchat and require */
export interface IMessage {
rid: string, // room ID
_id?: string, // generated by Random.id()
t?: string, // type, e.g. rm
msg?: string, // text content
alias?: string, // ??
emoji?: string, // emoji code
avatar?: string, // url
groupable?: boolean, // ?
bot?: boolean, // sent by bot
urls?: Array<string>, // ?
mentions?: Array<string>, // ?
reactions?: { [emoji: string]: Array<string> } // emoji: [usernames]
location?: {
type: string, // e.g. Point
coordinates: Array<string> // longitude, latitude
},
attachments?: Array<IAttachment>,
editedAt?: Date,
editedBy?: {
_id: string,
username: string
}
}
export interface IAttachment {
fields: Array<IAttachmentField>,
color?: string,
text?: string,
ts?: string,
thumb_url?: string,
message_link?: string,
collapsed?: boolean,
author_name?: string,
author_link?: string,
author_icon?: string,
title?: string,
title_link?: string,
title_link_download?: string,
image_url?: string,
audio_url?: string,
video_url?: string
}
export interface IAttachmentField {
short?: boolean,
title: 'string',
value: 'string'
}
......@@ -3,8 +3,29 @@ import { EventEmitter } from 'events'
import WebSocket from 'ws'
import * as methodCache from './methodCache'
import { IAsteroid } from '../config/asteroidInterfaces'
import { IMessage } from '../config/messageInterfaces'
const Asteroid = createClass()
/**
* Setup method cache configs from env or defaults, before they are called
* @param asteroid The asteroid instance to cache method calls
*/
function setupMethodCache (asteroid: IAsteroid): void {
methodCache.use(asteroid)
methodCache.create('getRoomIdByNameOrId', {
max: parseInt(process.env.ROOM_CACHE_SIZE || '10', 10),
maxAge: 1000 * parseInt(process.env.ROOM_CACHE_MAX_AGE || '300', 10)
}),
methodCache.create('getRoomNameById', {
max: parseInt(process.env.ROOM_CACHE_SIZE || '10', 10),
maxAge: 1000 * parseInt(process.env.ROOM_CACHE_MAX_AGE || '300', 10)
})
methodCache.create('createDirectMessage', {
max: parseInt(process.env.DM_ROOM_CACHE_SIZE || '10', 10),
maxAge: 1000 * parseInt(process.env.DM_ROOM_CACHE_MAX_AGE || '100', 10)
})
}
/**
* Connection options type
* @param host Rocket.Chat instance Host URL:PORT (without protocol)
......@@ -37,6 +58,7 @@ export const events = new EventEmitter()
/**
* An Asteroid instance for interacting with Rocket.Chat
* Variable not initialised until connect method called
*/
export let asteroid: IAsteroid
......@@ -65,7 +87,7 @@ export function connect (options: IOptions = {}, callback?: ICallback): Promise<
endpoint: `ws://${options.host}/websocket`,
SocketConstructor: WebSocket
})
methodCache.use(asteroid) // init instance for later caching method calls
setupMethodCache(asteroid) // init instance for later caching method calls
asteroid.on('connected', () => events.emit('connected'))
asteroid.on('reconnected', () => events.emit('reconnected'))
let cancelled = false
......@@ -84,3 +106,48 @@ export function connect (options: IOptions = {}, callback?: ICallback): Promise<
})
})
}
/** @todo: From on here on untested */
/** Get ID for a room by name (or ID) */
export function getRoomId (name: string): Promise<string> {
return methodCache.call('getRoomIdByNameOrId', name)
}
/** Get name for a room by ID */
export function getRoomName (id: string): Promise<string> {
return methodCache.call('getRoomNameById', id)
}
/**
* Get ID for a DM room by its recipient's name
* Will create a DM (with the bot) if it doesn't exist already
*/
export function getDirectMessageRoomId (username: string): Promise<string> {
return methodCache.call('createDirectMessage', username)
}
/** Join the bot into a room by its ID */
export function joinRoom (roomId: string): Promise<void> {
return Promise.resolve(asteroid.call('joinRoom', roomId))
}
/**
* Put message content in required structure for sending to room
* Accepts a message string, or a preformed message object to address room ID
*/
export function prepareMessage (content: string | IMessage, roomId: string): IMessage {
let message: IMessage
if (typeof content === 'string') {
message = {
msg: content,
rid: roomId,
bot: true
}
} else {
message = content
message.rid = roomId
message.bot = true
}
return message
}
......@@ -19,8 +19,8 @@ export function use (instanceToUse: object) {
/**
* Setup a cache for a method call
* @param method Method name, for index of cached results
* @param max Maximum size of cache
* @param maxAge Maximum age of cache
* @param options.max Maximum size of cache
* @param options.maxAge Maximum age of cache
*/
export function create (method: string, options: LRU.Options = {}) {
options = Object.assign(defaults, options)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment