示例#1
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'))
示例#2
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 = 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
示例#3
0
    def handle(self, *args, **options):
        sound_list = args[0]
        base_dir = os.path.dirname(sound_list)
        delete_already_existing = False
        if len(args) > 1:
            delete_already_existing = bool(args[1])

        isHeader = True
        for line in csv.reader(open(sound_list,'rU')):
            if isHeader:
                isHeader = False
                continue

            # 0 get data from csv
            pathf,namef,tagsf,geotagf,descriptionf,licensef,packnamef,usernamef = line
            u = User.objects.get(username=usernamef)

            # 1 create dir and move sound to dir
            directory = os.path.join(settings.UPLOADS_PATH, str(u.id))
            if not os.path.exists(directory):
                os.mkdir(directory)
            src_path = base_dir + "/"+ pathf
            dest_path = os.path.join(directory, os.path.basename(pathf))
            #print src_path,dest_path

            shutil.copy(src_path,dest_path)

            # 2 make sound object
            # user id (search), original_fname(name),path (new), filesize,type,slicense
            sound = Sound()
            sound.user = u
            sound.original_filename = namef
            sound.original_path = dest_path
            sound.filesize = os.path.getsize(sound.original_path)
            sound.type = get_sound_type(sound.original_path)
            # License format
            # name: 'Creative Commons 0'
            # name: 'Attribution'
            # name: 'Attribution Noncommercial'
            l = License.objects.get(name=licensef)
            sound.license = l

            # 3 md5, check
            try:
                sound.md5 = md5file(sound.original_path)
            except IOError:
                #messages.add_message(request, messages.ERROR, 'Something went wrong with accessing the file %s.' % sound.original_path)
                continue

            sound_already_exists = Sound.objects.filter(md5=sound.md5).exists()
            if sound_already_exists:
                if delete_already_existing:
                    existing_sound = Sound.objects.get(md5=sound.md5)
                    existing_sound.delete()
                    print 'The file %s is already part of freesound, we re-add it again' % (sound.original_filename)
                else:
                    os.remove(sound.original_path)
                    print 'The file %s is already part of freesound, we re-add it again' % (sound.original_filename)
                    continue

            # 4 save
            sound.save()

            # 5 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)
                    #shutil.copy(sound.original_path, new_original_path)
                except IOError, e:
                    print "failed to move file from %s to %s" % (sound.original_path, new_original_path)
                    #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()

            # 6 create pack if it does not exist
            if packnamef:
                if Pack.objects.filter(name=packnamef, user=u).exists():
                    p = Pack.objects.get(name=packnamef, user=u)
                else:
                    p, created = Pack.objects.get_or_create(user=u, name=packnamef)

                sound.pack = p
                #dirty_packs.append(sound.pack)

            # 7 create geotag objects
            # format: lat#lon#zoom
            if geotagf:
                lat,lon,zoom = [g for g in geotagf.split(" ") if g]
                geotag = GeoTag(user=u,
                    lat=float(lat),
                    lon=float(lon),
                    zoom=int(zoom))
                geotag.save()
                sound.geotag = geotag

            # 8 set description, tags
            sound.description = descriptionf
            sound.set_tags([t for t in tagsf.split(" ") if t])

            # 9 save!
            sound.save()

            # if(whitelisted): set moderation OK
            sound.moderation_state = 'OK'
            sound.save()

            # 10 Proces
            try:
                sound.compute_crc()
            except:
                pass

            try:
                sound.process()
            except Exception, e:
                print 'Sound with id %s could not be scheduled. (%s)' % (sound.id, str(e))
示例#4
0
    def handle(self, *args, **options):
        sound_list = args[0]
        base_dir = os.path.dirname(sound_list)
        delete_already_existing = False
        if len(args) > 1:
            delete_already_existing = bool(args[1])

        isHeader = True
        for line in csv.reader(open(sound_list, 'rU')):
            if isHeader:
                isHeader = False
                continue

            # 0 get data from csv
            pathf, namef, tagsf, geotagf, descriptionf, licensef, packnamef, usernamef = line
            u = User.objects.get(username=usernamef)

            # 1 create dir and move sound to dir
            directory = os.path.join(settings.UPLOADS_PATH, str(u.id))
            if not os.path.exists(directory):
                os.mkdir(directory)
            src_path = base_dir + "/" + pathf
            dest_path = os.path.join(directory, os.path.basename(pathf))
            #print src_path,dest_path

            shutil.copy(src_path, dest_path)

            # 2 make sound object
            # user id (search), original_fname(name),path (new), filesize,type,slicense
            sound = Sound()
            sound.user = u
            sound.original_filename = namef
            sound.original_path = dest_path
            sound.filesize = os.path.getsize(sound.original_path)
            sound.type = get_sound_type(sound.original_path)
            # License format
            # name: 'Creative Commons 0'
            # name: 'Attribution'
            # name: 'Attribution Noncommercial'
            l = License.objects.get(name=licensef)
            sound.license = l

            # 3 md5, check
            try:
                sound.md5 = md5file(sound.original_path)
            except IOError:
                #messages.add_message(request, messages.ERROR, 'Something went wrong with accessing the file %s.' % sound.original_path)
                continue

            sound_already_exists = Sound.objects.filter(md5=sound.md5).exists()
            if sound_already_exists:
                if delete_already_existing:
                    existing_sound = Sound.objects.get(md5=sound.md5)
                    existing_sound.delete()
                    print 'The file %s is already part of freesound, we re-add it again' % (
                        sound.original_filename)
                else:
                    os.remove(sound.original_path)
                    print 'The file %s is already part of freesound, not uploading it' % (
                        sound.original_filename)
                    continue

            # 4 save
            sound.save()

            # 5 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)
                    #shutil.copy(sound.original_path, new_original_path)
                except IOError, e:
                    print "failed to move file from %s to %s" % (
                        sound.original_path, new_original_path)
                    #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()

            # 6 create pack if it does not exist
            if packnamef:
                if Pack.objects.filter(
                        name=packnamef,
                        user=u).exclude(is_deleted=True).exists():
                    p = Pack.objects.get(name=packnamef, user=u)
                else:
                    p, created = Pack.objects.get_or_create(user=u,
                                                            name=packnamef)

                sound.pack = p

            # 7 create geotag objects
            # format: lat#lon#zoom
            if geotagf:
                lat, lon, zoom = [g for g in geotagf.split(" ") if g]
                geotag = GeoTag(user=u,
                                lat=float(lat),
                                lon=float(lon),
                                zoom=int(zoom))
                geotag.save()
                sound.geotag = geotag

            # 8 set description, tags
            sound.description = descriptionf
            sound.set_tags([t for t in tagsf.split(" ") if t])

            # 9 save!
            sound.save()

            # if(whitelisted): set moderation OK
            sound.change_moderation_state('OK',
                                          do_not_update_related_stuff=True)

            # 10 Proces
            try:
                sound.compute_crc()
            except:
                pass

            try:
                sound.process()
            except Exception, e:
                print 'Sound with id %s could not be scheduled. (%s)' % (
                    sound.id, str(e))
示例#5
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.
    '''

    # 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
    # format: lat#lon#zoom
    if 'geotag' in sound_fields:
        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

    # 6 set description, tags
    sound.description = 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', do_not_update_related_stuff=True)
    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 proces sound and packs
    try:
        sound.compute_crc()
    except:
        pass

    if process:
        try:
            sound.process()

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

    return sound