Skip to content
This repository has been archived by the owner on May 7, 2021. It is now read-only.

Commit

Permalink
v0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
tmarshall committed Jul 1, 2012
0 parents commit 435f6f2
Show file tree
Hide file tree
Showing 4 changed files with 387 additions and 0 deletions.
23 changes: 23 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Copyright 2012 Timothy J Marshall.
All rights reserved.

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
192 changes: 192 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
Dribbble Api 0.0.1
==================


# What's this?

This is a node module, serving as Dribbble API wrapper. See the [Dribbble API docs](http://dribbble.com/api/) for more details.


# Dependencies

Currently the only real dependency is [Request](https://github.com/mikeal/request).


# Installation

Currently the only way to install this is by taking the code and sticking it in node_modules folder.

Pretty soon it will be published to [NPM](http://npmjs.org/).


# Usage

Dribbble currently doesn't require any sort of auth key or access token. Still, this module is a constructor. This way, if things change and keys are required, the constructor would become more useful.

Making a request looks something like this:

```js
var dribbbleApi = require('dribbble-api')

var dribbble = new dribbbleApi()

dribbble.list('debuts', function(err, res, json, paging) { })
```

Every callback gets four arguments; An error (if there is one), the HTTP response, a JSON object (probably what you will want) and a paging object (more on this in the [paging section](#paging)).


## Player

All of the player-related functions require a player id (or username).

### Player Profile

```js
dribbble.player('44656', function(err, res, json, paging) {
console.log(json)
})
```

### Player Shots

```js
dribbble.playerShots('44656', function(err, res, json, paging) {
console.log(json) // json.shots
})
```

### Shots by Players Player is Following

```js
dribbble.playerFollowingShots('44656', function(err, res, json, paging) {
console.log(json) // json.shots
})
```

### Shots Liked by Player

```js
dribbble.playerLikes('44656', function(err, res, json, paging) {
console.log(json) // json.shots
})
```

### Players that Follow the Player

```js
dribbble.playerFollowers('44656', function(err, res, json, paging) {
console.log(json) // json.players
})
```

### Players that the Player Follows

```js
dribbble.playerFollows('44656', function(err, res, json, paging) {
console.log(json) // json.players
})
```

### Player Drafted by the Player

```js
dribbble.playerDraftees('44656', function(err, res, json, paging) {
console.log(json) // json.players
})
```


## Shots

All of the shot-related functions, except for `list`, require a shot id.

### Individual Shot

```js
dribbble.shot('300230', function(err, res, json, paging) {
console.log(json)
})
```

### Rebounds of a Shot

```js
dribbble.shotRebounds('43424', function(err, res, json, paging) {
console.log(json) // json.shots
})
```

### Comments for a Shot

```js
dribbble.shotComments('43424', function(err, res, json, paging) {
console.log(json) // json.comments
})
```

### Lists of Shots

This one is a bit different. It does not take a shot id. Instead, it takes the name of a list.

Possible names are `popular`, `debuts` and `everyone`.

If you don't pass a list name it will default to `popular`.

```js
dribbble.list('popular', function(err, res, json, paging) {
console.log(json) // json.shots
})

// has the same effect as

dribbble.list(function(err, res, json, paging) {
console.log(json) // json.shots
})
```


# Options

Dribbble allows for options to be set. You can set these by passing your options, as an `{}` object, just before the callback.

```js
dribbble.lists('debuts', { per_page: 30, page: 5 }, function(err, res, json, paging) { })
```


# Paging

The paging object returned to the callbacks may contain a `next` or `previous` function. These functions allow you to make another request, using the same arguments passed before, but with a new callback.

Here's an example where we request as many pages as we can, from the 'popular list', and add all resulting shots to the `popularShots` array.
Once this is done we'll call `onRequestsFinished`.

```js
var popularShots = []

var onRequestsFinished = function() {
// do something
}

var requestCallback = function(err, res, json, paging) {
if (Array.isArray(json.shots)) {
popularShots = popularShots.concat(json.shots)
}

if (paging.next) {
paging.next(requestCallback)
}
else {
onRequestsFinished()
}
}

dribbble.list('popular', requestCallback)
```

# Future Plans

* User constructor, similar to the one in the [Facebook Graph API](https://github.com/tmarshall/Facebook-Graph-API#using-the-user-object)
* Performance tweaks
* publish to NPM
146 changes: 146 additions & 0 deletions dribbble.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
var
request = require('request'),
querystring = require('querystring'),
pathArgs = /:([a-z]+)(?:\=([a-z,]+))?/gi,
pathArg = /:([a-z]+)(?:\=([a-z,]+))?/i,
slice = Array.prototype.slice

// constructor
function court() {
return this
}

// building the func that the prototype will use
function pregame(name, path) {
var
expected = [],
match, possible

// parsing paths
// e.g.
// 'shots/:id/rebound' will expect the first argument to be that of 'id'
// 'shots/:id=tmars,44656' expects an 'id' that can only be set to 'tmars' or '44656', defaulting to 'tmars'
// note that things will not work properly if you try to set a defaulting argument after a non-defaulting argument
pathArgs.lastIndex = 0
while ((match = pathArgs.exec(path)) !== null) {
expected.push({
name: match[1],
allowed: (possible = match[2] != undefined ? match[2].split(',') : undefined),
assume: possible != undefined ? possible[0] : undefined
})
}

// the actual function that will be used
return function() {
var
lex = this,
args = slice.call(arguments),
options,
callback,
actual,
adjustedPath = path,
diff,
i

// sent too many arguments?
if (args.length > expected.length + 2 /* 2 = options + callback */) {
throw 'Too many arguments passed to .' + name + '()'
return;
}

// last argument must always be the callback
if (typeof args[args.length - 1] !== 'function') {
throw 'No callback given for .' + name + '()'
return;
}

callback = args.pop()

// may have sent options, just before callback
if (typeof args[args.length - 1] === 'object') {
options = args.pop()
}

// making sure the passed arguments (sans callback) match the expected
for (i = 0, diff = expected.length - args.length; i < expected.length; i++) {
actual = args.length >= expected.length - i ? args[ i - diff ] : expected[i].assume

// if not a defaulting argument, then throw
if (actual == undefined) {
throw 'No value given for ' + expected[i].name
return;
}

// if not in the allowed values set
if (expected[i].allowed && !~expected[i].allowed.indexOf(actual)) {
throw 'Value passed is not one of the following: ' + expected[i].allowed.join(', ')
return;
}

adjustedPath = adjustedPath.replace(pathArg, actual)
}

// firing request
!function gameon(options, callback) {
request('http://api.dribbble.com/' + adjustedPath + (options ? '?' + querystring.stringify(options) : ''), function(err, res, body) {
var paging = {}

// not sure if this try catch is needed (or a good idea)
try {
body = JSON.parse(body)
} catch(e) {}

if (
typeof body.pages === 'number' &&
typeof body.page === 'number'
) {
if (body.page < body.pages) {
options = options || {}

paging.next = function(callback) {
options.page = body.page + 1

gameon(options, callback)

return lex
}
}

if (body.page > 1) {
options = options || {}

paging.previous = function(callback) {
options.page = body.page - 1

gameon(options, callback)

return lex
}
}
}

callback(err, res, body, paging)
})
}(options, callback)

return this
}
}

;[
{ name: 'shot', path: 'shots/:id' },
{ name: 'shotRebounds', path: 'shots/:id/rebounds' },
{ name: 'shotComments', path: 'shots/:id/comments' },
{ name: 'list', path: 'shots/:list=popular,everyone,debuts' },
{ name: 'player', path: 'players/:id' },
{ name: 'playerShots', path: 'players/:id/shots' },
{ name: 'playerFollowingShots', path: 'players/:id/shots/following' },
{ name: 'playerLikes', path: 'players/:id/shots/likes' },
{ name: 'playerFollowers', path: 'players/:id/followers' },
{ name: 'playerFollows', path: 'players/:id/following' },
{ name: 'playerDraftees', path: 'players/:id/draftees' }
].forEach(function(definition) {
court.prototype[definition.name] = pregame(definition.name, definition.path)
})

module.exports = court
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "Dribbble_API",
"description": "Node.js wrapper for the Dribbble API",
"version": "0.0.1",
"author": "Tim Marshall <timothyjmarhall@gmail.com>",
"repository": {
"type": "git",
"url": "git://github.com/tmarshall/Dribbble-API.git"
},
"os": [ "osx", "linux" ],
"directories": { },
"main": "dribbble",
"dependencies" : {
"request": "*"
},
"engines": {
"node" : ">=0.4.8"
},
"bugs": {
"url" : "http://github.com/tmarshall/Dribbble-API/issues"
},
"licenses": [{
"type": "MIT",
"url": "http://github.com/tmarshall/Dribbble-API/raw/master/LICENSE"
}]
}

0 comments on commit 435f6f2

Please sign in to comment.