You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gangplank.py 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!/usr/bin/env python3
  2. import datetime
  3. import os
  4. import subprocess
  5. import sys
  6. import inotify.adapters
  7. def extract_zip(path, dest):
  8. p = subprocess.run(['unzip', '-o', '-qq', path, '-d', dest])
  9. if p.returncode != 0:
  10. raise Exception('failed to extract ' + path)
  11. def extract_rar(path, dest):
  12. if not dest.endswith('/'):
  13. dest += '/'
  14. p = subprocess.run(['unrar', 'x', '-idq', '-y', path, dest])
  15. if p.returncode != 0:
  16. raise Exception('failed to extract ' + path)
  17. def extract_tar_gz(path, dest):
  18. if not dest.endswith('/'):
  19. dest += '/'
  20. p = subprocess.run([
  21. 'tar',
  22. '-C', dest, # goes first cuz reasons?
  23. '-x', '-z',
  24. '-f', path])
  25. if p.returncode != 0:
  26. raise Exception('failed to extract ' + path)
  27. ARCHIVE_HANDLERS = {
  28. '.zip': extract_zip,
  29. '.rar': extract_rar,
  30. '.tar.gz': extract_tar_gz
  31. }
  32. def convert_name(path):
  33. base = os.path.basename(path)
  34. date = str(datetime.date.today())
  35. return str(date) + '-' + ''.join(c for c in base if c.isalpha())
  36. def process_file(path, extractdir):
  37. filename = os.path.basename(path)
  38. for (ext, handler) in ARCHIVE_HANDLERS.items():
  39. if path.endswith(ext):
  40. # Set up the directory
  41. destdir = os.path.realpath(os.path.join(extractdir, convert_name(path)))
  42. os.makedirs(destdir, exist_ok=True)
  43. # Actually extract it
  44. print('Processing', filename, '...')
  45. handler(path, destdir)
  46. print('Extracted', filename, 'to', destdir)
  47. return True
  48. # If we did nothing, just ignore it.
  49. print('File', filename, 'doesn\'t seem to be an archive, ignoring')
  50. return False
  51. def main(args):
  52. if len(args) != 3:
  53. print('usage: ./crowsnest.py <watchdir(s)> <extractdir>')
  54. return 1
  55. # Do setup and sanity checking
  56. watchdirs = args[1].split(',')
  57. extractdir = args[2]
  58. for d in watchdirs:
  59. if not os.path.exists(d):
  60. print('This watch path does not exist:', d)
  61. return 1
  62. if not os.path.exists(extractdir):
  63. print('extract path does not exist')
  64. return 1
  65. # Set up the watch
  66. watch = inotify.adapters.Inotify()
  67. for d in watchdirs:
  68. real = os.path.realpath(d)
  69. watch.add_watch(real)
  70. print('Added watch for:', real)
  71. # Start watching
  72. for event in watch.event_gen(yield_nones=False):
  73. (_, type_names, path, filename) = event
  74. fullpath = os.path.join(path, filename)
  75. if os.path.isdir(fullpath):
  76. print('Found new directory created:', filename)
  77. continue
  78. # Do some checking to see if it was something we care about.
  79. wasimportant = False
  80. for tn in type_names:
  81. if tn == 'IN_CLOSE_WRITE' or tn == 'IN_MOVED_TO':
  82. wasimportant = True
  83. if not wasimportant:
  84. continue
  85. # Actually deal with it.
  86. try:
  87. did_something = process_file(fullpath, extractdir)
  88. if did_something:
  89. os.remove(fullpath)
  90. except Exception as err:
  91. print('Failed to process file:', str(err))
  92. # Probs won't get here.
  93. return 0
  94. if __name__ == '__main__':
  95. sys.exit(main(sys.argv))