diff options
Diffstat (limited to 'mediagoblin/plugins/archivalook/tools.py')
-rw-r--r-- | mediagoblin/plugins/archivalook/tools.py | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/mediagoblin/plugins/archivalook/tools.py b/mediagoblin/plugins/archivalook/tools.py new file mode 100644 index 00000000..9c715c9b --- /dev/null +++ b/mediagoblin/plugins/archivalook/tools.py @@ -0,0 +1,292 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +from mediagoblin.db.models import MediaEntry, User +from mediagoblin.plugins.archivalook.models import FeaturedMedia +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.plugins.archivalook.models import FeaturedMedia + +def get_media_entry_from_uploader_slug(uploader_username, slug): + """ + Accepts two strings and searches to see if those strings identify a + MediaEntry + + :param uploader_username A string representing the User.username + of the user who uploaded a piece of + media. + :param slug A string representing the slug of a + piece of media + + :returns media A MediaEntry object or None if no entry + matches the specifications. + """ + uploader = User.query.filter( + User.username == uploader_username).first() + media = MediaEntry.query.filter( + MediaEntry.get_uploader == uploader ).filter( + MediaEntry.slug == slug).first() + return media + + +def parse_url(url): + """ + A simple helper function that extracts the uploader and slug from a full url + + :param url A string containing the url for a piece + of media. This should be in the format + of "/u/{user}/m/{media}/" + + :returns (uploader_username, slug) Uploader_username is a unicode string + representing the username of the user + who uploaded the piece of media, slug is + the media entry's url slug. + """ + url = unicode(url) + u_end, m_start, m_end, end = (url.find('/u/') + 3, + url.find('/m/'), + url.find('/m/') + 3, + url.rfind('/')) + + uploader_username = url[u_end:m_start].strip() + slug = url[m_end:end].strip() + + return uploader_username, slug + + +def split_featured_media_list(featured_media): + """ + This script is part of processing post request on the /mod/feature-media/ + page. Post requests on these pages will only include the textbox, so this + script accepts the textbox's contents as its parameter. + + :parameter featured_media A string from a submitted + textarea within the post request + on /mod/feature-media/ + + :returns all_featured_media A dictionary of the format + MediaEntry : 'string' + where MediaEntry is a featured + piece of media and 'string' is + a string representation of its + display type (primary, secondary + or tertiary) + """ + + featured_media = unicode(featured_media) + featured_media_list = featured_media.split("\n") + display_type = 0 + media_already_featured = [] + all_featured_media = [] + for line in featured_media_list: + if line == '' or line.isspace(): continue + elif line.startswith(u'-'): + display_type += 1 + elif display_type <= 0 or display_type > 3: continue + else: + uploader, slug = parse_url(line) + media = get_media_entry_from_uploader_slug(uploader, slug) + # Make sure the media entry referenced exists, and has not already + # been featured higher up the list + if media == None or media in media_already_featured: continue + media_already_featured.append(media) + all_featured_media.append((media, + [None, + u'primary', + u'secondary', + u'tertiary'][display_type])) + + return all_featured_media + + +def create_featured_media_textbox(): + """ + This script searches through the database of which media is featured and + returns a string of each entry in the proper format for use in the + /mod/feature-media/ page. This string will be used as the default text in + the textbox on that page. + """ + + primaries = FeaturedMedia.query.order_by( + FeaturedMedia.order.asc()).filter( + FeaturedMedia.display_type == u'primary').all() + secondaries = FeaturedMedia.query.order_by( + FeaturedMedia.order.asc()).filter( + FeaturedMedia.display_type == u'secondary').all() + tertiaries = FeaturedMedia.query.order_by( + FeaturedMedia.order.asc()).filter( + FeaturedMedia.display_type == u'tertiary').all() + output_text = u'' + for display_type, feature_list in [ + (_(u'Primary'),primaries), + (_(u'Secondary'),secondaries), + (_(u'Tertiary'),tertiaries)]: + output_text += _( + u"""-----------{display_type}-Features--------------------------- +""").format(display_type=display_type) + for feature in feature_list: + media_entry = feature.media_entry + output_text += u'/u/{uploader_username}/m/{media_slug}/\n'.format( + uploader_username = media_entry.get_uploader.username, + media_slug = media_entry.slug) + + + return output_text + +def automatically_add_new_feature(media_entry): + """ + This function automates the addition of a new feature. New features will be + placed at the top of the feature stack as 'primary' features. All of the + current features are demoted one step to make room. + + :param media_entry :type mediagoblin.db.MediaEntry + The media entry that will been + featured which this function + targets + """ + # Set variables to determine which media entries should be pushed down to + # maintain the correct number of primary & secondary featured media. At this + # point the program assumes that there should be 1 primary feature and 2 + # secondary features, but in the future this should be a variable editable + # by the site admin. + too_many_primaries = FeaturedMedia.query.filter( + FeaturedMedia.display_type==u'primary').count() >= 1 + too_many_secondaries = FeaturedMedia.query.filter( + FeaturedMedia.display_type==u'secondary').count() >= 2 + featured_first_to_last = FeaturedMedia.query.order_by( + FeaturedMedia.order.asc()).all() + + for feature in featured_first_to_last: + # Some features have the option to demote or promote themselves to a + # different display_type, based on their position. But all features move + # up and down one step in the stack. + if (feature.is_last_of_type() and feature.display_type == u'primary' + and too_many_primaries): + feature.demote() + too_many_primaries = False + elif (feature.is_last_of_type() and feature.display_type == u'secondary' + and too_many_secondaries): + feature.demote() + too_many_secondaries = False + feature.move_down() + feature.save() + + # Create the new feature at the top of the stack. + new_feature = FeaturedMedia( + media_entry=media_entry, + display_type=u"primary", + order=0) + new_feature.save() + return new_feature + +def automatically_remove_feature(media_entry): + """ + This function automates the removal of a feature. All of the features below + them are promoted one step to close the gap. + + :param media_entry :type mediagoblin.db.MediaEntry + The media entry that will been + removed which this function + targets + """ + # Get the feature which will be deleted + target_feature = FeaturedMedia.query.filter( + FeaturedMedia.media_entry_id == media_entry.id).first() + # Find out which continuing features will have to be adjusted + featured_last_to_first = FeaturedMedia.query.filter( + FeaturedMedia.order>target_feature.order).order_by( + FeaturedMedia.order.desc()).all() + + for feature in featured_last_to_first: + # Maintain the current arrangement of primary/secondary/tertiary + # features by moving all the features below the deleted one up on slot + # and promoting any features in the proper position. + if feature.is_first_of_type(): + feature.promote() + feature.move_up() + feature.save() + + # Delete the feature, now that it's space has been closed + target_feature.delete() + +def promote_feature(media_entry): + """ + This function takes a current feature and moves it up the stack so that it + will be displayed higher up. It swaps the place of the selected feature for + the one above it, or if relevant raises the display_type of the feature up + one rung (ie. from 'tertiary' to 'secondary') + + :param media_entry :type mediagoblin.db.MediaEntry + The media entry that has been + featured which this function + targets + """ + # Get the FeaturedMedia object + target_feature = FeaturedMedia.query.filter( + FeaturedMedia.media_entry_id == media_entry.id).first() + # Get the first Feature with a lower order than the target + above_feature = FeaturedMedia.query.filter( + FeaturedMedia.order < target_feature.order).order_by( + FeaturedMedia.order.desc()).first() + # If the feature is not the uppermost one + if above_feature is not None: + # Swap the positions of the target feature with the one before it + (target_feature.order, + above_feature.order) = above_feature.order, target_feature.order + (target_feature.display_type, + above_feature.display_type) = (above_feature.display_type, + target_feature.display_type) + above_feature.save() + # Change the feature's display type to a more prominent one + elif target_feature.display_type == u'secondary': + target_feature.display_type = u'primary' + elif target_feature.display_type == u'tertiary': + target_feature.display_type = u'secondary' + target_feature.save() + +def demote_feature(media_entry): + """ + This function takes a current feature and moves it down the stack so that it + will be displayed lower down. It swaps the place of the selected feature for + the one below it, or if relevant lowers the display_type of the feature down + one rung (ie. from 'secondary' to 'tertiary') + + :param media_entry :type mediagoblin.db.MediaEntry + The media entry that has been + featured which this function + targets + """ + # Get the FeaturedMedia object + target_feature = FeaturedMedia.query.filter( + FeaturedMedia.media_entry_id == media_entry.id).first() + # Get the first Feature with a higher order than the target + below_feature = FeaturedMedia.query.filter( + FeaturedMedia.order > target_feature.order).order_by( + FeaturedMedia.order.asc()).first() + # If the feature is not the lowest one + if below_feature != None: + # Swap the positions of the target feature with the one after it + (target_feature.order, + below_feature.order) = below_feature.order, target_feature.order + (target_feature.display_type, + below_feature.display_type) = (below_feature.display_type, + target_feature.display_type) + below_feature.save() + # Change the feature's display type to a less prominent one + elif target_feature.display_type == u'secondary': + target_feature.display_type = u'tertiary' + elif target_feature.display_type == u'primary': + target_feature.display_type = u'secondary' + target_feature.save() + |