else:
raise HTTPError(400, 'unknown operation')
+ @asynchronous
+ def post(self, camera_id, op, filename=None, group=None):
+ if camera_id is not None:
+ camera_id = int(camera_id)
+ if camera_id not in config.get_camera_ids():
+ raise HTTPError(404, 'no such camera')
+
+ if op == 'delete':
+ self.delete(camera_id, filename)
+
+ else:
+ raise HTTPError(400, 'unknown operation')
+
@BaseHandler.auth(prompt=False)
def current(self, camera_id):
self.set_header('Content-Type', 'image/jpeg')
def list(self, camera_id):
logging.debug('listing pictures for camera %(id)s' % {'id': camera_id})
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
-
camera_config = config.get_camera(camera_id)
if utils.local_camera(camera_config):
def on_media_list(media_list):
logging.debug('downloading picture %(filename)s of camera %(id)s' % {
'filename': filename, 'id': camera_id})
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
-
camera_config = config.get_camera(camera_id)
if utils.local_camera(camera_config):
content = mediafiles.get_media_content(camera_config, filename, 'picture')
logging.debug('previewing picture %(filename)s of camera %(id)s' % {
'filename': filename, 'id': camera_id})
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
-
camera_config = config.get_camera(camera_id)
if utils.local_camera(camera_config):
content = mediafiles.get_media_preview(camera_config, filename, 'picture',
height=self.get_argument('height', None))
@BaseHandler.auth()
- def zipped(self, camera_id, group):
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
+ def delete(self, camera_id, filename):
+ logging.debug('deleting picture %(filename)s of camera %(id)s' % {
+ 'filename': filename, 'id': camera_id})
+
+ camera_config = config.get_camera(camera_id)
+ if utils.local_camera(camera_config):
+ try:
+ mediafiles.del_media_content(camera_config, filename, 'picture')
+ self.finish_json()
+
+ except Exception as e:
+ self.finish_json({'error': unicode(e)})
+
+ else: # remote camera
+ def on_response(response=None, error=None):
+ if error:
+ return self.finish_json({'error': 'Failed to delete picture from %(url)s: %(msg)s.' % {
+ 'url': remote.make_camera_url(camera_config)}, 'msg': error})
+
+ self.finish_json()
+ remote.del_media_content(camera_config, on_response, filename=filename, media_type='picture')
+
+ @BaseHandler.auth()
+ def zipped(self, camera_id, group):
key = self.get_argument('key', None)
if key:
logging.debug('serving zip file for group %(group)s of camera %(id)s with key %(key)s' % {
@BaseHandler.auth()
def timelapse(self, camera_id, group):
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
-
key = self.get_argument('key', None)
if key:
logging.debug('serving timelapse movie for group %(group)s of camera %(id)s with key %(key)s' % {
else:
raise HTTPError(400, 'unknown operation')
+ @asynchronous
+ def post(self, camera_id, op, filename=None):
+ if camera_id is not None:
+ camera_id = int(camera_id)
+ if camera_id not in config.get_camera_ids():
+ raise HTTPError(404, 'no such camera')
+
+ if op == 'delete':
+ self.delete(camera_id, filename)
+
+ else:
+ raise HTTPError(400, 'unknown operation')
+
@BaseHandler.auth()
def list(self, camera_id):
logging.debug('listing movies for camera %(id)s' % {'id': camera_id})
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
-
camera_config = config.get_camera(camera_id)
if utils.local_camera(camera_config):
def on_media_list(media_list):
logging.debug('downloading movie %(filename)s of camera %(id)s' % {
'filename': filename, 'id': camera_id})
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
-
camera_config = config.get_camera(camera_id)
if utils.local_camera(camera_config):
content = mediafiles.get_media_content(camera_config, filename, 'movie')
logging.debug('previewing movie %(filename)s of camera %(id)s' % {
'filename': filename, 'id': camera_id})
- if camera_id not in config.get_camera_ids():
- raise HTTPError(404, 'no such camera')
-
camera_config = config.get_camera(camera_id)
if utils.local_camera(camera_config):
content = mediafiles.get_media_preview(camera_config, filename, 'movie',
width=self.get_argument('width', None),
height=self.get_argument('height', None))
+ def delete(self, camera_id, filename):
+ logging.debug('deleting movie %(filename)s of camera %(id)s' % {
+ 'filename': filename, 'id': camera_id})
+
+ camera_config = config.get_camera(camera_id)
+ if utils.local_camera(camera_config):
+ try:
+ mediafiles.del_media_content(camera_config, filename, 'movie')
+ self.finish_json()
+
+ except Exception as e:
+ self.finish_json({'error': unicode(e)})
+
+ else: # remote camera
+ def on_response(response=None, error=None):
+ if error:
+ return self.finish_json({'error': 'Failed to delete movie from %(url)s: %(msg)s.' % {
+ 'url': remote.make_camera_url(camera_config)}, 'msg': error})
+
+ self.finish_json()
+
+ remote.del_media_content(camera_config, on_response, filename=filename, media_type='movie')
+
class UpdateHandler(BaseHandler):
@BaseHandler.auth(admin=True)
http_client = AsyncHTTPClient()
http_client.fetch(request, on_response)
+
+
+def del_media_content(local_config, callback, filename, media_type):
+ host = local_config.get('@host', local_config.get('host'))
+ port = local_config.get('@port', local_config.get('port'))
+ username = local_config.get('@username', local_config.get('username'))
+ password = local_config.get('@password', local_config.get('password'))
+ uri = local_config.get('@uri', local_config.get('uri')) or ''
+ camera_id = local_config.get('@remote_camera_id', local_config.get('remote_camera_id'))
+
+ logging.debug('deleting file %(filename)s of remote camera %(id)s on %(url)s' % {
+ 'filename': filename,
+ 'id': camera_id,
+ 'url': make_camera_url(local_config)})
+
+ uri += '/%(media_type)s/%(id)s/delete/%(filename)s' % {
+ 'media_type': media_type,
+ 'id': camera_id,
+ 'filename': filename}
+
+ request = _make_request(host, port, username, password, uri, method='POST', timeout=settings.REMOTE_REQUEST_TIMEOUT)
+
+ def on_response(response):
+ if response.error:
+ logging.error('failed to delete file %(filename)s of remote camera %(id)s on %(url)s: %(msg)s' % {
+ 'filename': filename,
+ 'id': camera_id,
+ 'url': make_camera_url(local_config),
+ 'msg': unicode(response.error)})
+
+ return callback(error=unicode(response.error))
+
+ return callback()
+
+ http_client = AsyncHTTPClient()
+ http_client.fetch(request, on_response)
});
}
+function doDeleteFile(uri, callback) {
+ var url = window.location.href;
+ var parts = url.split('/');
+ url = parts.slice(0, 3).join('/') + uri;
+
+ runConfirmDialog('Really delete this file?', function () {
+ ajax('POST', url, null, function () {
+ if (callback) {
+ callback();
+ }
+ });
+ }, {stack: true});
+}
+
+
/* fetch & push */
/* dialogs */
-function runAlertDialog(message, onOk) {
- runModalDialog({title: message, buttons: 'ok', onOk: onOk});
+function runAlertDialog(message, onOk, options) {
+ var params = {
+ title: message,
+ buttons: 'ok',
+ onOk: onOk
+ };
+
+ if (options) {
+ Object.update(params, options);
+ }
+
+ runModalDialog(params);
}
-function runConfirmDialog(message, onYes) {
- runModalDialog({title: message, buttons: 'yesno', onYes: onYes});
+function runConfirmDialog(message, onYes, options) {
+ var params = {
+ title: message,
+ buttons: 'yesno',
+ onYes: onYes
+ };
+
+ if (options) {
+ Object.update(params, options);
+ }
+
+ runModalDialog(params);
}
function runPictureDialog(entries, pos, mediaType) {
var downloadButton = $('<div class="media-list-download-button button">Download</div>');
entryDiv.append(downloadButton);
+ var deleteButton = $('<div class="media-list-delete-button button">Delete</div>');
+
+ if (user === 'admin') {
+ entryDiv.append(deleteButton);
+ }
+
var nameDiv = $('<div class="media-list-entry-name">' + entry.name + '</div>');
entryDiv.append(nameDiv);
entryDiv.append(detailsDiv);
downloadButton.click(function () {
- downloadFile('/picture/' + cameraId + '/download' + entry.path);
+ downloadFile('/' + mediaType + '/' + cameraId + '/download' + entry.path);
return false;
});
+ deleteButton.click(function () {
+ doDeleteFile('/' + mediaType + '/' + cameraId + '/delete' + entry.path, function () {
+ entryDiv.remove();
+ });
+
+ return false;
+ });
+
entryDiv.click(function () {
var pos = entries.indexOf(entry);
runPictureDialog(entries, pos, mediaType);