def get_complete_list_with_relations_owner(self, owner_userid, glob, limit, sort): """ Get *all* tags for owner_username's images and mark any that match the glob. @param owner_username: Owner of the account @type owner_username: String @param glob: A complex dictionary of limits for the user_images table see Glober.py for more details. @type glob: Dictionary """ valid_sorts = { 'title-asc': ("t1.tag_name", "asc"), 'title-desc': ("t1.tag_name", "desc"), 'date_asc': ("date_added", "asc"), 'date_desc': ("date_added", "desc"), 'count-asc': ("cnt_images", "asc"), 'count-desc': ("cnt_images", "desc"), 'recent':("last_used", "desc") } try: owner_userid = validation.cast_integer(owner_userid, 'owner_userid') validation.required(glob, 'glob') limit = validation.cast_integer(limit, 'limit') validation.oneof(sort, valid_sorts.keys(), 'sort') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def untag_image(self, owner_userid, tag_userid, image_id, tag_name): """ Removes assication with tag and image @param owner_username: Image owner username @type owner_username: String @param tag_username: username @type tag_username: String @param media_id: Id of image assciated with tag @type media_id: String @param tag_name: tag names to be associated with images (media_ids) @type tag_name: String @return: Nothing @rtype: Nothing """ try: owner_userid = validation.cast_integer(owner_userid, 'owner_userid') tag_userid = validation.cast_integer(tag_userid, 'owner_userid') media_id = validation.cast_integer(image_id, 'image_id') validation.required(tag_name, 'tag_name') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _make_media_path(self, media_id, host, username=None, width=None, height=None, crop=None): """ Makes a path to an image. @param media_id: ID of the image @type media_id: String @param host: Host that holds the image @type host: String @param username: User who modified the image (if applicable) @type username: String @param width: Width of the render @type width: Integer @param height: Height of the render @type height: Integer @param crop: Whether or not the render is cropped @type crop: Integer """ try: media_id = validation.media_id(media_id) validation.required(host, "host") if username: username = validation.username(username, "username") if width: width = validation.cast_integer(width, "width") height = validation.cast_integer(height, "height") crop = validation.cast_boolean(crop, "crop") except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def send_message(self, from_userid, to_userids, subject, body, reply_to_id): """ Sends a message to 1 or more recipients. @param from_username: User sending the message. @type from_username: String @param to_usernames: List of recipients @type to_usernames: List @param subject: Subject/heading of the message @type subject: String @param body: Body of the message @type body: String @param reply_to_id: Message being replied to, if applicable @type reply_to_id: Integer """ try: from_userid = validation.cast_integer(from_userid, 'from_userid') subject = validation.string(subject) validation.required(subject, 'subject') body = validation.string(body) validation.required(body, 'body') reply_to_id = validation.cast_integer(reply_to_id, 'reply_to_id') recipients = [] if not isinstance(to_userids, (list, tuple)): to_userids = [to_userids] for user in to_userids: recipients.append(validation.cast_integer(user, 'to_userid')) except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _generate_rendered(self, data, image_id, width, height, crop, quality): """ Generates and stores a rendered copy of an image for a given user. @param media_id: ID of the image being rendered. @type media_id: String @param data: Raw binary data for the image. @type data: String @param owner_username: User the image is being rendered for. @type owner_username: String @param width: Requested width of the image. @type width: Integer @param height: Requested height of the image. @type height: Integer @param crop: Whether or not the image should be cropped to exact size. @type crop: Boolean @param quality: Quality to use for the render. @type quality: Integer @return: Rendered binary data. @rtype: String """ try: validation.required(data, 'data') image_id = validation.cast_integer(image_id, 'image_id') width = validation.cast_integer(width, 'width') height = validation.cast_integer(height, 'height') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def update_image_comment(self, comment_owner, comment_id, subject, body, ip_address): """ Adds a comment to an image. @param commenting_username: Username making the comment. @type commenting_username: String @param comment_id: Comment being edited on. @type comment_id: Integer @param subject: Subject of the comment. @type subject: String @param body: Body of the comment. @type body: String @param ip_address: IP Address the comment is originating from @type ip_address: String @return: 0 on successful comment insertion, raises an exception otherwise. @rtype: Integer """ try: comment_owner = validation.cast_integer(comment_owner, 'comment_owner') comment_id = validation.cast_integer(comment_id, 'comment_id') validation.required(body, 'body') validation.required(ip_address, 'ip_address') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def completely_edit_tag(self, owner_userid, tag_name, new_name): """ Updates tag on all users pics @param owner_username: Image owner username @type owner_username: String @param tag_name: tag name to be removed @type tag_name: String @param new_name: new name for the tag @type new_name: String @return: Nothing @rtype: Nothing """ owner_userid = validation.cast_integer(owner_userid, 'owner_userid') validation.required(tag_name, 'tag_name') tag_name = tag_name.strip() tag_name = tag_name.lower() validation.required(new_name, 'new_name') new_name = new_name.strip() new_name = new_name.lower() d = self.app.db.runOperation( """ select zoto_update_tag_for_all_user_images(%s, %s, %s) """, (owner_userid, tag_name, new_name)) return d
def get_complete_list_with_relations_owner(self, owner_userid, glob, limit, sort): """ Get *all* tags for owner_username's images and mark any that match the glob. @param owner_username: Owner of the account @type owner_username: String @param glob: A complex dictionary of limits for the user_images table see Glober.py for more details. @type glob: Dictionary """ valid_sorts = { 'title-asc': ("t1.tag_name", "asc"), 'title-desc': ("t1.tag_name", "desc"), 'date_asc': ("date_added", "asc"), 'date_desc': ("date_added", "desc"), 'count-asc': ("cnt_images", "asc"), 'count-desc': ("cnt_images", "desc"), 'recent': ("last_used", "desc") } try: owner_userid = validation.cast_integer(owner_userid, 'owner_userid') validation.required(glob, 'glob') limit = validation.cast_integer(limit, 'limit') validation.oneof(sort, valid_sorts.keys(), 'sort') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def add_rendered(self, image_id, data, width, height, crop): """ Adds a rendered image to the filesystem. @param media_id: ID of the image being rendered. @type media_id: String @param owner_username: User who's account the image is being rendered for. @type owner_username: String @param data: Actual binary data of the render @type data: String @param width: Requested width @type width: Integer @param height: Requested height @type height: Integer @param crop: Whether or not the image was cropped @type crop: Boolean """ try: image_id = validation.cast_integer(image_id, 'image_id') validation.required(data, 'data') if width: width = validation.cast_integer(width, 'width') height = validation.cast_integer(height, 'height') crop = validation.cast_boolean(crop, 'crop') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def create_key(self, owner, app_name, email, url): """ Creates an API key and stores it in the global DB. @param owner: Name of the person/entity requesting the key. @type owner: String @param app_name: Name of the application that will be using the API key. @type app_name: String @param email: Contact address of the entity requesting the key. @type email: String @param url: Web address of the person/entity requesting the key. @type url: String @return: New API key @rtype: String """ try: validation.required(owner, 'owner') validation.required(app_name, 'app_name') validation.email(email) except errors.ValidationError, ex: self.log.warning("Validation failure: %s" % str(ex)) raise errors.APIError, str(ex)
def add_image_comment(self, owner_userid, commenting_userid, image_id, subject, body, ip_address): """ Adds a comment to an image. @param owner_username: Username who owns the image being commented on. @type owner_username: String @param commenting_username: Username making the comment. @type commenting_username: String @param media_id: Image being commented on. @type media_id: String @param subject: Subject of the comment. @type subject: String @param body: Body of the comment. @type body: String @param ip_address: IP Address the comment is originating from @type ip_address: String @return: 0 on successful comment insertion, raises an exception otherwise. @rtype: Integer """ try: owner_userid = validation.cast_integer(owner_userid, 'owner_userid') commenting_userid = validation.cast_integer(commenting_userid, 'commenting_userid') image_id = validation.cast_integer(image_id, "iamge_id") validation.required(body, 'body') validation.required(ip_address, 'ip_address') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def completely_edit_tag(self, owner_userid, tag_name, new_name): """ Updates tag on all users pics @param owner_username: Image owner username @type owner_username: String @param tag_name: tag name to be removed @type tag_name: String @param new_name: new name for the tag @type new_name: String @return: Nothing @rtype: Nothing """ owner_userid = validation.cast_integer(owner_userid, 'owner_userid') validation.required(tag_name, 'tag_name') tag_name = tag_name.strip() tag_name = tag_name.lower() validation.required(new_name, 'new_name') new_name = new_name.strip() new_name = new_name.lower() d = self.app.db.runOperation(""" select zoto_update_tag_for_all_user_images(%s, %s, %s) """, (owner_userid, tag_name, new_name)) return d
def _make_media_path(self, media_id, host, username=None, width=None, height=None, crop=None): """ Makes a path to an image. @param media_id: ID of the image @type media_id: String @param host: Host that holds the image @type host: String @param username: User who modified the image (if applicable) @type username: String @param width: Width of the render @type width: Integer @param height: Height of the render @type height: Integer @param crop: Whether or not the render is cropped @type crop: Integer """ try: media_id = validation.media_id(media_id) validation.required(host, 'host') if username: username = validation.username(username, 'username') if width: width = validation.cast_integer(width, 'width') height = validation.cast_integer(height, 'height') crop = validation.cast_boolean(crop, 'crop') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def add_rendered(self, image_id, data, width, height, crop): """ Adds a rendered image to the filesystem. @param media_id: ID of the image being rendered. @type media_id: String @param owner_username: User who's account the image is being rendered for. @type owner_username: String @param data: Actual binary data of the render @type data: String @param width: Requested width @type width: Integer @param height: Requested height @type height: Integer @param crop: Whether or not the image was cropped @type crop: Boolean """ try: image_id = validation.cast_integer(image_id, "image_id") validation.required(data, "data") if width: width = validation.cast_integer(width, "width") height = validation.cast_integer(height, "height") crop = validation.cast_boolean(crop, "crop") except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _read_binary(self, filename): """ Reads a binary file from the disk. @param filename: File to be read @type filename: String """ try: validation.required(filename, "filename") except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _delete_binary(self, filename): """ Safely deletes a file. @param filename: Name of the file to be deleted. @type filename: String """ try: validation.required(filename, 'filename') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _read_binary(self, filename): """ Reads a binary file from the disk. @param filename: File to be read @type filename: String """ try: validation.required(filename, 'filename') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _delete_binary(self, filename): """ Safely deletes a file. @param filename: Name of the file to be deleted. @type filename: String """ try: validation.required(filename, "filename") except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def get_media_source_id(self, source_name): """ Gets the source id from the media_sources that matches the name provided. @param source_name: Source name to be reconciled. @type source_name: String @return: Source id @rtype: (Deferred) Integer """ validation.required(source_name, 'source_name') return self.media_sources.get(source_name, 1)
def get_media_source_id(self, source_name): """ Gets the source id from the media_sources that matches the name provided. @param source_name: Source name to be reconciled. @type source_name: String @return: Source id @rtype: (Deferred) Integer """ validation.required(source_name, "source_name") return self.media_sources.get(source_name, 1)
def clear_renders(self, media_id, owner_username, node): """ Clears out all the renders for a particular user's image. @param media_id: ID of the media being cleared @type media_id: String @param owner_username: User who owns the image @type owner_username: String """ try: media_id = validation.media_id(media_id) owner_username = validation.username(owner_username) validation.required(node, 'node') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def clear_renders(self, media_id, owner_username, node): """ Clears out all the renders for a particular user's image. @param media_id: ID of the media being cleared @type media_id: String @param owner_username: User who owns the image @type owner_username: String """ try: media_id = validation.media_id(media_id) owner_username = validation.username(owner_username) validation.required(node, "node") except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def beta_blogger_get_blog_list(self, owner_userid, token): """ Gets a user's list of blogger blogs. @param owner_username: User to get blogs for. @type owner_username: String @param token: Auth token to use for communicating with beta blogger. @type token: String """ try: owner_userid = validation.cast_integer(owner_userid, 'owner_userid') token = validation.string(token) validation.required(token, 'token') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def delete_key(self, api_key): """ Deletes the specified API key from the database. @param api_key: API key to be deleted. @type api_key: String @return: nothing @rtype: nothing @raise errors.APIError: when api_key validation failed """ try: validation.required(api_key, 'api_key') except errors.ValidationError, ex: self.log.warning("Validation failure: %s" % str(ex)) raise errors.APIError, str(ex)
def get_key_info(self, api_key, include_key=False): """ Gets information about the supplied API key. @param api_key: The key to get information for. @type api_key: String @return: api key info @rtype: dictionary @raise errors.ValidationError: when api_key validation fails. """ try: validation.required(api_key, 'api_key') except errors.ValidationError, ex: self.log.warning("Validation failure: %s" % str(ex)) raise errors.APIError, str(ex)
def _write_binary(self, filename, data, delete=True): """ Writes a binary file to the filesystem. If delete is True, and the file already exists, it will be deleted. Otherwise, an exception is thrown. @param filename: Name of the file to write @type filename: String @param data: Binary data to be written @type data: String @param delete: Whether to delete or raise an exception @type delete: Boolean """ try: validation.required(filename, 'filename') validation.required(data, 'data') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _write_binary(self, filename, data, delete=True): """ Writes a binary file to the filesystem. If delete is True, and the file already exists, it will be deleted. Otherwise, an exception is thrown. @param filename: Name of the file to write @type filename: String @param data: Binary data to be written @type data: String @param delete: Whether to delete or raise an exception @type delete: Boolean """ try: validation.required(filename, "filename") validation.required(data, "data") except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _generate_render_paths(self, media_id, host, username=None): """ Generates all possible render storage for the given host/media_id/username. @param media_id: ID of the media rendered @type media_id: String @param host: Host the render is stored on @type host: String @param username: Specific username, if applicable @type username: String (or None) """ try: media_id = validation.media_id(media_id) validation.required(host, "host") if username: username = validation.username(username, "username") except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def _generate_render_paths(self, media_id, host, username=None): """ Generates all possible render storage for the given host/media_id/username. @param media_id: ID of the media rendered @type media_id: String @param host: Host the render is stored on @type host: String @param username: Specific username, if applicable @type username: String (or None) """ try: media_id = validation.media_id(media_id) validation.required(host, 'host') if username: username = validation.username(username, 'username') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def set_attr(self, owner_userid, image_id, key, value): """ Sets an attribute of an image. @param owner_username: Username @type owner_username: String @param media_id: Image ID @type media_id: String @param key: Field to set. One of ('title', 'description', 'date', 'camera_make', 'camera_model', 'fstop', 'exposure_time', 'focal_length', 'iso_speed', 'rotate_bit', 'flash_fired', 'lat', 'lng', 'alt') @type key: String @param value: Value to set field to. @type: String @return: Nothing @rtype: Nothing """ owner_userid = validation.cast_integer(owner_userid, 'owner_userid') image_id = validation.cast_integer(image_id, 'image_id') validation.required(key, 'key') validation.oneof(key, self.attr_fields.keys(), 'key') if key == 'date': validation.isodatetime(value, 'date') if key == 'lat' or key == 'lng': value = float(value) if key == 'title': value = utils.check_n_chop(value, 30) self.log.debug("setting image [%s] [%s]=>[%s]" % (image_id, key, value)) return self.app.db.runOperation(""" select zoto_image_set_attr(%s, %s, %s, %s) """, (owner_userid, image_id, key, utils.sql_escape(value)))
def get_complete_list_with_relations(self, auth_userid, owner_userid, glob, limit, sort): """ Get *all* tags on owner_username's images and mark any that match the glob @param owner_username: The user's tags we care about @type owner_username: String @param auth_username: The logged-in user that is trying to get the tag list @type auth_username: String @param glob: A complex dictionary of limits for the user_images table see Globber.py for more details @type glob: Dictionary @return: List of Dictionaries including tag_name, image_count, is_related (boolean) """ valid_sorts = { 'title-asc': ("t1.tag_name", "asc"), 'title-desc': ("t1.tag_name", "desc"), 'date_asc': ("date_added", "asc"), 'date_desc': ("date_added", "desc"), 'count-asc': ("cnt_images", "asc"), 'count-desc': ("cnt_images", "desc"), 'recent': ("last_used", "desc") } try: owner_userid = validation.cast_integer(owner_userid, 'owner_id') limit = validation.cast_integer(limit, 'limit') if auth_userid: auth_userid = validation.cast_integer(auth_userid, 'auth_userid') validation.required(glob, 'glob') validation.oneof(sort, valid_sorts.keys(), 'sort') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def get_complete_list_with_relations(self, auth_userid, owner_userid, glob, limit, sort): """ Get *all* tags on owner_username's images and mark any that match the glob @param owner_username: The user's tags we care about @type owner_username: String @param auth_username: The logged-in user that is trying to get the tag list @type auth_username: String @param glob: A complex dictionary of limits for the user_images table see Globber.py for more details @type glob: Dictionary @return: List of Dictionaries including tag_name, image_count, is_related (boolean) """ valid_sorts = { 'title-asc': ("t1.tag_name", "asc"), 'title-desc': ("t1.tag_name", "desc"), 'date_asc': ("date_added", "asc"), 'date_desc': ("date_added", "desc"), 'count-asc': ("cnt_images", "asc"), 'count-desc': ("cnt_images", "desc"), 'recent':("last_used", "desc") } try: owner_userid = validation.cast_integer(owner_userid, 'owner_id') limit = validation.cast_integer(limit, 'limit') if auth_userid: auth_userid = validation.cast_integer(auth_userid, 'auth_userid') validation.required(glob, 'glob') validation.oneof(sort, valid_sorts.keys(), 'sort') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def add_image_comment(self, owner_userid, commenting_userid, image_id, subject, body, ip_address): """ Adds a comment to an image. @param owner_username: Username who owns the image being commented on. @type owner_username: String @param commenting_username: Username making the comment. @type commenting_username: String @param media_id: Image being commented on. @type media_id: String @param subject: Subject of the comment. @type subject: String @param body: Body of the comment. @type body: String @param ip_address: IP Address the comment is originating from @type ip_address: String @return: 0 on successful comment insertion, raises an exception otherwise. @rtype: Integer """ try: owner_userid = validation.cast_integer(owner_userid, 'owner_userid') commenting_userid = validation.cast_integer( commenting_userid, 'commenting_userid') image_id = validation.cast_integer(image_id, "iamge_id") validation.required(body, 'body') validation.required(ip_address, 'ip_address') except errors.ValidationError, ex: return utils.return_deferred_error(ex.value)
def add(self, owner_userid, filename, data, image_source, title, description, testing=False): """ Add an image to the system. does all the fancy stuff of checking types, sources, quota, etc... This is as high-level as as it gets, call this if you need to add an image to the system. @param owner_username: Username that will own the image. @type username: String @param filename: The original filename of this image. @type filename: String @param data: The binary data of the image. @type data: byte-array (buffer or XMLRPC.Binary object) @param image_source: Where did this image come from? (Must be one of the entries in the media_sources table). @type image_source: String @param title: Title of the newly added image. @type title: String @param description: Description of the newly added image. @type description: String @param testing: If true, data contains the name of a local file to be read instead of binary data. Remove this once we are finished developing. @type testing: Boolean @return: New media_id of the image added. @rtype: (Deferred) String """ owner_userid = validation.cast_integer(owner_userid, 'owner_userid') validation.required(data, 'data') state = {} if not title: title = filename.replace(".jpg", "") title = title.replace(".JPG", "") ##======================== ## HACK FOR DEVELOPMENT ##======================== if testing: f = open(data, 'rb') data = f.read() f.close() if isinstance(data, Binary): data = data.data media_id = md5.md5(data).hexdigest() source_id = self.app.api.mediahost.get_media_source_id(image_source) @stack def store_image(void): self.log.debug("storing image %s" % media_id) return self.app.api.mediahost.add(data, source_id) @stack def assign_to_user(void): return self.set_user_image(owner_userid, media_id, filename, image_source, title, description, data) @stack def check_result(result): if result[0] == 0: image_id = result[1] return (0, (image_id, media_id)) else: return result # TODO: make sure the user has enough room to store it # TODO: check to see if it's a duplicate? -- no # TODO: do something for global stats (should be a DB trigger) d = manip.verify_jpeg(data) # make sure this is an acceptable image type d.addCallback(store_image) # store the image d.addCallback(assign_to_user) # assign the user to the image d.addCallback(check_result) return d