text: import os
  import shutil
  import ujson
  import datetime
  import time
  
  from celery import states
  from celery.result import AsyncResult
  from django.contrib.auth.decorators import login_required
  from django.db.transaction import atomic
  from django.http.response import HttpResponse, HttpResponseNotFound
  from django.shortcuts import render, redirect
  from django.views.decorators.http import last_modified
  import requests
  from requests.exceptions import RequestException
  
  from WhatManager2 import whatimg
  from WhatManager2.utils import wm_str
  from home.models import DownloadLocation, WhatTorrent
  from qobuz import tasks
  from qobuz.api import get_qobuz_client
  from qobuz.models import NewUploadForm, QobuzUpload, EditUploadForm
  from qobuz.settings import ADD_TRANSCODE_REQUEST_URL, ADD_TRANSCODE_USERNAME, ADD_TRANSCODE_PASSWORD
  from what_transcode.utils import get_info_hash
  
  
  @login_required
  def uploads(request):
      uploads = QobuzUpload.objects.order_by('-added').all()
      data = {
          'uploads': uploads,
      }
      return render(request, 'qobuz/uploads.html', data)
  
  
  @atomic
  @login_required
  def edit_upload(request, upload_id):
      qobuz_upload = QobuzUpload.objects.get(id=upload_id)
      if request.method == 'POST':
          form = EditUploadForm(request.POST, qobuz_upload=qobuz_upload)
          if form.is_valid():
              qobuz_upload.artists = form.cleaned_data['artists']
              qobuz_upload.album_name = form.cleaned_data['album_name']
              tracks = []
              for i, track in enumerate(qobuz_upload.track_data):
                  qobuz_track = qobuz_upload.album_data['tracks']['items'][i]
                  title_field = 'track_{0}_{1}_title'.format(qobuz_track['media_number'], i + 1)
                  artists_field = 'track_{0}_{1}_artists'.format(qobuz_track['media_number'], i + 1)
                  tracks.append({
                      'media_number': qobuz_track['media_number'],
                      'artists': form.cleaned_data[artists_field],
                      'title': form.cleaned_data[title_field],
                  })
              qobuz_upload.track_data_json = ujson.dumps(tracks)
              qobuz_upload.save()
      else:
          form = EditUploadForm(qobuz_upload=qobuz_upload)
      download_error = ''
      if qobuz_upload.download_task_id:
          async_result = AsyncResult(qobuz_upload.download_task_id)
          if async_result.state == states.PENDING:
              download_status = 'Waiting to start'
          elif async_result.state == states.STARTED:
              download_status = 'Started'
          elif async_result.state == states.SUCCESS:
              download_status = 'Completed'
          elif async_result.state == states.FAILURE:
              download_status = 'Failed'
              download_error = '{0}: {1}'.format(type(async_result.result).__name__,
                                                 async_result.result.message)
          else:
              download_status = 'Unknown Status'
      else:
          download_status = 'not_started'
      try:
          spectral_files = sorted(os.listdir(wm_str(qobuz_upload.spectrals_path)))
      except OSError:
          spectral_files = []
      try:
          cover_files = sorted([f for f in os.listdir(wm_str(qobuz_upload.temp_media_path))
                                if f.endswith('.jpg')], reverse=True)
      except OSError:
          cover_files = []
      data = {
          'upload': qobuz_upload,
          'form': form,
          'download_status': download_status,
          'download_error': download_error,
          'spectral_files': spectral_files,
          'cover_files': cover_files,
      }
      return render(request, 'qobuz/edit_upload.html', data)
  
  
  @login_required
  def download_torrent_file(request, upload_id):
      qobuz_upload = QobuzUpload.objects.get(id=upload_id)
      file_name = qobuz_upload.torrent_name + '.torrent'
      file_path = os.path.join(qobuz_upload.temp_media_path, file_name)
      f = open(wm_str(file_path), 'rb')
      response = HttpResponse(f, content_type='application/x-bittorrent')
      response['Content-Disposition'] = 'attachment; filename="' + file_name + '"'
      return response
  
  
  @atomic
  @login_required
  def upload_cover_to_whatimg(request, upload_id):
      qobuz_upload = QobuzUpload.objects.get(id=upload_id)
      with open(os.path.join(wm_str(qobuz_upload.temp_media_path), 'folder.jpg'), 'rb') as f:
          data = f.read()
      qobuz_upload.what_img_cover = whatimg.upload_image_from_memory('4460', data)
      qobuz_upload.save()
      return redirect(edit_upload, upload_id)
  
  
  def _add_to_wm_transcode(what_id):
      print 'Adding {0} to wm'.format(what_id)
      post_data = {
          'what_id': what_id,
      }
      response = requests.post(ADD_TRANSCODE_REQUEST_URL, data=post_data,
                               auth=(ADD_TRANSCODE_USERNAME, ADD_TRANSCODE_PASSWORD))
      response_json = response.json()
      if response_json['message'] != 'Request added.':
          raise Exception('Cannot add {0} to wm: {1}'.format(what_id, response_json['message']))
  
  
  def add_to_wm_transcode(what_id):
      for i in range(2):
          try:
              _add_to_wm_transcode(what_id)
              return
          except Exception:
              print 'Error adding to wm, trying again in 2 sec...'
              time.sleep(3)
      _add_to_wm_transcode(what_id)
  
  
  @login_required
  def start_seeding(request, upload_id):
      qobuz_upload = QobuzUpload.objects.get(id=upload_id)
      dest_upload_dir = DownloadLocation.get_what_preferred().path
      torrent_file_path = os.path.join(qobuz_upload.temp_media_path,
                                       qobuz_upload.torrent_name + u'.torrent')
      info_hash = get_info_hash(torrent_file_path)
      what_torrent = WhatTorrent.get_or_create(request, info_hash=info_hash)
      qobuz_upload.what_torrent = what_torrent
      qobuz_upload.save()
      dest_path = os.path.join(dest_upload_dir, str(what_torrent.id))
      shutil.rmtree(wm_str(qobuz_upload.spectrals_path))
      os.remove(wm_str(torrent_file_path))
      try:
          os.makedirs(wm_str(dest_path))
      except OSError:
          raise Exception('Dest torrent directory already exists.')
      os.chmod(wm_str(dest_path), 0777)
      shutil.move(wm_str(qobuz_upload.temp_media_path), wm_str(dest_path))
      add_to_wm_transcode(str(what_torrent.id))
      return redirect(edit_upload, upload_id)
  
  
  def get_image_last_modified(prop):
      def inner(request, upload_id):
          try:
              qobuz_upload = QobuzUpload.objects.get(id=upload_id)
              path = os.path.join(getattr(qobuz_upload, prop), os.path.basename(request.GET['path']))
              s = os.path.getmtime(wm_str(path))
              return datetime.datetime.utcfromtimestamp(s)
          except Exception:
              return None
  
      return inner
  
  
  @last_modified(get_image_last_modified('spectrals_path'))
  def view_spectral(request, upload_id):
      try:
          qobuz_upload = QobuzUpload.objects.get(id=upload_id)
          path = os.path.join(qobuz_upload.spectrals_path, os.path.basename(request.GET['path']))
          f = open(wm_str(path), 'rb')
          return HttpResponse(f, content_type='image/jpeg')
      except Exception:
          return HttpResponseNotFound()
  
  
  @login_required
  @last_modified(get_image_last_modified('temp_media_path'))
  def view_cover(request, upload_id):
      qobuz_upload = QobuzUpload.objects.get(id=upload_id)
      path = os.path.join(qobuz_upload.temp_media_path, os.path.basename(request.GET['path']))
      f = open(wm_str(path), 'rb')
      return HttpResponse(f, content_type='image/jpeg')
  
  
  @atomic
  @login_required
  def start_download_album(request, upload_id):
      qobuz_upload = QobuzUpload.objects.get(id=upload_id)
      if qobuz_upload.download_task_id is not None:
          qobuz_upload.download_task_id = None
      tasks.start_download_album(qobuz_upload)
      return redirect(edit_upload, upload_id)
  
  
  @atomic
  @login_required
  def new_upload(request):
      if request.method == 'POST':
          form = NewUploadForm(request.POST)
          if form.is_valid():
              qobuz = get_qobuz_client(request)
              album_id = form.cleaned_data['album_id']
              try:
                  album = qobuz.call('album/get', {'album_id': album_id})
                  qobuz_upload = QobuzUpload(
                      qobuz_album_id=album_id,
                      album_data_json=ujson.dumps(album),
                  )
                  qobuz_upload.populate_fields()
                  qobuz_upload.save()
                  return redirect(edit_upload, qobuz_upload.id)
              except RequestException:
                  form.add_error('album_id', 'Cannot fetch Qobuz album')
      else:
          form = NewUploadForm()
      data = {
          'form': form,
      }
      return render(request, 'qobuz/new_upload.html', data)
  
  