Code Monkey home page Code Monkey logo

node-ari-client's Issues

replace jsdoc with a non-abandoned project

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.

unmute

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

ari could not restart automatically

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?

Initial connection failure : update swagger-client ?

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 ?

adding multiple channels to a bridge

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.

Swagger Client Out of Date

[ '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.

Swagger.js does not respect body parameter type

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.

ws build failure on win10 x64

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?

Support sending via the ARI Proxy Messaging Protocol

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!

client.originate() doesn't set exten value on originated channel

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!

Documentation: Passing playbacks as parameters for .play()

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.

'channelStateChange' not emmiting properly.

'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.

getStoredFile() fails

Description:

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.

The correct way to make a call

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?

ari.channels.create() and ari.channels.dial() function not working

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)

Update README

Update the generated README using the latest version of Asterisk.

ws dependency not compiling in node 0.12.7

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.

Swagger API deprecated message

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!

channels.create hangs when there is no connection

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.

Listen to multiple instanses

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.

Cryptic error when ARI user password has special characters

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 401s 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?

Documentation difficult to read

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

Event handler leak

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.

client.connect() does not throw exception on no connection

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

Allow events of a child Local channel to fire the listeners registered on its parent

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:

  • First, I create a channel and register a listener on it:
var chan = ari.Channel();
chan.on('Dial', function(event) {
    console.log('Dial received!');
});
  • Then, I do an originate on this channel, targeting a Local endpoint:
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.

ari-client.connect authentication error should be catchable

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.

how to get call originate event

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.

redirect doesnt work

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

Problem with ari-client : sendMessage

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,

connecting over wss doesn't work

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

Swagger needs to be updated

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' ]

ari only response to the first call

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.

How to get the status of a failed playback

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.

Resource specific events inconsistent with Client events

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

Client.prototype.start undefined apps silently dies

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

Can you allow move the Client out to another file?

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!

Error determining real directory for rest-api

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.

'ChannelDtmfReceived' event not emitting

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.

Getting a swagger caution

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' ]

Error when working with non existing channels

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!

No playback after hangup

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?

Options for backoff in connect()

Hi,

Is it possible to add a parameter "option" in ari connect function to configure maxRetries, maxDelay and delay for backoff ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.