Ejemplo n.º 1
0
def convert_to_solr_document(sound):
    document = {}

    # Basic sound fields
    keep_fields = ['username', 'created', 'is_explicit', 'avg_rating', 'is_remix', 'num_ratings', 'channels', 'md5',
                   'was_remixed', 'original_filename', 'duration', 'type', 'id', 'num_downloads', 'filesize']
    for key in keep_fields:
        document[key] = getattr(sound, key)
    document["original_filename"] = remove_control_chars(getattr(sound, "original_filename"))
    document["description"] = remove_control_chars(getattr(sound, "description"))
    document["tag"] = getattr(sound, "tag_array")
    document["license"] = getattr(sound, "license_name")

    if getattr(sound, "pack_id"):
        document["pack"] = remove_control_chars(getattr(sound, "pack_name"))
        document["grouping_pack"] = str(getattr(sound, "pack_id")) + "_" + remove_control_chars(getattr(sound, "pack_name"))
    else:
        document["grouping_pack"] = str(getattr(sound, "id"))

    document["is_geotagged"] = False
    if getattr(sound, "geotag_id"):
        document["is_geotagged"] = True
        if not math.isnan(getattr(sound, "geotag_lon")) and not math.isnan(getattr(sound, "geotag_lat")):
            document["geotag"] = str(getattr(sound, "geotag_lon")) + " " + str(getattr(sound, "geotag_lat"))

    document["bitdepth"] = getattr(sound, "bitdepth") if getattr(sound, "bitdepth") else 0
    document["bitrate"] = getattr(sound, "bitrate") if getattr(sound, "bitrate") else 0
    document["samplerate"] = int(getattr(sound, "samplerate")) if getattr(sound, "samplerate") else 0

    document["comment"] = [remove_control_chars(comment_text) for comment_text in getattr(sound, "comments_array")]
    document["comments"] = getattr(sound, "num_comments")
    locations = sound.locations()
    document["waveform_path_m"] = locations["display"]["wave"]["M"]["path"]
    document["waveform_path_l"] = locations["display"]["wave"]["L"]["path"]
    document["spectral_path_m"] = locations["display"]["spectral"]["M"]["path"]
    document["spectral_path_l"] = locations["display"]["spectral"]["L"]["path"]
    document["preview_path"] = locations["preview"]["LQ"]["mp3"]["path"]

    # Audio Commons analysis
    # NOTE: as the sound object here is the one returned by SoundManager.bulk_query_solr, it will have the Audio Commons
    # descriptor fields under a property called 'ac_analysis'.
    ac_analysis = getattr(sound, "ac_analysis")
    if ac_analysis is not None:
        # If analysis is present, index all existing analysis fields under SOLR's dynamic fields "*_i", "*_d", "*_s"
        # and "*_b" depending on the value's type. Also add Audio Commons prefix.
        for key, value in ac_analysis.items():
            suffix = settings.SOLR_DYNAMIC_FIELDS_SUFFIX_MAP.get(type(value), None)
            if suffix:
                document['{0}{1}{2}'.format(settings.AUDIOCOMMONS_DESCRIPTOR_PREFIX, key, suffix)] = value

    return document
Ejemplo n.º 2
0
def convert_to_solr_document(sound):
    document = {}
    keep_fields = [
        'username', 'created', 'is_explicit', 'avg_rating', 'is_remix',
        'num_ratings', 'channels', 'md5', 'was_remixed', 'original_filename',
        'duration', 'type', 'id', 'num_downloads', 'filesize'
    ]
    for key in keep_fields:
        document[key] = getattr(sound, key)
    document["original_filename"] = remove_control_chars(
        getattr(sound, "original_filename"))
    document["description"] = remove_control_chars(
        getattr(sound, "description"))
    document["tag"] = getattr(sound, "tag_array")
    document["license"] = getattr(sound, "license_name")

    if getattr(sound, "pack_id"):
        document["pack"] = remove_control_chars(getattr(sound, "pack_name"))
        document["grouping_pack"] = str(getattr(
            sound, "pack_id")) + "_" + remove_control_chars(
                getattr(sound, "pack_name"))
    else:
        document["grouping_pack"] = str(getattr(sound, "id"))

    document["is_geotagged"] = False
    if getattr(sound, "geotag_id"):
        document["is_geotagged"] = True
        if not math.isnan(getattr(sound, "geotag_lon")) and not math.isnan(
                getattr(sound, "geotag_lat")):
            document["geotag"] = str(getattr(sound, "geotag_lon")) + " " + str(
                getattr(sound, "geotag_lat"))

    document["bitdepth"] = getattr(sound, "bitdepth") if getattr(
        sound, "bitdepth") else 0
    document["bitrate"] = getattr(sound, "bitrate") if getattr(
        sound, "bitrate") else 0
    document["samplerate"] = int(getattr(sound, "samplerate")) if getattr(
        sound, "samplerate") else 0

    document["comment"] = [
        remove_control_chars(comment_text)
        for comment_text in getattr(sound, "comments_array")
    ]
    document["comments"] = getattr(sound, "num_comments")
    locations = sound.locations()
    document["waveform_path_m"] = locations["display"]["wave"]["M"]["path"]
    document["waveform_path_l"] = locations["display"]["wave"]["L"]["path"]
    document["spectral_path_m"] = locations["display"]["spectral"]["M"]["path"]
    document["spectral_path_l"] = locations["display"]["spectral"]["L"]["path"]
    document["preview_path"] = locations["preview"]["LQ"]["mp3"]["path"]
    return document
Ejemplo n.º 3
0
def convert_to_solr_document(post):
    document = {
        "id": post.id,
        "thread_id": post.thread.id,
        "thread_title": remove_control_chars(post.thread.title),
        "thread_author": post.thread.author,
        "thread_created": post.thread.created,
        "forum_name": post.thread.forum.name,
        "forum_name_slug": post.thread.forum.name_slug,
        "post_author": post.author,
        "post_created": post.created,
        "post_body": remove_control_chars(post.body),
        "num_posts": post.thread.num_posts,
        "has_posts": False if post.thread.num_posts == 0 else True
    }

    return document
Ejemplo n.º 4
0
def convert_to_solr_document(sound):
    #logger.info("creating solr XML from sound %d" % sound.id)
    document = dict()
    document["id"] = sound.id
    document["username"] = sound.user.username
    document["created"] = sound.created
    document["original_filename"] = remove_control_chars(sound.original_filename)
    document["description"] = remove_control_chars(sound.description)
    document["tag"] = list(sound.tags.select_related("tag").values_list('tag__name', flat=True))
    document["license"] = sound.license.name
    document["is_remix"] = bool(sound.sources.count())
    document["was_remixed"] = bool(sound.remixes.count())
    if sound.pack:
        document["pack"] = remove_control_chars(sound.pack.name)
        document["grouping_pack"] = str(sound.pack.id) + "_" + remove_control_chars(sound.pack.name)
    else:
        document["grouping_pack"] = str(sound.id)
    document["is_geotagged"] = sound.geotag_id is not None
    if sound.geotag_id is not None:
        if not math.isnan(sound.geotag.lon) and not math.isnan(sound.geotag.lat):
            document["geotag"] = str(sound.geotag.lon) + " " + str(sound.geotag.lat)
    document["type"] = sound.type
    document["duration"] = sound.duration
    document["bitdepth"] = sound.bitdepth if sound.bitdepth != None else 0
    document["bitrate"] = sound.bitrate if sound.bitrate != None else 0
    document["samplerate"] = int(sound.samplerate)
    document["filesize"] = sound.filesize
    document["channels"] = sound.channels
    document["md5"] = sound.md5
    document["num_downloads"] = sound.num_downloads
    document["avg_rating"] = sound.avg_rating
    document["num_ratings"] = sound.num_ratings
    document["comment"] = [remove_control_chars(comment_text) for comment_text in
                           sound.comments.values_list('comment', flat=True)]
    document["comments"] = sound.num_comments
    document["waveform_path_m"] = sound.locations()["display"]["wave"]["M"]["path"]
    document["waveform_path_l"] = sound.locations()["display"]["wave"]["L"]["path"]
    document["spectral_path_m"] = sound.locations()["display"]["spectral"]["M"]["path"]
    document["spectral_path_l"] = sound.locations()["display"]["spectral"]["L"]["path"]
    document["preview_path"] = sound.locations()["preview"]["LQ"]["mp3"]["path"]
    return document
Ejemplo n.º 5
0
def post_edit(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    if post.author == request.user or request.user.has_perm(
            'forum.change_post'):
        if request.method == 'POST':
            form = PostReplyForm(request, '', request.POST)
            if form.is_valid():
                post.body = remove_control_chars(form.cleaned_data['body'])
                post.save()
                add_post_to_solr(post.id)  # Update post in solr
                return HttpResponseRedirect(
                    reverse('forums-post',
                            args=[
                                post.thread.forum.name_slug, post.thread.id,
                                post.id
                            ]))
        else:
            form = PostReplyForm(request, '', {'body': post.body})
        tvars = {'form': form}
        return render(request, 'forum/post_edit.html', tvars)
    else:
        raise Http404
Ejemplo n.º 6
0
def sound_edit(request, username, sound_id):
    sound = get_object_or_404(Sound, id=sound_id, processing_state='OK')
    if sound.user.username.lower() != username.lower():
        raise Http404

    if not (request.user.has_perm('sound.can_change')
            or sound.user == request.user):
        raise PermissionDenied

    def is_selected(prefix):
        if request.method == "POST":
            for name in request.POST.keys():
                if name.startswith(prefix + '-'):
                    return True
        return False

    def update_sound_tickets(sound, text):
        tickets = Ticket.objects.filter(sound_id=sound.id)\
                               .exclude(status=TICKET_STATUS_CLOSED)
        for ticket in tickets:
            tc = TicketComment(sender=request.user,
                               ticket=ticket,
                               moderator_only=False,
                               text=text)
            tc.save()
            ticket.send_notification_emails(ticket.NOTIFICATION_UPDATED,
                                            ticket.MODERATOR_ONLY)

    if is_selected("description"):
        description_form = SoundDescriptionForm(
            request.POST,
            prefix="description",
            explicit_disable=sound.is_explicit)

        if description_form.is_valid():
            data = description_form.cleaned_data
            sound.is_explicit = data["is_explicit"]
            sound.set_tags(data["tags"])
            sound.description = remove_control_chars(data["description"])
            sound.original_filename = data["name"]
            sound.mark_index_dirty()
            sound.invalidate_template_caches()
            update_sound_tickets(
                sound, '%s updated the sound description and/or tags.' %
                request.user.username)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        tags = " ".join([
            tagged_item.tag.name
            for tagged_item in sound.tags.all().order_by('tag__name')
        ])
        description_form = SoundDescriptionForm(
            prefix="description",
            explicit_disable=sound.is_explicit,
            initial=dict(tags=tags,
                         description=sound.description,
                         name=sound.original_filename))

    packs = Pack.objects.filter(user=request.user).exclude(is_deleted=True)
    if is_selected("pack"):
        pack_form = PackForm(packs, request.POST, prefix="pack")
        if pack_form.is_valid():
            data = pack_form.cleaned_data
            affected_packs = []
            if data['new_pack']:
                (pack,
                 created) = Pack.objects.get_or_create(user=sound.user,
                                                       name=data['new_pack'])
                if sound.pack:
                    affected_packs.append(
                        sound.pack)  # Append previous sound pack if exists
                sound.pack = pack
                affected_packs.append(pack)
            else:
                new_pack = data["pack"]
                old_pack = sound.pack
                if new_pack != old_pack:
                    sound.pack = new_pack
                    if new_pack:
                        affected_packs.append(new_pack)
                    if old_pack:
                        affected_packs.append(old_pack)

            sound.mark_index_dirty()  # Marks as dirty and saves
            sound.invalidate_template_caches()
            update_sound_tickets(
                sound, '%s updated the sound pack.' % request.user.username)
            for affected_pack in affected_packs:  # Process affected packs
                affected_pack.process()

            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        pack_form = PackForm(
            packs,
            prefix="pack",
            initial=dict(pack=sound.pack.id) if sound.pack else None)

    if is_selected("geotag"):
        geotag_form = GeotaggingForm(request.POST, prefix="geotag")
        if geotag_form.is_valid():
            data = geotag_form.cleaned_data
            if data["remove_geotag"]:
                if sound.geotag:
                    sound.geotag.delete()
                    sound.geotag = None
                    sound.mark_index_dirty()
            else:
                if sound.geotag:
                    sound.geotag.lat = data["lat"]
                    sound.geotag.lon = data["lon"]
                    sound.geotag.zoom = data["zoom"]
                    sound.geotag.save()
                else:
                    sound.geotag = GeoTag.objects.create(lat=data["lat"],
                                                         lon=data["lon"],
                                                         zoom=data["zoom"],
                                                         user=request.user)
                    sound.mark_index_dirty()

            sound.mark_index_dirty()
            sound.invalidate_template_caches()
            update_sound_tickets(
                sound, '%s updated the sound geotag.' % request.user.username)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        if sound.geotag:
            geotag_form = GeotaggingForm(prefix="geotag",
                                         initial=dict(lat=sound.geotag.lat,
                                                      lon=sound.geotag.lon,
                                                      zoom=sound.geotag.zoom))
        else:
            geotag_form = GeotaggingForm(prefix="geotag")

    license_form = NewLicenseForm(request.POST)
    if request.POST and license_form.is_valid():
        new_license = license_form.cleaned_data["license"]
        if new_license != sound.license:
            sound.set_license(new_license)
        sound.mark_index_dirty()  # Sound is saved here
        if sound.pack:
            sound.pack.process(
            )  # Sound license changed, process pack (if sound has pack)
        sound.invalidate_template_caches()
        update_sound_tickets(
            sound, '%s updated the sound license.' % request.user.username)
        return HttpResponseRedirect(sound.get_absolute_url())
    else:
        license_form = NewLicenseForm(initial={'license': sound.license})

    tvars = {
        'sound': sound,
        'description_form': description_form,
        'pack_form': pack_form,
        'geotag_form': geotag_form,
        'license_form': license_form
    }
    return render(request, 'sounds/sound_edit.html', tvars)
Ejemplo n.º 7
0
def describe_sounds(request):
    forms = []
    sounds_to_process = []
    sounds = request.session.get('describe_sounds', False)
    if not sounds:
        msg = 'Please pick at least one sound.'
        messages.add_message(request, messages.WARNING, msg)
        return HttpResponseRedirect(reverse('accounts-describe'))
    sounds_to_describe = sounds[0:settings.SOUNDS_PER_DESCRIBE_ROUND]
    request.session['describe_sounds_number'] = len(request.session.get('describe_sounds'))
    selected_license = request.session.get('describe_license', False)
    selected_pack = request.session.get('describe_pack', False)

    # If there are no files in the session redirect to the first describe page
    if len(sounds_to_describe) <= 0:
        msg = 'You have finished describing your sounds.'
        messages.add_message(request, messages.WARNING, msg)
        return HttpResponseRedirect(reverse('accounts-describe'))

    tvars = {
        'sounds_per_round': settings.SOUNDS_PER_DESCRIBE_ROUND,
        'forms': forms,
    }

    if request.method == 'POST':
        # First get all the data
        n_sounds_already_part_of_freesound = 0
        for i in range(len(sounds_to_describe)):
            prefix = str(i)
            forms.append({})
            forms[i]['sound'] = sounds_to_describe[i]
            forms[i]['description'] = SoundDescriptionForm(request.POST, prefix=prefix)
            forms[i]['geotag'] = GeotaggingForm(request.POST, prefix=prefix)
            forms[i]['pack'] = PackForm(Pack.objects.filter(user=request.user),
                                        request.POST,
                                        prefix=prefix)
            forms[i]['license'] = NewLicenseForm(request.POST, prefix=prefix)
        # Validate each form
        for i in range(len(sounds_to_describe)):
            for f in ['license', 'geotag', 'pack', 'description']:
                if not forms[i][f].is_valid():
                    # If at least one form is not valid, render template with form errors
                    return render(request, 'accounts/describe_sounds.html', tvars)

        # All valid, then create sounds and moderation tickets
        dirty_packs = []
        for i in range(len(sounds_to_describe)):
            # Create sound object and set basic properties
            sound = Sound()
            sound.user = request.user
            sound.original_filename = forms[i]['description'].cleaned_data['name']
            sound.original_path = forms[i]['sound'].full_path
            try:
                sound.filesize = os.path.getsize(sound.original_path)
            except OSError:
                # If for some reason audio file does not exist, skip creating this sound
                messages.add_message(request, messages.ERROR,
                                     'Something went wrong with accessing the file %s.' % sound.original_path)
                continue
            sound.md5 = md5file(forms[i]['sound'].full_path)
            sound.type = get_sound_type(sound.original_path)
            sound.license = forms[i]['license'].cleaned_data['license']
            try:
                # Check if another file with same md5 already exists, if it does, delete the sound and post a message
                existing_sound = Sound.objects.get(md5=sound.md5)
                n_sounds_already_part_of_freesound += 1
                msg = 'The file %s is already part of freesound and has been discarded, see <a href="%s">here</a>' % \
                    (forms[i]['sound'].name, reverse('sound', args=[existing_sound.user.username, existing_sound.id]))
                messages.add_message(request, messages.WARNING, msg)
                os.remove(forms[i]['sound'].full_path)
                continue
            except Sound.DoesNotExist:
                # Reaching here means that no other sound already exists with the same md5
                pass
            sound.save()

            # Move the original audio file
            orig = os.path.splitext(os.path.basename(sound.original_filename))[0]
            sound.base_filename_slug = "%d__%s__%s" % (sound.id, slugify(sound.user.username), slugify(orig))
            new_original_path = sound.locations("path")
            if sound.original_path != new_original_path:
                try:
                    os.makedirs(os.path.dirname(new_original_path))
                except OSError:
                    pass
                try:
                    shutil.move(sound.original_path, new_original_path)
                except IOError, e:
                    logger.info("Failed to move file from %s to %s" % (sound.original_path, new_original_path), e)
                logger.info("Moved original file from %s to %s" % (sound.original_path, new_original_path))
                sound.original_path = new_original_path
                sound.save()

            # Set pack (optional)
            pack = forms[i]['pack'].cleaned_data.get('pack', False)
            new_pack = forms[i]['pack'].cleaned_data.get('new_pack', False)
            if not pack and new_pack:
                pack, created = Pack.objects.get_or_create(user=request.user, name=new_pack)
            if pack:
                sound.pack = pack
                dirty_packs.append(sound.pack)

            # Set geotag
            data = forms[i]['geotag'].cleaned_data
            if not data.get('remove_geotag') and data.get('lat'):  # if 'lat' is in data, we assume other fields are too
                geotag = GeoTag(user=request.user,
                                lat=data.get('lat'),
                                lon=data.get('lon'),
                                zoom=data.get('zoom'))
                geotag.save()
                sound.geotag = geotag

            # Set the tags and description
            data = forms[i]['description'].cleaned_data
            sound.description = remove_control_chars(data.get('description', ''))
            sound.set_tags(data.get('tags'))
            sound.save()

            # Remember to process the file and create moderation ticket if user is not whitelisted
            sounds_to_process.append(sound)
            if request.user.profile.is_whitelisted:
                sound.change_moderation_state('OK', do_not_update_related_stuff=True)
                messages.add_message(request, messages.INFO,
                                     'File <a href="%s">%s</a> has been described and has been added to freesound.' % \
                                     (sound.get_absolute_url(), forms[i]['sound'].name))
            else:
                sound.create_moderation_ticket()
                messages.add_message(request, messages.INFO,
                                     'File <a href="%s">%s</a> has been described and is now awaiting processing '
                                     'and moderation.' % (sound.get_absolute_url(), forms[i]['sound'].name))

                # Invalidate affected caches in user header
                invalidate_template_cache("user_header", request.user.id)
                for moderator in Group.objects.get(name='moderators').user_set.all():
                    invalidate_template_cache("user_header", moderator.id)

            # Compute sound crc
            try:
                sound.compute_crc()
            except:
                pass

        # Remove the files we just described from the session and redirect to this page
        request.session['describe_sounds'] = request.session['describe_sounds'][len(sounds_to_describe):]

        # Process sounds and packs
        # N.B. we do this at the end to avoid conflicts between django-web and django-workers
        # If we're not careful django's save() functions will overwrite any processing we
        # do on the workers.
        # In the future if django-workers do not write to the db this might be changed
        try:
            for s in sounds_to_process:
                s.process()
        except Exception as e:
            audio_logger.error('Sound with id %s could not be scheduled. (%s)' % (s.id, str(e)))
        for p in dirty_packs:
            p.process()

        # Check if all sounds have been described after that round and redirect accordingly
        if len(request.session['describe_sounds']) <= 0:
            if len(sounds_to_describe) != n_sounds_already_part_of_freesound:
                msg = 'You have described all the selected files and are now awaiting processing and moderation. ' \
                      'You can check the status of your uploaded sounds in your <a href="%s">home page</a>. ' \
                      'Once your sounds have been processed, you can also get information about the moderation ' \
                      'status in the <a href="%s">uploaded sounds awaiting moderation' \
                      '</a> page.' % (reverse('accounts-home'), reverse('accounts-pending'))
                messages.add_message(request, messages.WARNING, msg)
            return HttpResponseRedirect(reverse('accounts-describe'))
        else:
            return HttpResponseRedirect(reverse('accounts-describe-sounds'))
Ejemplo n.º 8
0
def sound_edit(request, username, sound_id):
    ONLY_RECOMMEND_TAGS_TO_HALF_OF_UPLOADS = settings.ONLY_RECOMMEND_TAGS_TO_HALF_OF_UPLOADS

    sound = get_object_or_404(Sound, id=sound_id, processing_state='OK')
    if sound.user.username.lower() != username.lower():
        raise Http404

    if not (request.user.has_perm('sound.can_change') or sound.user == request.user):
        raise PermissionDenied

    def invalidate_sound_cache(sound):
        invalidate_template_cache("sound_header", sound.id, True)
        invalidate_template_cache("sound_header", sound.id, False)
        invalidate_template_cache("sound_footer_top", sound.id)
        invalidate_template_cache("sound_footer_bottom", sound.id)
        invalidate_template_cache("display_sound", sound.id, True, sound.processing_state, sound.moderation_state)
        invalidate_template_cache("display_sound", sound.id, False, sound.processing_state, sound.moderation_state)

    def is_selected(prefix):
        if request.method == "POST":
            for name in request.POST.keys():
                if name.startswith(prefix + '-'):
                    return True
        return False

    if is_selected("description"):
        description_form = SoundDescriptionForm(request.POST, prefix="description")
        if description_form.is_valid():
            data = description_form.cleaned_data
            sound.set_tags(data["tags"])
            sound.description = remove_control_chars(data["description"])
            sound.original_filename = data["name"]
            sound.mark_index_dirty()
            invalidate_sound_cache(sound)

            # also update any possible related sound ticket
            tickets = Ticket.objects.filter(content__object_id=sound.id,
                                            source=TICKET_SOURCE_NEW_SOUND) \
                                   .exclude(status=TICKET_STATUS_CLOSED)
            for ticket in tickets:
                tc = TicketComment(sender=request.user,
                                   ticket=ticket,
                                   moderator_only=False,
                                   text='%s updated the sound description and/or tags.' % request.user.username)
                tc.save()
                ticket.send_notification_emails(ticket.NOTIFICATION_UPDATED,
                                                ticket.MODERATOR_ONLY)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        tags = " ".join([tagged_item.tag.name for tagged_item in sound.tags.all().order_by('tag__name')])
        description_form = SoundDescriptionForm(prefix="description",
                                                initial=dict(tags=tags,
                                                             description=sound.description,
                                                             name=sound.original_filename))

    packs = Pack.objects.filter(user=request.user)

    if is_selected("pack"):
        pack_form = PackForm(packs, request.POST, prefix="pack")
        if pack_form.is_valid():
            data = pack_form.cleaned_data
            dirty_packs = []
            if data['new_pack']:
                (pack, created) = Pack.objects.get_or_create(user=sound.user, name=data['new_pack'])
                sound.pack = pack
            else:
                new_pack = data["pack"]
                old_pack = sound.pack
                if new_pack != old_pack:
                    sound.pack = new_pack
                if new_pack:
                    dirty_packs.append(new_pack)
                if old_pack:
                    dirty_packs.append(old_pack)

            for p in dirty_packs:
               p.process()

            sound.mark_index_dirty()
            invalidate_sound_cache(sound)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        pack_form = PackForm(packs, prefix="pack", initial=dict(pack=sound.pack.id) if sound.pack else None)

    if is_selected("geotag"):
        geotag_form = GeotaggingForm(request.POST, prefix="geotag")

        if geotag_form.is_valid():
            data = geotag_form.cleaned_data

            if data["remove_geotag"]:
                if sound.geotag:
                    geotag = sound.geotag.delete()
                    sound.geotag = None
                    sound.mark_index_dirty()
            else:
                if sound.geotag:
                    sound.geotag.lat = data["lat"]
                    sound.geotag.lon = data["lon"]
                    sound.geotag.zoom = data["zoom"]
                    sound.geotag.save()
                else:
                    sound.geotag = GeoTag.objects.create(lat=data["lat"], lon=data["lon"], zoom=data["zoom"], user=request.user)
                    sound.mark_index_dirty()

            invalidate_sound_cache(sound)

            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        if sound.geotag:
            geotag_form = GeotaggingForm(prefix="geotag", initial=dict(lat=sound.geotag.lat, lon=sound.geotag.lon, zoom=sound.geotag.zoom))
        else:
            geotag_form = GeotaggingForm(prefix="geotag")

    license_form = NewLicenseForm(request.POST)
    if request.POST and license_form.is_valid():
        sound.license = license_form.cleaned_data["license"]
        sound.mark_index_dirty()
        invalidate_sound_cache(sound)
        return HttpResponseRedirect(sound.get_absolute_url())
    else:
        license_form = NewLicenseForm(initial={'license': sound.license})

    google_api_key = settings.GOOGLE_API_KEY

    return render_to_response('sounds/sound_edit.html', locals(), context_instance=RequestContext(request))
Ejemplo n.º 9
0
def new_thread(request, forum_name_slug):
    forum = get_object_or_404(Forum, name_slug=forum_name_slug)
    user_can_post_in_forum, user_can_post_message = request.user.profile.can_post_in_forum(
    )
    user_is_blocked_for_spam_reports = request.user.profile.is_blocked_for_spam_reports(
    )

    if request.method == 'POST':
        form = NewThreadForm(request.POST)
        if user_can_post_in_forum and not user_is_blocked_for_spam_reports:
            if form.is_valid():
                post_title = form.cleaned_data["title"]
                post_body = form.cleaned_data["body"]
                thread = Thread.objects.create(forum=forum,
                                               author=request.user,
                                               title=post_title)
                may_be_spam = text_may_be_spam(post_body) or \
                              text_may_be_spam(post_title)

                post_body = remove_control_chars(post_body)
                if not request.user.posts.filter(
                        moderation_state="OK").count() and may_be_spam:
                    post = Post.objects.create(author=request.user,
                                               body=post_body,
                                               thread=thread,
                                               moderation_state="NM")
                    # DO NOT add the post to solr, only do it when it is moderated
                    set_to_moderation = True
                else:
                    post = Post.objects.create(author=request.user,
                                               body=post_body,
                                               thread=thread)
                    add_post_to_solr(post.id)
                    set_to_moderation = False

                # Add first post to thread (first post will always be the same)
                # We need to reload thread object from DB, not so overwrite the object we created before when saving
                # TODO: Ideally we would have a specific function to create a Post and add it to a thread immediately
                #       so that we can use this functionality in tests too
                updated_thread = Thread.objects.get(id=thread.id)
                updated_thread.first_post = post
                updated_thread.save()

                if form.cleaned_data["subscribe"]:
                    Subscription.objects.create(subscriber=request.user,
                                                thread=thread,
                                                is_active=True)

                if not set_to_moderation:
                    return HttpResponseRedirect(post.get_absolute_url())
                else:
                    messages.add_message(
                        request, messages.INFO,
                        "Your post won't be shown until it is manually "
                        "approved by moderators")
                    return HttpResponseRedirect(
                        post.thread.forum.get_absolute_url())
    else:
        form = NewThreadForm()

    if not user_can_post_in_forum:
        messages.add_message(request, messages.INFO, user_can_post_message)

    if user_is_blocked_for_spam_reports:
        messages.add_message(
            request, messages.INFO,
            "You're not allowed to post in the forums because your account "
            "has been temporaly blocked after multiple spam reports")

    tvars = {'forum': forum, 'form': form}
    return render(request, 'forum/new_thread.html', tvars)
Ejemplo n.º 10
0
def sound_edit(request, username, sound_id):
    sound = get_object_or_404(Sound, id=sound_id, processing_state="OK")
    if sound.user.username.lower() != username.lower():
        raise Http404

    if not (request.user.has_perm("sound.can_change") or sound.user == request.user):
        raise PermissionDenied

    def is_selected(prefix):
        if request.method == "POST":
            for name in request.POST.keys():
                if name.startswith(prefix + "-"):
                    return True
        return False

    def update_sound_tickets(sound, text):
        tickets = Ticket.objects.filter(content__object_id=sound.id, source=TICKET_SOURCE_NEW_SOUND).exclude(
            status=TICKET_STATUS_CLOSED
        )
        for ticket in tickets:
            tc = TicketComment(sender=request.user, ticket=ticket, moderator_only=False, text=text)
            tc.save()
            ticket.send_notification_emails(ticket.NOTIFICATION_UPDATED, ticket.MODERATOR_ONLY)

    if is_selected("description"):
        description_form = SoundDescriptionForm(request.POST, prefix="description")
        if description_form.is_valid():
            data = description_form.cleaned_data
            sound.set_tags(data["tags"])
            sound.description = remove_control_chars(data["description"])
            sound.original_filename = data["name"]
            sound.mark_index_dirty()
            sound.invalidate_template_caches()
            update_sound_tickets(sound, "%s updated the sound description and/or tags." % request.user.username)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        tags = " ".join([tagged_item.tag.name for tagged_item in sound.tags.all().order_by("tag__name")])
        description_form = SoundDescriptionForm(
            prefix="description", initial=dict(tags=tags, description=sound.description, name=sound.original_filename)
        )

    packs = Pack.objects.filter(user=request.user)
    if is_selected("pack"):
        pack_form = PackForm(packs, request.POST, prefix="pack")
        if pack_form.is_valid():
            data = pack_form.cleaned_data
            affected_packs = []
            if data["new_pack"]:
                (pack, created) = Pack.objects.get_or_create(user=sound.user, name=data["new_pack"])
                if sound.pack:
                    affected_packs.append(sound.pack)  # Append previous sound pack if exists
                sound.pack = pack
                affected_packs.append(pack)
            else:
                new_pack = data["pack"]
                old_pack = sound.pack
                if new_pack != old_pack:
                    sound.pack = new_pack
                    if new_pack:
                        affected_packs.append(new_pack)
                    if old_pack:
                        affected_packs.append(old_pack)

            sound.mark_index_dirty()  # Marks as dirty and saves
            sound.invalidate_template_caches()
            update_sound_tickets(sound, "%s updated the sound pack." % request.user.username)
            for affected_pack in affected_packs:  # Process affected packs
                affected_pack.process()

            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        pack_form = PackForm(packs, prefix="pack", initial=dict(pack=sound.pack.id) if sound.pack else None)

    if is_selected("geotag"):
        geotag_form = GeotaggingForm(request.POST, prefix="geotag")
        if geotag_form.is_valid():
            data = geotag_form.cleaned_data
            if data["remove_geotag"]:
                if sound.geotag:
                    sound.geotag.delete()
                    sound.geotag = None
                    sound.mark_index_dirty()
            else:
                if sound.geotag:
                    sound.geotag.lat = data["lat"]
                    sound.geotag.lon = data["lon"]
                    sound.geotag.zoom = data["zoom"]
                    sound.geotag.save()
                else:
                    sound.geotag = GeoTag.objects.create(
                        lat=data["lat"], lon=data["lon"], zoom=data["zoom"], user=request.user
                    )
                    sound.mark_index_dirty()

            sound.mark_index_dirty()
            sound.invalidate_template_caches()
            update_sound_tickets(sound, "%s updated the sound geotag." % request.user.username)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        if sound.geotag:
            geotag_form = GeotaggingForm(
                prefix="geotag", initial=dict(lat=sound.geotag.lat, lon=sound.geotag.lon, zoom=sound.geotag.zoom)
            )
        else:
            geotag_form = GeotaggingForm(prefix="geotag")

    license_form = NewLicenseForm(request.POST)
    if request.POST and license_form.is_valid():
        sound.license = license_form.cleaned_data["license"]
        sound.mark_index_dirty()
        if sound.pack:
            sound.pack.process()  # Sound license changed, process pack (is sound has pack)
        sound.invalidate_template_caches()
        update_sound_tickets(sound, "%s updated the sound license." % request.user.username)
        return HttpResponseRedirect(sound.get_absolute_url())
    else:
        license_form = NewLicenseForm(initial={"license": sound.license})

    tvars = {
        "sound": sound,
        "description_form": description_form,
        "pack_form": pack_form,
        "geotag_form": geotag_form,
        "license_form": license_form,
    }
    return render(request, "sounds/sound_edit.html", tvars)
Ejemplo n.º 11
0
def describe_sounds(request):
    sounds_to_process = []
    sounds = request.session.get('describe_sounds', False)
    selected_license = request.session.get('describe_license', False)
    selected_pack = request.session.get('describe_pack', False)

    # This is to prevent people browsing to the /home/describe/sounds page
    # without going through the necessary steps.
    # selected_pack can be False, but license and sounds have to be picked at least
    if not (sounds):
        msg = 'Please pick at least one sound.'
        messages.add_message(request, messages.WARNING, msg)
        return HttpResponseRedirect(reverse('accounts-describe'))

    # So SOUNDS_PER_DESCRIBE_ROUND is available in the template
    sounds_per_round = SOUNDS_PER_DESCRIBE_ROUND
    sounds_to_describe = sounds[0:sounds_per_round]
    forms = []
    request.session['describe_sounds_number'] = len(request.session.get('describe_sounds'))

    # If there are no files in the session redirect to the first describe page
    if len(sounds_to_describe) <= 0:
        msg = 'You have finished describing your sounds.'
        messages.add_message(request, messages.WARNING, msg)
        return HttpResponseRedirect(reverse('accounts-describe'))

    if request.method == 'POST':
        # first get all the data
        for i in range(len(sounds_to_describe)):
            prefix = str(i)
            forms.append({})
            forms[i]['sound'] = sounds_to_describe[i]
            forms[i]['description'] = SoundDescriptionForm(request.POST, prefix=prefix)
            forms[i]['geotag'] = GeotaggingForm(request.POST, prefix=prefix)
            forms[i]['pack'] = PackForm(Pack.objects.filter(user=request.user),
                                        request.POST,
                                        prefix=prefix)
            forms[i]['license'] = NewLicenseForm(request.POST, prefix=prefix)
        # validate each form
        for i in range(len(sounds_to_describe)):
            for f in ['license', 'geotag', 'pack', 'description']:
                if not forms[i][f].is_valid():
                    return render_to_response('accounts/describe_sounds.html',
                                              locals(),
                                              context_instance=RequestContext(request))
        # all valid, then create sounds and moderation tickets
                
        dirty_packs = []
        for i in range(len(sounds_to_describe)):
            sound = Sound()
            sound.user = request.user
            sound.original_filename = forms[i]['description'].cleaned_data['name']
            sound.original_path = forms[i]['sound'].full_path
            sound.filesize = os.path.getsize(sound.original_path)

            try:
                sound.md5 = md5file(forms[i]['sound'].full_path)
            except IOError:
                messages.add_message(request, messages.ERROR, 'Something went wrong with accessing the file %s.' % sound.original_path)
                continue
            sound.type = get_sound_type(sound.original_path)
            # check if file exists or not
            try:
                existing_sound = Sound.objects.get(md5=sound.md5)
                msg = 'The file %s is already part of freesound and has been discarded, see <a href="%s">here</a>' % \
                    (forms[i]['sound'].name, reverse('sound', args=[existing_sound.user.username, existing_sound.id]))
                messages.add_message(request, messages.WARNING, msg)
                os.remove(forms[i]['sound'].full_path)
                continue
            except Sound.DoesNotExist, e:
                pass

            # set the license
            sound.license = forms[i]['license'].cleaned_data['license']
            sound.save()
            # now move the original
            orig = os.path.splitext(os.path.basename(sound.original_filename))[0]
            sound.base_filename_slug = "%d__%s__%s" % (sound.id, slugify(sound.user.username), slugify(orig))
            new_original_path = sound.locations("path")
            if sound.original_path != new_original_path:
                try:
                    os.makedirs(os.path.dirname(new_original_path))
                except OSError:
                    pass
                try:
                    shutil.move(sound.original_path, new_original_path)
                    #shutil.copy(sound.original_path, new_original_path)
                except IOError, e:
                    logger.info("failed to move file from %s to %s" % (sound.original_path, new_original_path), e)
                logger.info("moved original file from %s to %s" % (sound.original_path, new_original_path))
                sound.original_path = new_original_path
                sound.save()

            # set the pack (optional)
            pack = forms[i]['pack'].cleaned_data.get('pack', False)
            new_pack = forms[i]['pack'].cleaned_data.get('new_pack', False)
            if not pack and new_pack:
                pack, created = Pack.objects.get_or_create(user=request.user, name=new_pack)
            if pack:
                sound.pack = pack
                dirty_packs.append(sound.pack)
            # set the geotag (if 'lat' is there, all fields are)
            data = forms[i]['geotag'].cleaned_data
            if not data.get('remove_geotag') and data.get('lat'):
                geotag = GeoTag(user=request.user,
                                lat=data.get('lat'),
                                lon=data.get('lon'),
                                zoom=data.get('zoom'))
                geotag.save()
                sound.geotag = geotag
            # set the tags and descriptions
            data = forms[i]['description'].cleaned_data
            sound.description = remove_control_chars(data.get('description', ''))
            sound.set_tags(data.get('tags'))
            sound.save()
            # remember to process the file
            sounds_to_process.append(sound)
            if request.user.profile.is_whitelisted:
                sound.moderation_state = 'OK'
                sound.save()
                messages.add_message(request, messages.INFO,
                                     'File <a href="%s">%s</a> has been described and has been added to freesound.' % \
                                     (sound.get_absolute_url(), forms[i]['sound'].name))
            else:
                # create moderation ticket!
                ticket = Ticket()
                ticket.title = 'Moderate sound %s' % sound.original_filename
                ticket.source = TICKET_SOURCE_NEW_SOUND
                ticket.status = TICKET_STATUS_NEW
                ticket.queue = Queue.objects.get(name='sound moderation')
                ticket.sender = request.user
                lc = LinkedContent()
                lc.content_object = sound
                lc.save()
                ticket.content = lc
                ticket.save()
                tc = TicketComment()
                tc.sender = request.user
                tc.text = "I've uploaded %s. Please moderate!" % sound.original_filename
                tc.ticket = ticket
                tc.save()
                # add notification that the file was described successfully
                messages.add_message(request, messages.INFO,
                                     'File <a href="%s">%s</a> has been described and is awaiting moderation.' % \
                                     (sound.get_absolute_url(), forms[i]['sound'].name))
            # compute crc
            # TEMPORARY
            try:
                sound.compute_crc()
            except:
                pass
Ejemplo n.º 12
0
def convert_to_solr_document(sound):
    document = {}

    # Basic sound fields
    keep_fields = [
        'username', 'created', 'is_explicit', 'avg_rating', 'is_remix',
        'num_ratings', 'channels', 'md5', 'was_remixed', 'original_filename',
        'duration', 'type', 'id', 'num_downloads', 'filesize'
    ]
    for key in keep_fields:
        document[key] = getattr(sound, key)
    document["original_filename"] = remove_control_chars(
        getattr(sound, "original_filename"))
    document["description"] = remove_control_chars(
        getattr(sound, "description"))
    document["tag"] = getattr(sound, "tag_array")
    document["license"] = getattr(sound, "license_name")

    if getattr(sound, "pack_id"):
        document["pack"] = remove_control_chars(getattr(sound, "pack_name"))
        document["grouping_pack"] = str(getattr(
            sound, "pack_id")) + "_" + remove_control_chars(
                getattr(sound, "pack_name"))
    else:
        document["grouping_pack"] = str(getattr(sound, "id"))

    document["is_geotagged"] = False
    if getattr(sound, "geotag_id"):
        document["is_geotagged"] = True
        if not math.isnan(getattr(sound, "geotag_lon")) and not math.isnan(
                getattr(sound, "geotag_lat")):
            document["geotag"] = str(getattr(sound, "geotag_lon")) + " " + str(
                getattr(sound, "geotag_lat"))

    document["bitdepth"] = getattr(sound, "bitdepth") if getattr(
        sound, "bitdepth") else 0
    document["bitrate"] = getattr(sound, "bitrate") if getattr(
        sound, "bitrate") else 0
    document["samplerate"] = int(getattr(sound, "samplerate")) if getattr(
        sound, "samplerate") else 0

    document["comment"] = [
        remove_control_chars(comment_text)
        for comment_text in getattr(sound, "comments_array")
    ]
    document["comments"] = getattr(sound, "num_comments")
    locations = sound.locations()
    document["waveform_path_m"] = locations["display"]["wave"]["M"]["path"]
    document["waveform_path_l"] = locations["display"]["wave"]["L"]["path"]
    document["spectral_path_m"] = locations["display"]["spectral"]["M"]["path"]
    document["spectral_path_l"] = locations["display"]["spectral"]["L"]["path"]
    document["preview_path"] = locations["preview"]["LQ"]["mp3"]["path"]

    # Audio Commons analysis
    # NOTE: as the sound object here is the one returned by SoundManager.bulk_query_solr, it will have the Audio Commons
    # descriptor fields under a property called 'ac_analysis'.
    ac_analysis = getattr(sound, "ac_analysis")
    if ac_analysis is not None:
        # If analysis is present, index all existing analysis fields under SOLR's dynamic fields "*_i", "*_d", "*_s"
        # and "*_b" depending on the value's type. Also add Audio Commons prefix.
        for key, value in ac_analysis.items():
            suffix = settings.SOLR_DYNAMIC_FIELDS_SUFFIX_MAP.get(
                type(value), None)
            if suffix:
                document['{0}{1}{2}'.format(
                    settings.AUDIOCOMMONS_DESCRIPTOR_PREFIX, key,
                    suffix)] = value

    return document
Ejemplo n.º 13
0
def create_sound(user,
                 sound_fields,
                 apiv2_client=None,
                 process=True,
                 remove_exists=False):
    """
    This function is used by the upload handler to create a sound object with
    the information provided through sound_fields parameter.
    """

    # Import models using apps.get_model (to avoid circular dependencies)
    Sound = apps.get_model('sounds', 'Sound')
    License = apps.get_model('sounds', 'License')
    Pack = apps.get_model('sounds', 'Pack')

    # 1 make sound object
    sound = Sound()
    sound.user = user
    sound.original_filename = sound_fields['name']
    sound.original_path = sound_fields['dest_path']
    try:
        sound.filesize = os.path.getsize(sound.original_path)
    except OSError:
        raise NoAudioException()

    license = License.objects.get(name=sound_fields['license'])
    sound.type = get_sound_type(sound.original_path)
    sound.license = license
    sound.md5 = md5file(sound.original_path)

    sound_already_exists = Sound.objects.filter(md5=sound.md5).exists()
    if sound_already_exists:
        existing_sound = Sound.objects.get(md5=sound.md5)
        if remove_exists:
            existing_sound.delete()
        else:
            msg = 'The file %s is already part of freesound and has been discarded, see <a href="%s">here</a>.' % \
                    (sound_fields['name'], reverse('sound', args=[existing_sound.user.username, existing_sound.id]))

            # Remove file (including mirror locations)
            os.remove(sound.original_path)
            remove_uploaded_file_from_mirror_locations(sound.original_path)
            _remove_user_uploads_folder_if_empty(sound.user)

            raise AlreadyExistsException(msg)

    # 2 save
    sound.save()

    # Create corresponding SoundLicenseHistory object (can't be done before Sound is saved for the first time)
    sound.set_license(license)

    # 3 move to new path
    orig = os.path.splitext(os.path.basename(
        sound.original_filename))[0]  # WATCH OUT!
    sound.base_filename_slug = "%d__%s__%s" % (
        sound.id, slugify(sound.user.username), slugify(orig))
    new_original_path = sound.locations("path")
    if sound.original_path != new_original_path:
        try:
            os.makedirs(os.path.dirname(new_original_path))
        except OSError:
            pass
        try:
            shutil.move(sound.original_path, new_original_path)

            # Check if user upload folder still has files and remove if empty
            # NOTE: we first need to remove the file from the mirror locations as we do not perform
            # a 'move' operation there.
            remove_uploaded_file_from_mirror_locations(sound.original_path)
            _remove_user_uploads_folder_if_empty(sound.user)

        except IOError as e:
            raise CantMoveException("Failed to move file from %s to %s" %
                                    (sound.original_path, new_original_path))
        sound.original_path = new_original_path
        sound.save()

    # Copy to mirror location
    copy_sound_to_mirror_locations(sound)

    # 4 create pack if it does not exist
    if 'pack' in sound_fields:
        if sound_fields['pack']:
            if Pack.objects.filter(
                    name=sound_fields['pack'],
                    user=user).exclude(is_deleted=True).exists():
                p = Pack.objects.get(name=sound_fields['pack'], user=user)
            else:
                p, created = Pack.objects.get_or_create(
                    user=user, name=sound_fields['pack'])
            sound.pack = p

    # 5 create geotag objects
    if 'geotag' in sound_fields:
        # Create geotag from lat,lon,zoom text format
        if sound_fields['geotag']:
            lat, lon, zoom = sound_fields['geotag'].split(',')
            geotag = GeoTag(user=user,
                            lat=float(lat),
                            lon=float(lon),
                            zoom=int(zoom))
            geotag.save()
            sound.geotag = geotag
    else:
        # Create geotag from lat, lon, zoom separated fields (if available)
        lat = sound_fields.get('lat', None)
        lon = sound_fields.get('lon', None)
        zoom = sound_fields.get('zoom', None)
        if lat is not None and lon is not None and zoom is not None:
            geotag = GeoTag(user=user,
                            lat=float(lat),
                            lon=float(lon),
                            zoom=int(zoom))
            geotag.save()
            sound.geotag = geotag

    # 6 set description, tags
    sound.description = remove_control_chars(sound_fields['description'])
    sound.set_tags(sound_fields['tags'])

    if 'is_explicit' in sound_fields:
        sound.is_explicit = sound_fields['is_explicit']

    # 6.5 set uploaded apiv2 client
    sound.uploaded_with_apiv2_client = apiv2_client

    # 7 save!
    sound.save()

    # 8 create moderation tickets if needed
    if user.profile.is_whitelisted:
        sound.change_moderation_state('OK')
    else:
        # create moderation ticket!
        sound.create_moderation_ticket()
        invalidate_template_cache("user_header", user.id)
        moderators = Group.objects.get(name='moderators').user_set.all()
        for moderator in moderators:
            invalidate_template_cache("user_header", moderator.id)

    # 9 process sound and packs
    sound.compute_crc()

    if process:
        try:
            sound.process_and_analyze(high_priority=True)

            if sound.pack:
                sound.pack.process()
        except ServerUnavailable:
            pass

    return sound
Ejemplo n.º 14
0
def create_sound(user,
                 sound_fields,
                 apiv2_client=None,
                 bulk_upload_progress=None,
                 process=True,
                 remove_exists=False):
    """
    This function is used to create sound objects uploaded via the sound describe form, the API or the bulk describe
    feature.

    Args:
        user (User): user that will appear as the uploader of the sound (author)
        sound_fields (dict): dictionary with data to populate the different fields of the sound object. Check example
            usages of create_sound for more information about what are these fields and their expected format
        apiv2_client (ApiV2Client): ApiV2Client object corresponding to the API account that triggered the creation
            of that sound object (if not provided, will be set to None)
        bulk_upload_progress (BulkUploadProgress): BulkUploadProgress object corresponding to the bulk upload progress
            that triggered the creation of this sound object (if not provided, will be set to None)
        process (bool): whether to trigger processing and analysis of the sound object after being created
            (defaults to True)
        remove_exists (bool): if the sound we're trying to create an object for already exists (according to
            md5 check), delete it (defaults to False)

    Returns:
        Sound: returns the created Sound object
    """

    # Import models using apps.get_model (to avoid circular dependencies)
    Sound = apps.get_model('sounds', 'Sound')
    License = apps.get_model('sounds', 'License')
    Pack = apps.get_model('sounds', 'Pack')

    # 1 make sound object
    sound = Sound()
    sound.user = user
    sound.original_filename = sound_fields['name']
    sound.original_path = sound_fields['dest_path']
    try:
        sound.filesize = os.path.getsize(sound.original_path)
    except OSError:
        raise NoAudioException()

    license = License.objects.get(name=sound_fields['license'])
    sound.type = get_sound_type(sound.original_path)
    sound.license = license
    sound.md5 = md5file(sound.original_path)

    sound_already_exists = Sound.objects.filter(md5=sound.md5).exists()
    if sound_already_exists:
        existing_sound = Sound.objects.get(md5=sound.md5)
        if remove_exists:
            existing_sound.delete()
        else:
            msg = 'The file %s is already part of freesound and has been discarded, see <a href="%s">here</a>.' % \
                    (sound_fields['name'], reverse('sound', args=[existing_sound.user.username, existing_sound.id]))

            # Remove file (including mirror locations)
            os.remove(sound.original_path)
            remove_uploaded_file_from_mirror_locations(sound.original_path)
            _remove_user_uploads_folder_if_empty(sound.user)

            raise AlreadyExistsException(msg)

    # 2 save
    sound.save()

    # Create corresponding SoundLicenseHistory object (can't be done before Sound is saved for the first time)
    sound.set_license(license)

    # 3 move to new path
    orig = os.path.splitext(os.path.basename(
        sound.original_filename))[0]  # WATCH OUT!
    sound.base_filename_slug = "%d__%s__%s" % (
        sound.id, slugify(sound.user.username), slugify(orig))
    new_original_path = sound.locations("path")
    if sound.original_path != new_original_path:
        create_directories(os.path.dirname(new_original_path), exist_ok=True)
        try:
            shutil.move(sound.original_path, new_original_path)

            # Check if user upload folder still has files and remove if empty
            # NOTE: we first need to remove the file from the mirror locations as we do not perform
            # a 'move' operation there.
            remove_uploaded_file_from_mirror_locations(sound.original_path)
            _remove_user_uploads_folder_if_empty(sound.user)

        except IOError as e:
            raise CantMoveException("Failed to move file from %s to %s" %
                                    (sound.original_path, new_original_path))
        sound.original_path = new_original_path
        sound.save()

    # Copy to mirror location
    copy_sound_to_mirror_locations(sound)

    # 4 create pack if it does not exist
    if 'pack' in sound_fields:
        if sound_fields['pack']:
            if Pack.objects.filter(
                    name=sound_fields['pack'],
                    user=user).exclude(is_deleted=True).exists():
                p = Pack.objects.get(name=sound_fields['pack'], user=user)
            else:
                p, created = Pack.objects.get_or_create(
                    user=user, name=sound_fields['pack'])
            sound.pack = p

    # 5 create geotag objects
    if 'geotag' in sound_fields:
        # Create geotag from lat,lon,zoom text format
        if sound_fields['geotag']:
            lat, lon, zoom = sound_fields['geotag'].split(',')
            geotag = GeoTag(user=user,
                            lat=float(lat),
                            lon=float(lon),
                            zoom=int(zoom))
            geotag.save()
            sound.geotag = geotag
    else:
        # Create geotag from lat, lon, zoom separated fields (if available)
        lat = sound_fields.get('lat', None)
        lon = sound_fields.get('lon', None)
        zoom = sound_fields.get('zoom', None)
        if lat is not None and lon is not None and zoom is not None:
            geotag = GeoTag(user=user,
                            lat=float(lat),
                            lon=float(lon),
                            zoom=int(zoom))
            geotag.save()
            sound.geotag = geotag

    # 6 set description, tags
    sound.description = remove_control_chars(sound_fields['description'])
    sound.set_tags(sound_fields['tags'])

    if 'is_explicit' in sound_fields:
        sound.is_explicit = sound_fields['is_explicit']

    # 6.5 set uploaded apiv2 client or bulk progress object (if any)
    sound.uploaded_with_apiv2_client = apiv2_client
    sound.uploaded_with_bulk_upload_progress = bulk_upload_progress

    # 7 save!
    sound.save()

    # 8 create moderation tickets if needed
    if user.profile.is_whitelisted:
        sound.change_moderation_state('OK')
    else:
        # create moderation ticket!
        sound.create_moderation_ticket()
        invalidate_template_cache("user_header", user.id)
        moderators = Group.objects.get(name='moderators').user_set.all()
        for moderator in moderators:
            invalidate_template_cache("user_header", moderator.id)

    # 9 process sound and packs
    sound.compute_crc()

    if process:
        try:
            sound.process_and_analyze(high_priority=True)

            if sound.pack:
                sound.pack.process()
        except ServerUnavailable:
            pass

    # Log
    if sound.uploaded_with_apiv2_client is not None:
        upload_source = 'api'
    elif sound.uploaded_with_bulk_upload_progress is not None:
        upload_source = 'bulk'
    else:
        upload_source = 'web'
    sounds_logger.info('Created Sound object (%s)' %
                       json.dumps({
                           'sound_id': sound.id,
                           'username': sound.user.username,
                           'upload_source': upload_source,
                       }))

    return sound
Ejemplo n.º 15
0
def sound_edit(request, username, sound_id):
    ONLY_RECOMMEND_TAGS_TO_HALF_OF_UPLOADS = settings.ONLY_RECOMMEND_TAGS_TO_HALF_OF_UPLOADS

    sound = get_object_or_404(Sound, id=sound_id, processing_state='OK')
    if sound.user.username.lower() != username.lower():
        raise Http404

    if not (request.user.has_perm('sound.can_change')
            or sound.user == request.user):
        raise PermissionDenied

    def invalidate_sound_cache(sound):
        invalidate_template_cache("sound_header", sound.id, True)
        invalidate_template_cache("sound_header", sound.id, False)
        invalidate_template_cache("sound_footer_top", sound.id)
        invalidate_template_cache("sound_footer_bottom", sound.id)
        invalidate_template_cache("display_sound", sound.id, True,
                                  sound.processing_state,
                                  sound.moderation_state)
        invalidate_template_cache("display_sound", sound.id, False,
                                  sound.processing_state,
                                  sound.moderation_state)

    def is_selected(prefix):
        if request.method == "POST":
            for name in request.POST.keys():
                if name.startswith(prefix + '-'):
                    return True
        return False

    def update_sound_tickets(sound, text):
        tickets = Ticket.objects.filter(content__object_id=sound.id,
                                        source=TICKET_SOURCE_NEW_SOUND) \
                               .exclude(status=TICKET_STATUS_CLOSED)
        for ticket in tickets:
            tc = TicketComment(sender=request.user,
                               ticket=ticket,
                               moderator_only=False,
                               text=text)
            tc.save()
            ticket.send_notification_emails(ticket.NOTIFICATION_UPDATED,
                                            ticket.MODERATOR_ONLY)

    if is_selected("description"):
        description_form = SoundDescriptionForm(request.POST,
                                                prefix="description")
        if description_form.is_valid():
            data = description_form.cleaned_data
            sound.set_tags(data["tags"])
            sound.description = remove_control_chars(data["description"])
            sound.original_filename = data["name"]
            sound.mark_index_dirty()
            invalidate_sound_cache(sound)
            update_sound_tickets(
                sound, '%s updated the sound description and/or tags.' %
                request.user.username)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        tags = " ".join([
            tagged_item.tag.name
            for tagged_item in sound.tags.all().order_by('tag__name')
        ])
        description_form = SoundDescriptionForm(
            prefix="description",
            initial=dict(tags=tags,
                         description=sound.description,
                         name=sound.original_filename))

    packs = Pack.objects.filter(user=request.user)
    if is_selected("pack"):
        pack_form = PackForm(packs, request.POST, prefix="pack")
        if pack_form.is_valid():
            data = pack_form.cleaned_data
            affected_packs = []
            if data['new_pack']:
                (pack,
                 created) = Pack.objects.get_or_create(user=sound.user,
                                                       name=data['new_pack'])
                sound.pack = pack
                affected_packs.append(pack)
            else:
                new_pack = data["pack"]
                old_pack = sound.pack
                if new_pack != old_pack:
                    sound.pack = new_pack
                    if new_pack:
                        affected_packs.append(new_pack)
                    if old_pack:
                        affected_packs.append(old_pack)

            sound.mark_index_dirty()  # Marks as dirty and saves
            invalidate_sound_cache(sound)
            update_sound_tickets(
                sound, '%s updated the sound pack.' % request.user.username)
            for affected_pack in affected_packs:  # Process affected packs
                affected_pack.process()

            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        pack_form = PackForm(
            packs,
            prefix="pack",
            initial=dict(pack=sound.pack.id) if sound.pack else None)

    if is_selected("geotag"):
        geotag_form = GeotaggingForm(request.POST, prefix="geotag")

        if geotag_form.is_valid():
            data = geotag_form.cleaned_data

            if data["remove_geotag"]:
                if sound.geotag:
                    geotag = sound.geotag.delete()
                    sound.geotag = None
                    sound.mark_index_dirty()
            else:
                if sound.geotag:
                    sound.geotag.lat = data["lat"]
                    sound.geotag.lon = data["lon"]
                    sound.geotag.zoom = data["zoom"]
                    sound.geotag.save()
                else:
                    sound.geotag = GeoTag.objects.create(lat=data["lat"],
                                                         lon=data["lon"],
                                                         zoom=data["zoom"],
                                                         user=request.user)
                    sound.mark_index_dirty()

            sound.mark_index_dirty()
            invalidate_sound_cache(sound)
            update_sound_tickets(
                sound, '%s updated the sound geotag.' % request.user.username)
            return HttpResponseRedirect(sound.get_absolute_url())
    else:
        if sound.geotag:
            geotag_form = GeotaggingForm(prefix="geotag",
                                         initial=dict(lat=sound.geotag.lat,
                                                      lon=sound.geotag.lon,
                                                      zoom=sound.geotag.zoom))
        else:
            geotag_form = GeotaggingForm(prefix="geotag")

    license_form = NewLicenseForm(request.POST)
    if request.POST and license_form.is_valid():
        sound.license = license_form.cleaned_data["license"]
        sound.mark_index_dirty()
        invalidate_sound_cache(sound)
        update_sound_tickets(
            sound, '%s updated the sound license.' % request.user.username)
        return HttpResponseRedirect(sound.get_absolute_url())
    else:
        license_form = NewLicenseForm(initial={'license': sound.license})

    google_api_key = settings.GOOGLE_API_KEY

    return render_to_response('sounds/sound_edit.html',
                              locals(),
                              context_instance=RequestContext(request))