- Constructor
- Settings
- Connect state methods
- Connect state events
- Logger
- API requests
- Event listeners
- Action hooks
- Helpers
Socket(settings, websocketImplementation)
API connection won't be established until connect
is called.
Arguments
settings
(object, required)
Settings object that will override the default connector options (see the following section for information about available settings).
socketImplementation
(object, required)
W3C-compatible WebSocket implementation to use for underlying API communication.
Example implementation for Node.js: w3cwebsocket from package https://github.com/theturtle32/WebSocket-Node
Web browsers: browser's native WebSocket implementation should be used (simply provide WebSocket
or window.WebSocket
)
Example
import { Socket } from 'airdcpp-apisocket';
import { w3cwebsocket } from 'websocket';
const settings = {
url: 'ws:https://localhost:5600/api/v1/',
username: 'testuser',
password: 'testpassword',
reconnectInterval: 5
};
const socket = Socket(settings, w3cwebsocket);
Name | Type | Default | Description |
---|---|---|---|
url | string |
Fully qualified API URL (required). Example: ws:https://localhost:5600/api/v1/ | |
username, password | string |
Username and password to use when connecting to the API. Alternatively you may provide the credentials when calling connect . |
|
autoReconnect | boolean |
true | Reconnect automatically if there are network errors when initializing connection or when a connected socket gets disconnected |
reconnectInterval | number |
10 | Interval of automatic reconnection (seconds) |
requestTimeout | number |
30 | Notify about about API requests that have taken longer than this to complete (seconds). This is mainly used for detecting possible issues (deadlocks) with the backend as messages sent via WebSocket should always be delivered (pending request will be aborted automatically when the socket is disconnected). |
reconnectInterval | number |
10 | Interval of automatic reconnection (seconds) |
logLevel | enum[string] |
verbose | Logging level. Available values: none , error , warn , info , verbose |
logOutput | object |
console | Output for logged messages. The supplied object must have the following function properties taking a variable number of arguments: log , info , warn , error |
ignoredRequestPaths | array[string] | RegExp |
Request paths that should never be displayed in logs/console. Array of exact paths or a single regex pattern may be used. This option is mainly targeted for debugging purposes in order to prevent spammy requests from filling the console window. | |
ignoredListenerEvents | array[string] | RegExp |
Listener/hook event names that should never be displayed in logs/console. Array of exact names or a single regex pattern may be used. This option is mainly targeted for debugging purposes in order to prevent spammy events from filling the console window. |
Generic methods for viewing and changing the socket connect state. These methods should not be used by (managed) extensions as the connect state is managed automatically.
connect(username, password, reconnectOnFailure = true)
Arguments
username
, password
(string, optional)
Custom user name and password that will override the possible globally set values.
reconnectOnFailure
(boolean, optional)
Attempt to reconnect automatically if the socket can't be connected due to connectivity issue (API errors will always fail the action). This won't have effect if the socket gets disconnected after a successful connect attempt (the global auto reconnect option is used there instead).
Return value
Promise that will be resolved with response of the POST /sessions/authorize API method
disconnect(reconnect, reason)
Disconnect the socket while keeping the session token cached. reconnect
can be used to re-establish the connection.
Arguments
reconnect
(boolean, optional)
reason
(string, optional)
String describing the reason for the disconnect
reconnect(authToken)
Reconnect a disconnected session or connect with an existing session token. This method can't be used for currently connected sockets.
Arguments
authToken
(string, optional)
Possible session token to use for reconnecting. If no token is specified, the cached token will be used. If there is no cached token available, the method will throw.
Return value
Promise that will be resolved with response of the POST /sessions/socket API method.
Returns true if connection is currently being established.
Returns true if the socket is currently connected and authenticated.
Returns true if the socket is currently connected or there is a connection attempt in progress.
Invalidate the current API session and disconnect the socket.
Return value
Promise that will be resolved with the possible response of the DELETE /sessions API method.
onConnected(data)
Fired after the socket was connected and authenticated. data
is the data received from the API authentication request (connect
/reconnect
).
Fired after the socket was disconnected.
Callback arguments
Supplied arguments are properties from the websocket CloseEvent.
reason
(string)
code
(number)
wasClean
(number)
Fired when the session was reset (either after logout
was called or due to a rejected reconnect attempt).
Similar to console
object but the output is emitted only if allowed by the logLevel
setting.
post(path, data)
, put(path, data)
, patch(path, data)
, get(path)
, delete(path)
Arguments
path
(string, required)
API request path
data
(object, optional)
Method-specific data object. No data is allowed for get
and delete
methods.
Return value
Promise that will be resolved with the possible response data (or is rejected with an error object).
Example
socket.post('events', {
text: 'Testing',
severity: 'info'
})
.then(data => console.log('Message was sent'))
.catch(error => console.error('Failed to send the message: ' + error.message));
addListener(path, listenerName, callback, entityId)
Arguments
apiSection
(string, required)
API section of the listener (the first part of the documented listener URL, e.g. hubs
or search
).
listenerName
(string, required)
Name of the API listener (last part of the documented listener URL)
callback
(function, required)
Function to call on received event messages. The callback function signature is handler(data, entityId)
where data
is the
subscription-specific data object (if available) and entityId
is set only for entity type subscriptions.
entityId
(string|number, optional)
Possible ID when using per-entity subscriptions (filelist, hub, extension...). Events from all entities will be sent if no entity ID is specified.
Return value
Promise returning a function that will remove the listener when being called. Note that all listeners will be removed automatically when the socket is disconnected.
Note that the function returns asynchronously after receiving confirmation from the application that the event listener has really been added. It's generally safer to wait for the function to return even if you don't need the removal callback before continuing with other actions that expect the listener to be functional and emitting events. As the API is multithreaded and requests may be processed in a different order that they were sent, this will avoid race conditions and events possibly being missed.
Example
const onMessageReceived = (message, hubId) => {
console.log(`${message.text} (hub ID: ${hubId})`);
}
// NOTE: async function
const removeListener = await socket.addListener('hubs', 'hub_chat_message', onMessageReceived);
// If you want to add the listener only for a single hub, add the session ID argument at the end:
// const removeListener = await socket.addListener('hubs', 'hub_chat_message', onMessageReceived, replace_with_the_wanted_session_id);
// ... other code
// Remove the listener
removeListener();
Action hooks are meant to be used only if you are going to change the behavior how certain actions/events are being processed by the application (or whether the action/event is being processed at all). Please see the API docs for more information about action hooks and how they compare with event listeners.
addHook(path, hookName, callback)
Arguments
apiSection
(string, required)
API section of the wanted hook (the first part of the documented hook URL, e.g. hubs
or search
).
hookName
(string, required)
Name of the hook (last part of the documented hook URL)
callback
(function, required)
Function to call on received event messages. The callback function signature is handler(data, accept, reject)
where data
is the
hook-specific data object. accept
((data) => void
) function should be called in case of success, and it may also be called with a data argument, if supported by the hook. reject
(signature (rejectId: string, rejectMessage: string) => void
) should be called with the error information in case of errors.
subscriberInfo
(object, required)
Information about the subscriber (an object with id
and name
properties).
Return value
Promise returning a function that will remove the hook when being called. Note that all hooks will be removed automatically when the socket is disconnected.
Note that the function returns asynchronously after receiving confirmation from the application that the hook has really been added. It's generally safer to wait for the function to return even if you don't need the removal callback before continuing with other actions that expect the listener to be functional and emitting events. As the API is multithreaded and requests may be processed in a different order that they were sent, this will avoid race conditions and events possibly being missed.
Example
const handleIncomingMessage = (message, accept, reject) => {
if (message.text.indexOf('spam') !== -1) {
reject('spam_filtered', 'Message was spam');
} else {
accept();
}
}
const subscriberInfo = {
id: 'my-test-hook',
name: 'Test hook'
};
// NOTE: async function
const removeHook = await socket.addHook('hubs', 'hub_incoming_message_hook', handleIncomingMessage, subscriberInfo);
// ... other code
// Remove the hook
removeHook();
Logging tip
With certain hooks, the console may quickly be filled with API communication messages when verbose
logging level is used.
The following socket options will filter out all incoming share_file_validation_hook
hook messages and their respective accept calls (rejected files are still being logged):
ignoredListenerEvents: [
'share_file_validation_hook'
],
ignoredRequestPaths: /^(share\/hooks\/share_file_validation_hook\/\d+\/resolve)$/
A helper function that can be used to add context menu items. See the (Menu API documentation)[https://airdcpp.docs.apiary.io/#reference/menus] for more information about the menu API.
Arguments
socket
(object, required)
airdcpp-apisocket
instance
menuItems
(array[object], required)
List of menu items to be added
Each item should include id
and name
properties and optionally an icon
property (see menuitems
for more information).
Additionally each item should have either of the following properties:
onClick
function (signature(selectedIds: any[], entityId: any | undefined, permissions: string[], supports: string[], formValues: object) => void
) property that will be called if the menu item is being clicked by the user.formValues
contains user input from the input form ifformDefinitions
was specified for the menu item.urls
function/string array (signaturestring[] | ((selectedIds: any[], entityId: any | undefined, permissions: string[], supports: string[]) => string[]) | undefined
) property that will return an array of URLs to be opened by the UI if the menu item is being clicked by the user (orundefined
if no URLs should be added and theonClick
hander should be called instead)
Optional properties for filtering:
filter
: function (signature (selectedIds: any[], entityId: any | undefined, permissions: string[], supports: string[]) => boolean | Promise<boolean>
) if you want to show the menu item conditionally. The filter function must return true
if the specific menu item should be added.
access
: Required access (string
) for accessing the menu item. If you need to perform more complex permission checks, use the filter
function to check the permissions
argument. See the API documentation
for available access strings.
Optional form definitions:
formDefinitions
function/object array (signatureobject[] | ((selectedIds: any[], entityId: any | undefined, permissions: string[], supports: string[]) => object[]) | undefined
) property that can used to define a form that will be shown to the user after the item has been clicked (the form user input will then be available in theonClick
handler). See the API documentation for information about the form definition format.
menuType
(string, required)
Menu type (see the Menu API documentation for available types)
subscriberInfo
(object, required)
Information about the subscriber (see the addHook
method).
Return value
Promise returning a function that will remove the menu items when being called.
Example
import { addContextMenuItems } from 'airdcpp-apisocket';
const socket = // ...initialize the socket
socket.onConnected = (sessionInfo) => {
if (sessionInfo.system_info.api_feature_level >= 4) {
// ...remember to check the permissions if needed
const subscriberInfo = {
id: 'airdcpp-release-validator',
name: 'Release validator extension'
};
addContextMenuItems(
socket,
[
{
id: 'scan_missing_extra',
title: `Scan share for missing/extra files`,
icon: {
semantic: 'yellow broom'
},
access: 'settings_edit',
onClick: async (selectedIds, entityId, permissions, supports, formValues) => {
const ignoreExcluded = formValues.ignore_excluded; // User input from the displayed form
await runners.scanShare(ignoreExcluded);
},
filter: selectedIds => selectedIds.indexOf(extension.name) !== -1,
formDefinitions: (selectedIds, entityId, permissions, supports) => {
// Show a dialog before the scan to allow the user to customize scanning options
return {
key: 'ignore_excluded',
title: 'Ignore files/directories that are excluded from share',
default_value: true,
type: 'boolean'
};
},
}, {
id: 'google',
title: `Google extension by ID`,
icon: {
semantic: 'external'
},
urls: async (selectedIds, entityId, permissions, supports) => {
// Generate Google search URL for each selected extension
return selectedIds
.map(extensionId => {
return `https://www.google.com/q=${encodeURIComponent(extensionId)}`
);
}
}
],
'extension', // Menu type
subscriberInfo,
);
}
}