asterisk / node-ari-client Goto Github PK
View Code? Open in Web Editor NEWNode.js client for ARI. This library is best effort with limited support.
License: Other
Node.js client for ARI. This library is best effort with limited support.
License: Other
I'd see it here using the demo tt-monkeys app: https://gist.github.com/dougbtv/bef8c442f47c432147ffd9c511d435ca
Then I traced it out a big, and I found that...
channel.hangup(function(err) {
console.log(typeof err);
}
would give me...
object
fwiw, thought I'd note it here.
It seems that jsdoc has been abandoned... most people that want to see patches land in the project have decided to just fork it and make the changes themselves. I know that @ruffrey also has a fork of the project called jsdoxy.
In any case, we should move away from this package if we want to make sure we get updates to its dependencies and any bugs fixed ever.
I was attempting to use the mute and unmute channel options. The mute option worked just fine but the unmute didn't. If I used the direct Swagger UI delete mute call it was able to unmute the channel just fine.
Have you had any reports of this? I found another way around the issue. I was setting the role of a bridge to mixing when I should've been setting it to holding. But, I'm sure I'll need mute and unmute in the future.
Thank you!
Phil Mickelson
we use ari.start('hello-world') to active/create a stasis app in asterisk, a websocket connection is established. But if network error, the websocket will be disconnected. Then calls can't be made through ari stasis. So is there an event to check the websocket connection? or will ari stasis app be restarted automatically?
Currently, if Asterisk is not started when ari-client tries to open a connection, the error callback is not fired as we would expect to.
It seems to be a bug in swagger-client
, which is apparently fixed in the latest version (2.1.26 this day). I cannot figure out precisely which version fixed this, but my own tests suggest it is actually working in the current one.
So, is it possible to update the swagger-client
version to 2.1.26 ?
How to add multiple channels by sending only one request.
"channel (string) - Ids of channels to add to bridge" -> Cannot add multiple channels using a comma separated string.
[ 'This API is using a deprecated version of Swagger! Please see http://github.com/wordnik/swagger-core/wiki for more info' ]
Getting this output any time the client is instantiated.
For ARI operations that support parameters in a POST body (channel origination channel variables for example), Swagger.js does not respect the parameter type.
Passing
{variables: {}}
to an ARI operation call does not send the variables in the POST body. The parameter must be passed as
{body: '{}'}
where the json is sent as a string.
ari-client should abstract this issue out and convert parameters with a body parameter type to use the Swagger.js body parameter option and convert JavaScript objects to a json string.
An ari-client unit test should also be written to cover this issue.
there're a lot of errors blocking the build of this module, e.g.
\node_modules\ari-client\node_modules\ws\node_modules\nan\nan.h(213):
error C2039: 'ThrowException': is not a member of 'v8'
error C2039: 'New': is not a member of 'v8::String'
error C3861: 'New': identifier not found
upgrade ws to the latest version 1.1.0 will solve this on my end.
possible to update the dependencies?
I'd love to be able to use this library with the ARI Proxy messaging protocol and send/recieve via a message bus such as RabbitMQ rather than via Websocket/HTTP.
The ARI is great except that it really limits us to a 1:1 relationship.
Both the .NET and Go ARI Clients don't rely on getting a resource list from the API on startup which makes utilising the Proxy easier. The other issue is that everything utilises the swagger-client
to generate request bodies etc from what I can see - which again limits the clients use as its tied to swagger.
I'd love to have a chat about the best way to implement this so that I don't come to put a PR in and have it rejected. @samuelg @erinspice @matt-jordan
I'd prefer to just have the one ARI client on npm but I'm starting to wonder if I should just fork the project, remove all the swagger cleverness and go down the route of what .NET and Go did - generate all the functions etc from the resources file whenever Asterisk changes - don't do it on every startup (which must add time to all app startup times) and not using swagger to do the HTTP/Websocket calls etc.
Let me know your thoughts!
Is there a function that lets the application execute an AGI script?
npm is showing 1.0.2, but there's no tag in GitHub.
I'm using a single stasis application to demo several ARI functionalities, and I'm using channel.dialplan.exten
as a "switch" to tell between these sub-apps.
When I use a SIP phone and dial in the extension, exten
is set accordingly. However, when calling out from ARI using client.originate({ extension: '1234', ... })
, exten
always contains an empty string (regardless of the channel source: the StasisStart event, originate callback, etc). Is this intentional? Why does it do that?
Thanks!
When you have a channel, you can call this line of code and pass a playback without any issues:
channel.play({media: sound}, playback, function (err, playback) {});
This gives the same playback id for the start and finish events.
When you only have the channel id, it works differently:
ari.channels.play({media: sound, channelId: chanId, playbackId: playId}, function (err, playback) {});
The playback id needs to be specified in the options, rather than passing a playback object as a parameter. Slight discrepancy between the two ".play()" calls.
hello,
How to set argument value in channel.orginate() and how to get argument value in ari.on('StasisStart',function(){});
'channelStateChange' not emmiting on channel-state-change for event 'Rsrvd' and such more events. Currently i am using Asterisk 14 and using node-ari-client 1.1.0,
and also list events name for channelStateChange.
Thanks.
Asterisk 14 introduces the ability to fetch a recording file, which is transmitted in binary.
The getStoredFile()
method fails with the following error:
RIFFd`
^SyntaxError: Unexpected token R in JSON at position 0
at Object.parse (native)
at SwaggerRequest.processResponse (/myapp/node_modules/ari-client/lib/client.js:261:31)
at Object.response (/myapp/node_modules/swagger-client/lib/swagger.js:1086:24)
at EventEmitter.response (/myapp/node_modules/swagger-client/lib/swagger.js:1308:19)
at emitOne (events.js:96:13)
at EventEmitter.emit (events.js:188:7)
at emit (/myapp/node_modules/shred/lib/shred/request.js:456:21)
at /myapp/node_modules/shred/lib/shred/request.js:476:9
at setBodyAndFinish (/myapp/node_modules/shred/lib/shred/response.js:103:7)
at IncomingMessage. (/myapp/node_modules/shred/lib/shred/response.js:120:7)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
I've tracked this error to JSON.parse(result) attempting to parse a non-JSON binary string, instead of handling the Buffer
object.
Surprisingly, I haven't found an example of this. Here is how I am doing it
client.start('hello-world');
client.channels.create({app: 'hello-world', endpoint: 'Local/79991111111@sip-dialout'}).then(localChannel => {
console.log('STAGE 1: ', localChannel.state);
localChannel.dial().then(() => {
console.log('STAGE 2: ', localChannel.state);
}).error(function(err) {
console.log('ERROR 2:', err);
});
}).error(function(err) {
console.log('ERROR 1: ', arguments);
});
Which usually works, i.e. I get a phone call on +79991111111 but sometimes instead I get the following error
STAGE 1: Down
ERROR 2: Error: {"message":"Channel not found"}
at SwaggerRequest.swaggerError [as errorCallback] (/usr/lib/node_modules/ari-client/lib/resources.js:944:19)
at Object.error (/usr/lib/node_modules/ari-client/node_modules/swagger-client/lib/swagger.js:1077:24)
at EventEmitter.error (/usr/lib/node_modules/ari-client/node_modules/swagger-client/lib/swagger.js:1296:19)
at emitOne (events.js:96:13)
at EventEmitter.emit (events.js:188:7)
at emit (/usr/lib/node_modules/ari-client/node_modules/shred/lib/shred/request.js:454:21)
at /usr/lib/node_modules/ari-client/node_modules/shred/lib/shred/request.js:473:9
at setBodyAndFinish (/usr/lib/node_modules/ari-client/node_modules/shred/lib/shred/response.js:103:7)
at IncomingMessage. (/usr/lib/node_modules/ari-client/node_modules/shred/lib/shred/response.js:120:7)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
This is the context from extensions.conf
[sip-dialout]
exten => _X.,1,Dial(SIP/zebra/+${EXTEN})
exten => _X.,n,Hangup()
What am doing wrong?
Hello ,
I am talking about issue #77.
In this issue i am using ari.channels.create() then ari.channels.dial() but it gives type error:
/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/async.js:43
fn = function () { throw arg; };
^
TypeError: client.channels.create is not a function
at clientLoaded (/usr/local/lib/node_modules/sarvIVR/IVR/mahi_callTransfer.js:163:25)
at tryCatcher (/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/util.js:26:23)
at Promise.successAdapter (/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/nodeify.js:23:30)
at Promise._settlePromiseAt (/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/promise.js:582:21)
at Promise._settlePromises (/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/promise.js:700:14)
at Async._drainQueue (/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/async.js:123:16)
at Async._drainQueues (/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/async.js:133:10)
at Immediate.Async.drainQueues [as _onImmediate] (/usr/local/lib/node_modules/ari-client/node_modules/bluebird/js/main/async.js:15:14)
at processImmediate [as _immediateCallback] (timers.js:383:17)
In case of network errors, auto-reconnect to WebSocket connection with a back-off algorithm. See #14 for original issue.
Update the generated README using the latest version of Asterisk.
I got the following error when trying to npm install ari-client:
> [email protected] install /usr/src/app/node_modules/ari-client/node_modules/ws
> (node-gyp rebuild 2> builderror.log) || (exit 0)
make: Entering directory '/usr/src/app/node_modules/ari-client/node_modules/ws/build'
CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
bufferutil.target.mk:90: recipe for target 'Release/obj.target/bufferutil/src/bufferutil.o' failed
make: Leaving directory '/usr/src/app/node_modules/ari-client/node_modules/ws/build'
It appears that the older version of ws is not compatible with node 0.12.7 seeing that I was able to build ws 0.7.2 successfully on node 0.12.7.
I've searched for this all I can. I can't seem to locate anything other than how it may be fixed. When I load a program with ari-client I get the message:
[ 'This API is using a deprecated version of Swagger! Please see http://github.com/wordnik/swagger-core/wiki for more info' ]
It does appear that ari-client is using ver 1.2 which is the latest. And it's setting "swaggerVersion": "1.2" which also appears to be the correct setting.
Should I just ignore this?
Thank you!
If the connection's been lost and I'm trying to call channels.create
on the client
, the returned promise is never resolved or rejected, nor is there any error thrown. I don't know if this is related to #35 but #12 certainly doesn't fix it. The same happens with channel.dial
. I think other channel functions may behave the same.
Hi. In my small project become necessary listen multiple ARI instances same time, and interact with it. And now, i really don't have any idea how to realize this feature. Can you get me something like advice, or something like that? I don`t asking for working code, just for advice.
Thanks.
When calling ari.start()
, I encountered a mysterious error that left the following trace:
Unhandled rejection Error: undefined
at Object.ensureErrorObject (/home/<user>/src/<ari_app>/node_modules/bluebird/js/main/util.js:261:20)
at Promise._rejectCallback (/home/<user>/src/<ari_app>/node_modules/bluebird/js/main/promise.js:472:22)
at /home/<user>/src/<ari_app>/node_modules/bluebird/js/main/promise.js:489:17
at /home/<user>/src/<ari_app>/node_modules/ari-client/lib/client.js:327:11
at /home/<user>/src/<ari_app>/node_modules/underscore/underscore.js:890:21
at reconnect (/home/<user>/src/<ari_app>/node_modules/ari-client/lib/client.js:526:9)
at WebSocket.processError (/home/<user>/src/<ari_app>/node_modules/ari-client/lib/client.js:509:7)
at emitOne (events.js:77:13)
at WebSocket.emit (events.js:169:7)
at ClientRequest.response (/home/<user>/src/<ari_app>/node_modules/ws/lib/WebSocket.js:721:12)
at ClientRequest.g (events.js:260:16)
at emitOne (events.js:77:13)
at ClientRequest.emit (events.js:169:7)
at HTTPParser.parserOnIncomingClient (_http_client.js:433:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:103:23)
at Socket.socketOnData (_http_client.js:322:20)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at readableAddChunk (_stream_readable.js:153:18)
at Socket.Readable.push (_stream_readable.js:111:10)
at TCP.onread (net.js:537:20)
Suspiciously, it occurred about a minute after connecting. Looking around, it turned out that my ARI user had some special characters (+
) that weren't being escaped. When creating the websocket url, it added my user as is:
var wsUrl = util.format(
'%s://%s/ari/events?app=%s&api_key=%s:%s',
(self._connection.protocol === 'https:' ? 'wss' : 'ws'),
self._connection.host,
applications,
self._connection.user, // <-- may be unsafe
self._connection.pass
);
It resulted in 401
s that didn't bubble up well, and finally culminated in the above error.
Is this a bug? Or should I be url-encoding my own usernames/passwords...or should I simply avoid special characters altogether?
Resource instances should support the EventEmitter once function for registering event handlers.
The library documentation on the README is difficult to parse visually. Would be great if there were some sort of table of contents, and if the different header levels were more visually distinct, perhaps using color, emoji, or anything to help.
Would also be good to document the api of the Channel object, and any other objects that we create that are not part of the swagger api
There is a kind of "memory leak" in the list of event handlers (the _instanceListeners
attribute of the client object): if event handlers are registered on a channel, they are kept in memory event when the channel no longer exists.
Of course, this can be avoided by explicitly calling the method removeAllListeners
with the previously used events just before the channel disappears, but this behaviour is really unexpected.
If there is no general way to solve this issue, I think it should at least be documented.
When using client.connect() to connect to a Asterisk server (v 13.6.0), the client.connec() command does not throw an exception, emit any event nor do anything when it cannot connect to the server. This makes it impossible to detect if the client is actually connected or not
Hello,
I am having a problem with the handling of events triggered by a Local channel, which do not fire the listeners registered on its parent. The problem is a bit complex to explain, I will take an example:
var chan = ari.Channel();
chan.on('Dial', function(event) {
console.log('Dial received!');
});
chan.originate({
endpoint: 'Local/exten@context',
app: 'myApp',
appArgs: 'foo,bar'
});
The dialplan located at exten@context
is doing a Dial to a SIP peer, so I would expect to see Dial received
in the console, but it is not happening. However, I can see Dial events coming from the websocket.
After looking more closely at the events and digging through the code, I figured out that this has something to do with the fact that when we originate a Local endpoint, Asterisk actually creates two Local channels connected by a virtual endpoint. And my listener is registered on the first Local channel, but it is the second Local channel which triggers the Dial events.
To be more precise, I register the events on a channel named 123456.789
(for example), but the Dial events are bound to the "child" channel 123456.789;2
.
As there is no way to retrieve a reference to the child channel and thus register event handlers on it, I suggest that events bound to the child channel should trigger the listeners registered on the parent channel.
What do you think of that ? I did this modification on my own, I may submit it as a pull request if you will.
Here is a very simple use case
try {
ari.connect(config.url, config.user, config.pass, connErr => {
if (connErr) {
logger.log('error', 'caught from callback', connErr);
return;
}
logger.log('info', 'connected');
}).catch(e => {
logger.log('error', 'caught from promise', e);
});
} catch (e) {
logger.log('error', 'caught from try-catch', e);
}
If the credentials are invalid I get this error message and the program exits.
/home/artyom/WebstormProjects/pbsw-dialer/node_modules/swagger-client/lib/swagger.js:270
throw message;
^
401 : undefined http://localhost:8088/ari/api-docs/resources.json
I never actually catch the error which means I can't perform a resource cleanup or produce a custom error message or wrap the error or anything like that. I believe all connection errors should be catchable.
Some of the tests no longer pass if fixtures are generated from the latest version of Asterisk.
how to get current status of a call originate in ARI,means staus of call-originated is at -> local end is ringing OR remote end is ringing OR remote end is busy etc.
whats supposed to happen if I redirect the channel?
I'm using
incoming.redirect({endpoint: 'SIP/sip-trunk/123456789'})
.then(function () {
console.log('worked');
})
.catch(function (err) { console.log(err);});
and its only showing 'worked' in the console without actually doing something on the call.
Am I getting something wrong here?
Thanks & Cheers
Qiong
I use your API, ari-client, but I have a problem with the function "sendMessageToEndpoint". I use it like this :
ari.endpoints.sendMessageToEndpoint({
from: 'AstSae',
tech: 'SIP', resource: '91',
body: 'ESSAI',
variables: []},
function (err) {
if (err) {
throw err;
}
});
But the ARI request is :
PUT /ari/endpoints/SIP/91/sendMessage?from=AstSae HTTP/1.1
user-agent: Shred
Content-Type: application/json
Accept: application/json
Authorization: Basic YXJpdGVzdDp0ZXN0bWU=
Content-Length: 16
Host: 192.168.50.90:8088
Connection: keep-alive
{"variables":[]}
I can not see the body message.
And the resulting SIP message sending to SIP/91 is :
MESSAGE sip:[email protected];line=b6e881de237c150 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.90:5060;branch=z9hG4bK5c0bc190
Max-Forwards: 70
From: "AstSae" <sip:[email protected]>;tag=as43280f06
To: <sip:[email protected];line=b6e881de237c150>
Contact: <sip:[email protected]:5060>
Call-ID: 6399e2172b93f6092e82f6a229f7139c@[fe80::a65d:36ff:fecf:db94]:5060
CSeq: 102 MESSAGE
User-Agent: Asterisk PBX 13.5.0
Content-Type: text/plain;charset=UTF-8
Content-Length: 0
There is no Body Message.
Could you help me to understand ?
Best regards,
The library expects to connect to Asterisk's Websocket over WS, but in my current scenario, Asterisk has TLS and port 80 isnt exposed to the public internet. And so I'm connecting via WSS - the lib hardcodes WS - we should make this configurable
Using this project, connection to a newly installed asterisk 13.6.0 gives the following error:
[ 'This API is using a deprecated version of Swagger! Please see http://github.com/wordnik/swagger-core/wiki for more info' ]
node-ari-client: 0.1.5
nodejs: v0.10.32
asterisk: 13.0.0-beta3
the first call works fine, if I hangup and dial again, nothing happen, call hit Stasis but there're no log from nodejs, if I break nodejs and run again, it will work, but only for 1st call.
Trying to connect to an Asterisk server using HTTPS because the asterisk http server is running TLS does not work, if you do not use a hostname with certificate.
Maybe an option to allow it to connect but not validate the certificate when you use the ip to connect directly?
When I try to play a non-existing media by doing something like this
channel.play({media: 'sound:nonexisting'}, playback).then(function() {
console.log('Everything is fine');
}).catch((err) => {
console.log('Error>', err);
});
I never get an error even though in asterisk's logs I can find
WARNING[10620] res_stasis_playback.c: 1481280112.80: Playback failed for sound:nonexisting
I don't know if this is a node-ari-client issue or rather an ari one. I haven't been able to create an issue in https://github.com/asterisk/asterisk repo.
Client events use a built in EventEmitter. Resource specific events however use a wrapper around an EventEmitter. Some of the implementation is inconsistent with the way an EventEmitter should work.
1 - attaching more than one callback via resource.on('event', callback) only attaches the first callback
2 - removeListener acts like removeAllListeners but does not actually remove the underlying EventEmitter attached callback
3 - removeAllListeners is not implemented
If for some reason, a developer will try to start a Stasis application that has an undefined name (yes, it's stupid, but may happen), Client will not return any type of error or exception.
The issue should be handled within Client.prototype.start (I think):
Client.prototype.start = function (apps, subscribeAll, callback) {
var self = this;
// are we currently processing a WebSocket error?
var processingError = false;
// Perform argument renaming for backwards compatibility
if (typeof subscribeAll === 'function') {
callback = subscribeAll;
subscribeAll = null;
}
This may also provide some easy resolution for issue #35
This would make stubbing a couple of methods (namely connecting to the ARI) far easier in my tests, right now, as the Client isn't exported anywhere before it's instantiated I can't do that and I'll have to just mock up a server or something which I don't really want to do...
More than happy to do this myself if you agree!
I am not sure if it belongs here but it felt natural for me to put it here. I am running asterisk 13 on ubuntu 16. I enabled ari but when I try to use ari-client it says Error determining real directory for rest-api if I go to the web browser and try ari it says the same. it lets me in with user and password but then it wont serve the api.
hello ,
when i put more than one channel in a bridge, in this case event 'ChannelDtmfReceived' not emitting for all those channel , who are in created bridge.
Note :- event 'ChannelDtmfReceived' is emitting ,when single channel in a bridge.
On connecting to Asterisk I'm getting this error message?
[ 'This API is using a deprecated version of Swagger! Please see http://github.com/wordnik/swagger-core/wiki for more info' ]
For example when I got channelHangupRequest I want to hangup other party of a call. But the other party already could be hanged up due to transfer (e.g. without hangup request). So when i try to manipulate this channel by id I get uncatchable error:
/var/daemon/node_modules/ari-client/lib/client.js:244
userCallback(err);
^
TypeError: object is not a function
at swaggerError as errorCallback
at Object.obj.on.error (/var/daemon/node_modules/ari-client/node_modules/swagger-client/lib/swagger.js:1077:24)
at EventEmitter.res.error (/var/daemon/node_modules/ari-client/node_modules/swagger-client/lib/swagger.js:1296:19)
at EventEmitter.emit (events.js:109:17)
at emit (/var/daemon/node_modules/ari-client/node_modules/swagger-client/node_modules/shred/lib/shred/request.js:454:21)
at /var/daemon/node_modules/ari-client/node_modules/swagger-client/node_modules/shred/lib/shred/request.js:473:9
at setBodyAndFinish (/var/daemon/node_modules/ari-client/node_modules/swagger-client/node_modules/shred/lib/shred/response.js:103:7)
at IncomingMessage. (/var/daemon/node_modules/ari-client/node_modules/swagger-client/node_modules/shred/lib/shred/response.js:120:7)
at IncomingMessage.emit (events.js:131:20)
at _stream_readable.js:910:16
Yea, I know I should take care of that and prevent the use of non-existing channels but from the other side my worker can crash and stop if non existing channeld is used in ari.channels.hangup({})
. Let me know if you consider this is an issue or not. Thanks in advance!
Hi there, just came across this module and find it amazing!
So I tried setting up the example application (playback.js) and upon hangup I get the following message in the asterisk CLI
WARNING[15517][C-00000001]: res_stasis_playback.c:248 playback_final_update: 1459630813.2: Playback failed for sound:demo-congrats
When I call back that same extension that should play the example once again, I get no playback just a blank call. Upon restarting the node app I get the sound to play again.
Is there anything I may be doing wrong is does it have something to do with the playback.js code?
Hi,
Is it possible to add a parameter "option" in ari connect function to configure maxRetries, maxDelay and delay for backoff ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.