Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Fill audio field Anki plugin

By: a guest on Jul 31st, 2012  |  syntax: Python  |  size: 4.80 KB  |  views: 80  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. # -*- coding: utf-8 -*-
  2. """
  3. Fill audio field with [sound:$kana - $kanji.mp3]
  4. and try to download audio from languagepod101.
  5. If no audio available fill with no audio message.
  6. Skips over cards which already have something written
  7. in the audio field.
  8.  
  9. """
  10.  
  11. from PyQt4.QtCore import *
  12. from PyQt4.QtGui import *
  13.  
  14. import os, urllib, urllib2, shutil, hashlib
  15.  
  16. from ankiqt import mw, ui
  17. from ankiqt.ui import utils
  18. from anki.cards import Card
  19.  
  20. # User settings
  21.  
  22. """
  23. The name of the model.  Other models will be ignored.
  24. """
  25. MODEL_NAME = 'MasterSentences'
  26.  
  27. """
  28. The field which keeps the Kanji.
  29. """
  30. KANJI_FIELD = 'VocabularyKanji'
  31.  
  32. """
  33. The field which keeps the Kana.
  34. """
  35. KANA_FIELD = 'VocabularyKana'
  36.  
  37. """
  38. The field which keeps the audio.
  39. """
  40. AUDIO_FIELD = 'VocabularyAudio'
  41.  
  42. """
  43. Content to fill with if audio is missing.
  44. """
  45. MISSING_FILL = u'(音無し)'
  46.  
  47. # Internal settings
  48.  
  49. audioFileExtension = '.mp3'
  50. downloadedFileExtension = '.php'
  51. base_url = 'http://assets.languagepod101.com/dictionary/japanese/audiomp3.php?'
  52.  
  53. def downloadSound(kanji, kana, deck, log):
  54.   """
  55.  Download audio for given word. If it is not the dummy audio
  56.  (check by file size) copy it to the media dir of the deck.
  57.  """
  58.   # Determine local file name
  59.   target_filename = kana + u' - ' + kanji + u'.mp3'
  60.   target_path = os.path.join(deck.mediaDir(create=True), target_filename)
  61.  
  62.   # Check if already present
  63.   if os.path.exists(target_path):
  64.     return 2
  65.  
  66.   # Download audo file
  67.   args = urllib.urlencode({'kana': kana.encode('utf-8'), 'kanji': kanji.encode('utf-8')})
  68.   url = base_url + args
  69.   (filename, headers) = urllib.urlretrieve(url)
  70.  
  71.   # Check if not dummy audio
  72.   size = os.path.getsize(filename)
  73.   if(size > 50000):
  74.     log.append('No audio for %s' % (kanji))
  75.     return 3
  76.  
  77.   # Copy audio file
  78.   shutil.copy2(filename, target_path)
  79.   return 1
  80.  
  81. def update_card(deck, card, log):
  82.   """
  83.  Update the card by reading kanji/kana, downloading the
  84.  audio and updating the audio field.
  85.  """
  86.   kanji = card.fact[KANJI_FIELD]
  87.   kana = card.fact[KANA_FIELD]
  88.   audio = card.fact[AUDIO_FIELD]
  89.   # Only update if no audio so far
  90.   if audio.strip() == "" or audio.strip() == "<br />":
  91.     status = downloadSound(kanji, kana, deck, log)
  92.     if status == 1 or status == 2:
  93.       newaudio = u"[sound:%s - %s.mp3]" % (kana, kanji)
  94.     else:
  95.       newaudio = MISSING_FILL
  96.     card.fact[AUDIO_FIELD] = newaudio
  97.     card.fact.setModified(textChanged=True,deck=deck)
  98.     #log.append('Modified card %s[%s].' % (kanji, kana))
  99.     return status
  100.   else:
  101.     #log.append('Did not modify card %s[%s].' % (kanji, kana))
  102.     return 0
  103.  
  104. def get_cards_from_deck(deck, log):
  105.   """
  106.  Gets all the card adhering to the model from the specified deck.
  107.  """
  108.   sql = 'select id from models where name = \'%s\'' % MODEL_NAME
  109.   model_id = deck.s.scalar(sql)
  110.  
  111.   if model_id is None:
  112.     log.append('No model of name %s' % MODEL_NAME)
  113.     return []
  114.  
  115.   sql = 'select id from cardmodels where modelId = %s' % model_id
  116.   card_model_id = deck.s.scalar(sql)
  117.  
  118.   if card_model_id is None:
  119.     log.append('No card model of name %s' % MODEL_NAME)
  120.     return []
  121.  
  122.   cards_query = deck.s.query(Card).filter('cardModelId = %s' % card_model_id)
  123.  
  124.   if cards_query is None:
  125.     log.append('No cards in model of name %s' % MODEL_NAME)
  126.     return []
  127.  
  128.   cards = []
  129.   for c in cards_query:
  130.     cards.append(c)
  131.   return cards_query
  132.  
  133. def process_deck(deck, log):
  134.   """
  135.  Processes the cards in the specified deck.
  136.  """
  137.   cards = get_cards_from_deck(deck, log)
  138.   total = 0
  139.   modified = 0
  140.   noaudio = 0
  141.  
  142.   for card in cards:
  143.     total = total + 1
  144.     status = update_card(deck, card, log)
  145.     if status > 0:
  146.       modified = modified + 1
  147.       if status == 3:
  148.         noaudio = noaudio + 1
  149.   if modified > 0:
  150.     deck.s.flush()
  151.     deck.setModified()
  152.  
  153.   log.append('Total of %d cards...' % total)
  154.   log.append('Total of %d cards, %d cards modified, no audio for %d cards, %d cards skipped.' % (total, modified, noaudio, total - modified))
  155.  
  156. def doFill():
  157.   """
  158.  Update deck and display log information.
  159.  """
  160.   # Check if we have a deck open
  161.   if mw.deck is None: return
  162.  
  163.   log = []
  164.   log.append('Starting update.')
  165.   process_deck(mw.deck, log)
  166.   log.append('Update complete.')
  167.   utils.showInfo('\n'.join(log))
  168.  
  169. def init_hook():
  170.     """
  171.    Initialises the Anki GUI to present an option to invoke the plugin.
  172.    """
  173.     l.append(('Fill audio fields', FillAudioField))
  174.  
  175. def init():
  176.     mw.mainWin.toolBar.addSeparator()
  177.     FillAudioField= QAction(mw)
  178.     FillAudioField.setText(u"Fill Audio Field")
  179.     FillAudioField.setEnabled(True)
  180.     mw.connect(FillAudioField,SIGNAL("triggered()"),doFill)
  181.     mw.mainWin.toolBar.addAction(FillAudioField)
  182.  
  183. mw.addHook("init", init)
  184. mw.registerPlugin(u"Fill Audio Field", 666)
clone this paste RAW Paste Data