Last active
August 24, 2020 13:54
-
-
Save xionon/9a81fa6a5cba2e905dca41b7a16cf844 to your computer and use it in GitHub Desktop.
Simple program to watch a floppy drive (A:) for new disks, and copy the images or files from them
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'fileutils' | |
require 'win32-sound' | |
FILE_UTILS_NOOP = false | |
IMAGE_TYPES_REGEX = /.(jpg|gif|jpeg|png|mpg)$/i | |
DOC_TYPES_REGEX = /(?<!mavica).(doc|txt|docx|xls|xlsx|html|htm|zip)$/i | |
IMAGES_DIRECTORY = "C:/Users/Alec/Documents/floppys/images" | |
OTHER_DIRECTORY = "C:/Users/Alec/Documents/floppys/docs" | |
ALWAYS_IGNORE_REGEX = /(System Volume Information|.411|MAVICA.htm)$/i | |
FAILURE_WAV = "C:/Windows/Media/Windows Hardware Fail.wav" | |
DONE_WAV = "C:/Windows/Media/Windows Hardware Remove.wav" | |
INSERT_WAV = "C:/Windows/Media/Windows Hardware Insert.wav" | |
def play(sound) | |
case sound | |
when :insert | |
Win32::Sound.play(INSERT_WAV, Win32::Sound::FILENAME) | |
when :failure | |
Win32::Sound.play(FAILURE_WAV, Win32::Sound::FILENAME) | |
when :done | |
Win32::Sound.play(DONE_WAV, Win32::Sound::FILENAME) | |
else | |
Win32::Sound.play("SystemAsterisk", Win32::Sound::ALIAS) | |
end | |
end | |
def log(msg) | |
puts msg unless msg == @last_msg | |
@last_msg = msg | |
end | |
def safely_import(file,destination) | |
FileUtils.cp(file, destination, verbose: true, preserve: true, noop: FILE_UTILS_NOOP) | |
rescue => e | |
log "Error importing #{file}!" | |
log e | |
end | |
def import(files, original_destination) | |
destination = original_destination | |
attempts = 0 | |
while Dir.exist?(destination) && !Dir.empty?(destination) | |
attempts += 1 | |
destination = "%s-%03d" % [original_destination, attempts] | |
end | |
FileUtils.mkdir(destination, verbose: true, noop: FILE_UTILS_NOOP) | |
begin | |
FileUtils.cp_r(files, destination, verbose: true, preserve: true, noop: FILE_UTILS_NOOP) | |
rescue => e | |
play(:failure) | |
log e | |
log "Error attempting bulk import; attempting safe import" | |
files.each { |file| safely_import(file, destination) } | |
end | |
end | |
def process_import(list, destination) | |
if list[0] | |
destination_date = File.stat(list[0]).birthtime | |
destination = File.join(destination, "%s-%s-%s" % [destination_date.year.to_s, destination_date.month.to_s, destination_date.day.to_s]) | |
import(list, destination) | |
end | |
end | |
def main | |
while(true) do | |
last_import ||= nil | |
ignored_types ||= [] | |
files = Dir.glob("A:/**").sort.reject { |f| f =~ ALWAYS_IGNORE_REGEX } rescue nil | |
if files.nil? || files == last_import | |
msgs = ["Waiting."] | |
if files.nil? | |
msgs << "Drive empty." | |
# rarely, two disks in a row will look the same. resetting the last import prevents skipping a disk | |
last_import = nil | |
end | |
msgs << "No previous run detected." if last_import.nil? || last_import.empty? | |
msgs << "Disk unchanged." if files == last_import && files.nil? == false | |
msgs << "\n" | |
log msgs.join(" ") | |
sleep 3 | |
else | |
start_time = Time.now | |
if !files.nil? && last_import != files | |
play(:insert) | |
log "New files detected!\nFiles: #{files}\nLast: #{last_import}" | |
end | |
log "Starting import" | |
last_import = files | |
images = files.select {|f| f =~ IMAGE_TYPES_REGEX } | |
docs = files.select {|f| f =~ DOC_TYPES_REGEX } | |
ignored = files.reject {|f| f =~ IMAGE_TYPES_REGEX || f =~ DOC_TYPES_REGEX} | |
ignored_types = (ignored_types + ignored.map{|f| File.extname(f)}).uniq | |
log "Ignoring types: #{ignored_types}" | |
log "Ignoring #{ignored.join(" ")}" | |
process_import(images, IMAGES_DIRECTORY) | |
process_import(docs, OTHER_DIRECTORY) | |
log "Finished in #{Time.now - start_time} seconds\n\n" | |
play(:done) | |
end | |
end | |
end | |
if __FILE__ == $PROGRAM_NAME | |
main() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment