throw new TypeError('Parameter "url" must be a string, not ' + typeof url);
Opened this issue · 4 comments
I ran download-all.js and it ran for a while downloading 4,327 videos before getting the error below. I am about to look at this closer to see if I can figure it out. I know that there are more videos after this, but this might be about where there is a gap where several months ago a bunch of videos were deleted from the ring web portal.
url.js:103
throw new TypeError('Parameter "url" must be a string, not ' + typeof url);
^TypeError: Parameter "url" must be a string, not undefined
at Url.parse (url.js:103:11)
at Object.urlParse [as parse] (url.js:97:13)
at ring.recording (...RingVids\download-all.js:64:46)
at simpleRequest (...RingVids\node_modules\doorbot\doorbot.js:357:13)
at fetch (...RingVids\node_modules\doorbot\doorbot.js:176:17)
at IncomingMessage.res.on (...RingVids\node_modules\doorbot\doorbot.js:125:17)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
Looks like the recording
URL is coming back as null
here:
https://github.com/davglass/doorbot/blob/master/examples/download-all.js#L62
I'm able to reproduce this. I think it is because some of my cameras have a plan and others do not on my account. So on this line ring.recording(info.id, (e, recording)
* e=API returned Status Code 403
To debug I added console log messages like this one console.log('info: ' + JSON.stringify(info))
//First value is HistoryLimit, max return is 100 so I hardcoded 1000 to make sure this number is bigger than what the API returns
ring.history(1000, olderthan, (e, history) => {
const fetch = (info, callback) => {
console.log('info: ' + JSON.stringify(info))
ring.recording(info.id, (e, recording) => {
if (e != null) {
console.log('Error: ' + e)
return
}
//Calculate the filename we want this to be saved as
console.log('recording: ' + JSON.stringify(recording))
const datea = dateFormat(info['created_at'],"yyyymmdd_HHMMssZ");
const partFilePath = url.parse(recording).pathname.substring(0,url.parse(recording).pathname.length - 4);
const parts = partFilePath.split('/');
const filePath = '/' + parts[1] + '/' + datea + '_' + parts[2] + '.mp4';
const file = path.join(base, '.', filePath);
This is the output (I removed potentially confidentail information):
info: {"id":"1234","created_at":"2018-12-19T13:54:31.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":656,"description":"CameraWithPlan"}}
info: {"id":"1235","created_at":"2018-12-19T13:44:18.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
info: {"id":"1236","created_at":"2018-12-19T13:07:32.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
info: {"id":"1237","created_at":"2018-12-19T13:03:15.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
info: {"id":"1238","created_at":"2018-12-19T12:08:42.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
info: {"id":"1239","created_at":"2018-12-19T12:05:45.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":656,"description":"CameraWithPlan"}}
info: {"id":"1240","created_at":"2018-12-19T12:05:07.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
info: {"id":"1241","created_at":"2018-12-19T12:03:00.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
info: {"id":"1242","created_at":"2018-12-19T12:01:12.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
info: {"id":"1243","created_at":"2018-12-19T12:00:07.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
Error: Error: API returned Status Code 403
Error: Error: API returned Status Code 403
Error: Error: API returned Status Code 403
Error: Error: API returned Status Code 403
Error: Error: API returned Status Code 403
Error: Error: API returned Status Code 403
recording: "https://ring-transcoded-videos.s3.amazonaws.com/833/1234.mp4?..."
Error: Error: API returned Status Code 403
recording: "https://ring-transcoded-videos.s3.amazonaws.com/833/1239.mp4?..."
Error: Error: API returned Status Code 403
Fetching file /private/tmp/doorbot/downloads/833/20181219_075431CST_1234.mp4
Fetching file /private/tmp/doorbot/downloads/833/20181219_060545CST_1239.mp4
Done writing /private/tmp/doorbot/downloads/833/20181219_060545CST_1239.mp4
info: {"id":"1244","created_at":"2018-12-19T00:25:10.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
Error: Error: API returned Status Code 403
Done writing /private/tmp/doorbot/downloads/833/20181219_075431CST_1234.mp4
info: {"id":"1245","created_at":"2018-12-19T00:20:42.000Z","answered":false,"events":[],"kind":"motion","favorite":false,"snapshot_url":"","recording":{"status":"ready"},"duration":0,"doorbot":{"id":370,"description":"NoPlanCamera"}}
Error: Error: API returned Status Code 403
Above the NoPlanCamera
is my camera that does not store video. And the other CameraWithPlan
does have video history. So I think the code just needs some simple error detection for this use case.
I think this may be the solution to the issue. Add:
if (e != null) {
console.log('Recording Error: ' + e)
return callback();
}
After:
ring.history(1000, olderthan, (e, history) => {
const fetch = (info, callback) => {
ring.recording(info.id, (e, recording) => {
--->HERE
:
:
Funny. I had fixed this a long time ago and just recently ran across it again. Thanks for the answer.