Skip to content
Snippets Groups Projects
run 4.58 KiB
Newer Older
  • Learn to ignore specific revisions
  • don's avatar
    don committed
    #!/usr/bin/python3
    import magic,os,pickle,re,subprocess
    
    basedir = '/home/pi/kiosk'
    remote = 'Kiosks:Kiosks/Testing'
    statusfile = os.path.join(basedir, 'state/statusfile')
    contentdir = os.path.join(basedir, 'content')
    slidedir   = os.path.join(basedir, 'slides')
    tmpdir     = os.path.join(basedir, 'tmp')
    synccommand = ['/usr/bin/rclone', 'sync', remote, contentdir]
    
    # File formats that "feh" can display directly with no processing
    directformats = [
      'JPEG image',
      'PNG image',
      'GIF image',
      'Netpbm image',
    ]
    
    # Empty the temporary working directory
    def cleantmp():
      try:
        tmpfiles = os.listdir(tmpdir)
        for f in tmpfiles:
          fpath = os.path.join(tmpdir, f)
          os.unlink(fpath)
      except:
        pass
    
    # Copy a file into the temporary directory
    def tmpcopy(filename):
      srcpath = os.path.join(contentdir, filename)
      dstpath = os.path.join(tmpdir,     filename)
      subprocess.call(['/bin/cp', '-p', '-f', srcpath, dstpath])
    
    # Move PNG files from temporary to slide directory
    # Returns a list of moved files, and cleans the temporary directory
    def tmpmove(moveall):
      tmpfiles = os.listdir(tmpdir)
      tmpfiles.sort()
      filelist = []
      for f in tmpfiles:
        srcpath = os.path.join(tmpdir,   f)
        if moveall or (f[-4:] == '.png'):
          dstpath = os.path.join(slidedir, f)
          subprocess.call(['/bin/mv', '-f', srcpath, dstpath])
          filelist += [f]
        else:
          os.unlink(srcpath)
      return(filelist)
    
    # Synchronize with cloud storage
    subprocess.call(synccommand)
    
    # Set up to read magic numbers and guess file types
    ms = magic.open(magic.NONE)
    ms.load()
    
    # Empty temporary directory
    cleantmp()
    
    # Read previous file status, if it exists
    try:
      stf = open(statusfile, 'rb')
      filestatus = pickle.load(stf)
      stf.close()
    except:
      filestatus = {}
    
    # Get list of content files
    files = os.listdir(contentdir)
    files.sort()
    
    # Slide files to preserve
    keepcontent = {}
    keepslides = {}
    
    # Examine all content files
    for f in files:
      filepath = os.path.join(contentdir, f)
      sb = os.stat(filepath)
      filetype = ms.file(filepath)
      processfile = True
      if f in filestatus:
        # Status record exists
        # Check size and modification time
        thisstatus = filestatus[f]
        if (thisstatus['s'] == sb.st_size) and (thisstatus['m'] == sb.st_mtime) and (thisstatus['t'] == filetype):
          # exact match, do not need to process this file
          print('exact', f)
          processfile = False
          # mark resulting slide files to save them
          for i in thisstatus['f']:
            keepslides[i] = True
        else:
          # something has changed
          print('changed', f)
          thisstatus['s'] = sb.st_size
          thisstatus['m'] = sb.st_mtime
          thisstatus['t'] = filetype
      else:
        # new file, no status record yet, so make one
        print('new', f)
        filestatus[f] = {}
        filestatus[f]['s'] = sb.st_size
        filestatus[f]['m'] = sb.st_mtime
        filestatus[f]['t'] = filetype
    
      # Active file, save status record
      keepcontent[f] = True
    
      # if this content file needs to be made into slide file(s)
      if processfile:
        # Figure out some useful paths
        tmppath  = os.path.join(tmpdir,   f)
        destpath = os.path.join(slidedir, f)
        direct = False
        for d in directformats:
          if d in filetype:
             direct = True
        if direct:
          # files that can be displayed directly just need to be copied into place
          print('direct', filepath)
          tmpcopy(f)
          subprocess.call(['/bin/cp', '-p', '-f', filepath, destpath])
          # keepslides[f] = True
        elif 'PDF document' in filetype:
          tmpcopy(f)
          subprocess.call(['/home/pi/kiosk/bin/file-pdf'])
        elif 'PostScript document' in filetype:
          tmpcopy(f)
          subprocess.call(['/home/pi/kiosk/bin/file-ps'])
        elif 'PowerPoint' in filetype or 'Microsoft Word' in filetype or 'Zip archive data' in filetype:
          tmpcopy(f)
          subprocess.call(['/home/pi/kiosk/bin/file-office'])
        elif 'ASCII text' in filetype:
          tmpcopy(f)
          subprocess.call(['/home/pi/kiosk/bin/file-text'])
        else:
          print('unknown', filepath)
          print(filetype)
        filelist = tmpmove(direct)
        filestatus[f]['f'] = filelist
        for i in filelist:
          keepslides[i] = True
    
    # final cleanup, delete obsolete slides
    # Get list of slide files
    files = os.listdir(slidedir)
    files.sort()
    for f in files:
      if f not in keepslides:
        os.unlink(os.path.join(slidedir, f))
        print('unlink slide', f)
    
    # Delete status records for obsolete content
    deletekeys = []
    for s in filestatus.keys():
      if s not in keepcontent:
        deletekeys += [s]
    
    for s in deletekeys:
      del filestatus[s]
      print('delete status', s)
    
    # Write new status file
    stf = open(statusfile, 'wb')
    pickle.dump(filestatus, stf)
    stf.close()