Advertisement
Guest User

Deluge execute script for seedbox with remote sonarr/radarr

a guest
Dec 16th, 2017
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.69 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # version 1
  3. """
  4. This script is meant to be run on a seedbox with deluge. It will extract .rars and transfer the
  5. content to your home computer or NAS running Sonarr/Radarr where the fill will be imported.
  6. This script has been tested with:
  7.    - Linux (tested with Ubuntu 16.04)
  8.        - unzip and unrar are required: `sudo apt-get install unzip unrar lftp python3 python3-pip`
  9.    - Modules required: pip3 install requests glob2
  10.    - Deluge with Label and Execute plugins
  11.    - Sonarr and Radarr on a different machine
  12. Usage on a different environment may require additional tweaks. MAKE SURE THE
  13. EXECUTABLE BIT IS SET ON THIS FILE.
  14.  
  15. Known bugs: Apparently Sonarr/Radarr talk directly with deluge and overwrite whatever API call
  16. is being made by the script, so files will only be copied instead of moved on import. Remember to
  17. clean up your /import/complete/ folder!
  18.  
  19. """
  20.  
  21. from collections import namedtuple
  22. import glob2
  23. import os
  24. import requests
  25. import shutil
  26. from syslog import syslog
  27. import sys
  28. import time
  29.  
  30. # -- Configs
  31. commands = {'zip': 'unzip -u', 'rar': 'unrar -o- e'}
  32. extraction_root = '/home/deluge/sync/'
  33. lockfile = '/home/deluge/deluge.lock'
  34.  
  35. deluge = namedtuple('DelugeConfig', 'url password session_id')
  36. deluge.url = 'https://localhost:8112/json'
  37. deluge.password = 'password'
  38.  
  39. sonarr = namedtuple('SonarrConfig', 'url api_key label')
  40. sonarr.url = 'https://remote.server:9898/api'
  41. sonarr.api_key = '123456789'
  42. sonarr.label = 'sonarr'
  43.  
  44. radarr = namedtuple('RadarrConfig', 'url api_key label')
  45. radarr.url = 'https://remote.server:7878/api'
  46. radarr.api_key = '123456789'
  47. radarr.label = 'radarr'
  48.  
  49. lftpcom = 'lftp -c "open -u username,password -p 22 sftp://remote.server; set sftp:auto-confirm yes; set ssl:verify-certificate false; mirror -c --ignore-time -R -P 5 ' + extraction_dir + ' /incoming/; mv /incoming/' + torrent.name + '/ /incoming/complete/"'
  50.  
  51. # -- Arguments
  52. torrent = namedtuple('Torrent', 'id name path dir label')
  53. torrent.id = sys.argv[1]
  54. torrent.name = sys.argv[2]
  55. torrent.path = sys.argv[3]
  56. torrent.dir = os.path.join(torrent.path, torrent.name)
  57. torrent.label = ''
  58.  
  59. syslog(torrent.name + ' - Preparing torrent for extraction: ' + torrent.dir)
  60.  
  61.  
  62. def update_rights(path, group, mode=0o664):
  63.     shutil.chown(path, group=group)
  64.     os.chmod(path, mode)
  65.  
  66.  
  67. # -- Fetch torrent label
  68. syslog(torrent.name + ' - Authenticating into deluge.')
  69.  
  70. auth_headers = {'content-type': 'application/json', 'accept': 'application/json'}
  71. auth_data = {'method': 'auth.login', 'params': [deluge.password], 'id': 1}
  72. response = requests.post(deluge.url, json=auth_data, headers=auth_headers, verify=False)
  73.  
  74. if response.status_code != 200 and not response.json()['result']:
  75.     sys.exit('Unable to authenticate to deluge')
  76.  
  77. deluge.session_id = response.cookies['_session_id']
  78.  
  79. syslog(torrent.name + ' - Got deluge session ID ' + deluge.session_id)
  80. syslog(torrent.name + ' - Fetching torrent label from deluge.')
  81.  
  82. info_headers = {'content-type': 'application/json', 'accept': 'application/json'}
  83. info_cookies = dict(_session_id=deluge.session_id)
  84. info_data = {'method': 'web.get_torrent_status', 'params': [torrent.id, ['label']], 'id': 1}
  85. response = requests.post(deluge.url, json=info_data, headers=info_headers, cookies=info_cookies, verify=False)
  86.  
  87. if response.status_code != 200:
  88.     sys.exit('Unable to fetch torrent label')
  89.  
  90. torrent.label = response.json()['result']['label']
  91.  
  92. syslog(torrent.name + ' - Got torrent label: ' + torrent.label)
  93.  
  94. pvr = next((x for x in (sonarr, radarr) if x.label == torrent.label), None)
  95.  
  96. if not pvr:
  97.     syslog(torrent.name + ' - Not a Sonarr/Radarr tracked download. Skipping extraction.')
  98.     sys.exit(0)
  99.  
  100. ### Wait til lockfile is gone, then create lockfile
  101. syslog(torrent.name + ' - Checking for lock file ...')
  102. locked = False
  103. while os.path.exists(lockfile):
  104.     if locked == False:
  105.         syslog(torrent.name + ' - Another torrent is currently being processed. Sleeping ...')
  106.     locked = True
  107.     time.sleep(10)
  108.     print('Another torrent is currently being processed. Sleeping ...')
  109.  
  110. if not os.path.exists(lockfile):    
  111.     lf = open(lockfile, 'w')
  112.     lf.write(torrent.name)
  113.     lf.close()
  114.     syslog(torrent.name + ' - Created lock file.')
  115.    
  116. if not os.path.exists(lockfile):
  117.     sys.exit(torrent.name + ' - Cannot create lock file')
  118.  
  119. # -- Extract files
  120. extraction_dir = os.path.join(extraction_root, torrent.name)
  121. extracted = False
  122. if not os.path.isdir(extraction_dir):
  123.     os.makedirs(extraction_dir)
  124.  
  125. os.chdir(torrent.dir)
  126. for ext, command in commands.items():
  127.     for file in glob2.glob('**/*.' + ext): ######### will mess up if only subs are rar'd and movie is not...
  128.         file_path = os.path.join(torrent.dir, file)
  129.         syslog(torrent.name + ' - Extracting ' + file_path + ' to ' + extraction_dir)
  130.  
  131.         # TODO: How to handle extraction errors (ie: CRC errors)?
  132.         os.system(command + ' "' + file + '" "' + extraction_dir + '"')
  133.         extracted = True
  134.  
  135. if not extracted:
  136.     syslog(torrent.name + ' - Nothing to extract. Creating symlinks.')
  137.     shutil.rmtree(extraction_dir, ignore_errors=True)
  138.     if os.path.islink(extraction_dir):
  139.         os.unlink(extraction_dir)
  140.     os.symlink(torrent.dir, extraction_dir)
  141.  
  142. # -- Copy extra files (srt, nfo, ...)
  143. #syslog(torrent.name + ' - Fetching extra file types to copy.')
  144. #
  145. #extras_headers = {'accept': 'application/json', 'X-Api-Key': pvr.api_key}
  146. #response = requests.get(pvr.url + '/config/mediamanagement', headers=extras_headers)
  147. #
  148. #extra_file_types = response.json()['extraFileExtensions']
  149. #
  150. #syslog(torrent.name + ' - Copying extra files: ' + extra_file_types)
  151. #for ext in extra_file_types.split(','):
  152. #    for file in glob2.glob('*.' + ext):
  153. #        shutil.copy2(file, extraction_dir)
  154.  
  155. ### TRANSFER FILES
  156. syslog(torrent.name + ' - Starting file transfer ...')
  157. os.system(lftpcom)
  158. syslog(torrent.name + ' - Transfer complete.')
  159.  
  160.  
  161. # -- Notify Sonarr/Radarr
  162. notify_headers = {'content-type': 'application/json', 'accept': 'application/json', 'X-Api-Key': pvr.api_key}
  163. notify_data = {'name': 'DownloadedEpisodesScan', 'importMode': 'Move', 'downloadClientId': torrent.id.upper(),
  164.                'path': extraction_dir}
  165.  
  166. syslog(torrent.name + ' - Asking PVR API to scan extracted files.')
  167.  
  168. response = requests.post(pvr.url + '/command', json=notify_data, headers=notify_headers)
  169.  
  170. if not response.status_code >= 200 and response.status_code < 300:
  171.     syslog(torrent.name + ' - Could not notify Sonarr/Radarr of extracted file.')
  172.    
  173. ### DELETE FILES
  174. shutil.rmtree(extraction_dir, ignore_errors=True)
  175. if os.path.islink(extraction_dir):
  176.     os.unlink(extraction_dir)
  177. os.remove(lockfile)
  178. syslog(torrent.name + ' - Processing complete.')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement