You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

spypoint-api-wrapper

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

spypoint-api-wrapper - npm Package Compare versions

Comparing version

to
2.1.0

check.js

14

package.json
{
"name": "spypoint-api-wrapper",
"version": "2.0.2",
"version": "2.1.0",
"description": "Node.js wrapper for the Spypoint game camera API",
"main": "spypoint.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "jest test.js"
},

@@ -15,2 +15,4 @@ "keywords": [

"game",
"camera",
"trail",
"camera"

@@ -23,3 +25,7 @@ ],

},
"type": "module"
}
"type": "module",
"devDependencies": {
"dotenv": "^15.0.0",
"jest": "^27.4.7"
}
}

@@ -11,6 +11,40 @@ # spypoint-api-wrapper

const Spypoint = new SpypointClient('YOUR_EMAIL_OR_USERNAME', 'YOUR_PASSWORD')
await Spypoint.login()
const Spypoint = new SpypointClient()
await Spypoint.login('YOUR_EMAIL_OR_USERNAME', 'YOUR_PASSWORD')
```
### Using within express.js routes and individual users
```js
import SpypointClient from './spypoint.js'
const SpypointInit = (req, res, next) => {
if (!req.cookies.authorization) throw Error('You need to login with valid credentials first!')
req.Spypoint = new SpypointClient(req.cookies.authorization)
next()
}
// Send user crederntials to login route and set auth token on the cookie
router.post('/login', async (req, res) => {
const Spypoint = new SpypointClient()
const bearer = await Spypoint.login(req.body.email, req.body.password)
res.cookie('authorization', bearer, {
expire: '2100-01-01T00:00:00.000Z,
httpOnly: process.env.NODE_ENV === 'production' ? true : false
})
res.send()
})
router.get('/', SpypointInit, (req, res) => {
const cameras = await req.Spypoint.cameras()
res.send(cameras)
})
```
## API

@@ -21,3 +55,2 @@

### Spypoint.login() ⇒ <code>Promise.&lt;string&gt;</code>
**Kind**: Spypoint method

@@ -29,3 +62,2 @@ **Returns**: <code>Promise.&lt;string&gt;</code> - Bearer token used for authorization (this is automatically set and added to all requests)

### Spypoint.cameras() ⇒ <code>Promise.&lt;Array&gt;</code>
**Kind**: Spypoint method

@@ -36,6 +68,5 @@ **Returns**: <code>Promise.&lt;Array&gt;</code> - List of all available `cameraId`s

### Spypoint.filters() ⇒ <code>Promise.&lt;Array&gt;</code>
**Kind**: Spypoint method
### Spypoint.filters() ⇒ <code>Promise.&lt;Object&gt;</code>
**Returns**: <code>Promise.&lt;Array&gt;</code> - List of all available filter tags
**Returns**: <code>Promise.&lt;Object&gt;</code> - Object containing a property `.species` w/ list of all available filter tags

@@ -45,3 +76,2 @@ <a name="Spypoint.mostRecentPhotosByCamera"></a>

### Spypoint.mostRecentPhotosByCamera() ⇒ <code>Promise.&lt;Array&gt;</code>
**Kind**: Spypoint method

@@ -53,3 +83,2 @@ **Returns**: <code>Promise.&lt;Array&gt;</code> - List of most recent photo taken from each camera

### Spypoint.photosByCamera(cameraId, [options]) ⇒ <code>Promise.&lt;Array&gt;</code>
**Kind**: Spypoint method

@@ -65,6 +94,5 @@ **Returns**: <code>Promise.&lt;Array&gt;</code> - List of photos from an individual camera

<a name="Spypoint.allPhotosByFilter"></a>
<a name="Spypoint.queryAllPhotos"></a>
### Spypoint.allPhotosByFilter([options]) ⇒ <code>Promise.&lt;Array&gt;</code>
**Kind**: Spypoint method
### Spypoint.queryAllPhotos([options]) ⇒ <code>Promise.&lt;Array&gt;</code>

@@ -77,2 +105,4 @@ **Returns**: <code>Promise.&lt;Array&gt;</code> - List of photo by individual camera

| [options.tags] | <code>Array</code> \| <code>string</code> | Array of filter tag options or a single tag as a string |
| [options.limit] | <code>Number</code> | Maximum number of results to return |
| [options.limit] | <code>Number</code> | Maximum number of results to return |

@@ -13,14 +13,10 @@ import fetch from 'node-fetch'

constructor(
username = isRequired(),
password = isRequired()
){
this._username = username
this._password = password
constructor(authorization) {
this._headers = {
'Content-Type': 'application/json'
}
this._headers.authorization = authorization
}
async get(apiEndpoint) {
async _get(apiEndpoint) {
const data = await fetch(apiEndpoint, {

@@ -32,4 +28,6 @@ headers: this._headers

async post(cameraId = isRequired(), options = { tags: [], limit: 100 }) {
async _post(cameraId = isRequired(), { limit: 100, tags: []} = {}) {
const { limit, tags } = options
const data = await fetch(PHOTOS, {

@@ -39,3 +37,3 @@ method: 'POST',

body: JSON.stringify({
cameraId: [cameraId],
camera: [cameraId],
dateEnd: "2100-01-01T00:00:00.000Z",

@@ -52,7 +50,40 @@ favorite: false,

/**
* Note: This is an async function, it retrieves a list of available tags from Spytpoint and
* compares the provided tags to ensure they match. Spypoint occasionally changes these hence why
* this is necessary otherwise it will return an error if you add a no longer supported tag.
*/
async _tagParamCheck(tags){
if (typeof tags === 'string'){
tags = [tags]
}
if (!Array.isArray(tags)){
return console.error('Tag parameter needs to either be a string or an array of strings')
}
tags = tags.map(tag => tag.toLowerCase())
const filters = await this.filters()
const filteredNames = filters.species.map(({nameId}) => nameId)
const cleanTags = tags.filter( tag => {
if (!filteredNames.includes(tag)){
console.error(`The tag "${tag}" is not an available option.
Please check your spelling or use Spypoint.filters() to
see all available tags.`)
return false
}
return tag
})
return cleanTags
}
/**
* @return {Object} - Auth token and uuid credentials
*/
async login() {
async login(username, password) {
const credentialRes = await fetch(LOGIN, {

@@ -62,4 +93,4 @@ method: 'POST',

body: JSON.stringify({
username: this._username,
password: this._password
username,
password
})

@@ -83,4 +114,4 @@ })

async cameras() {
const cameras = await this.get(CAMERAS)
return cameras.json()
const cameras = await this._get(CAMERAS)
return cameras
}

@@ -93,4 +124,4 @@

async filters() {
const filters = await this.get(FILTERS)
return filters.json()
const filters = await this._get(FILTERS)
return filters
}

@@ -105,19 +136,25 @@

async photosByCamera(cameraId = isRequired(), options = { limit: 100, tags: [] }){
const photos = await this.post(cameraId, {limit, tags})
return photos.json()
async photosByCamera(cameraId = isRequired(), { limit = 100, tags = []} = {}){
tags = await this._tagParamCheck(tags)
const photos = await this._post(cameraId, { limit, tags })
return photos
}
/**
* @param {string[]|string} [tags=[]] - Query to limit results by photo subject i.e. 'deer', 'bears'
* @return {Object[]} - The most recent photo from each camera
*/
async mostRecentPhotosByCamera() {
async mostRecentPhotosByCamera(tags = []) {
const cameras = await this.cameras()
const photoReq = cameras.map(({ id }) => this.photosByCamera(id, { limit: 1 }))
const photoReq = cameras.map(({ id }) => this.photosByCamera(id, { limit: 1, tags }))
const photoDataRes = await Promise.all(photoReq)
return photoDataRes
.filter(({ photos }) => !!photos.length)
.map(({ photos }) => photos[0])
.filter(({ cameraIds }) => !!cameraIds.length)
.map(photoList => photoList.photos[0])

@@ -132,30 +169,14 @@ }

async queryAllPhotos(options = { limit: 100, tags: []}) {
/**
* Note: The Spypoint API limits results to most recent 25 photos
*/
if (typeof options.tags === 'string'){
options.tags = [options.tags]
}
async queryAllPhotos({ limit = 100, tags = []} = { limit, tags }) {
if (!Array.isArray(options.tags)){
return console.error('Tag parameter needs to either be a string or an array of strings')
}
tags = await this._tagParamCheck(tags)
options.tags = options.tags.map(tag => tag.toLowerCase())
const filters = await this.filters()
const filteredNames = filters.species.map(({nameId}) => nameId)
const cleanTags = options.tags.filter( tag => {
if (!filteredNames.includes(tag)){
console.error(`The tag "${tag}" is not an available option. Please check your spelling.`)
return false
}
return tag
})
const cameras = await this.cameras()
const photoReq = cameras.map(({ id }) => {
return this.photosByCamera(id, {limit: options.limit, tags: cleanTags})
return this.photosByCamera(id, {limit, tags})
})

@@ -162,0 +183,0 @@ const photoRes = await Promise.all(photoReq)