asciinema.org/app/workers/snapshot_worker.rb
2013-06-14 00:11:30 +02:00

107 lines
2.5 KiB
Ruby

require 'tempfile'
class SnapshotWorker
def perform(asciicast_id)
begin
@asciicast = Asciicast.find(asciicast_id)
prepare_files
convert_to_typescript
delay = (@asciicast.duration / 2).to_i
delay = 30 if delay > 30
snapshot = capture_terminal(delay)
@asciicast.snapshot = snapshot
@asciicast.save!
rescue ActiveRecord::RecordNotFound
# oh well...
ensure
cleanup
end
end
def prepare_files
log "preparing files..."
if RUBY_VERSION < '1.9'
in_data_file = Tempfile.new('asciiio-data')
else
in_data_file = Tempfile.new('asciiio-data', :encoding => 'ascii-8bit')
end
in_data_file.write(@asciicast.stdout.read)
in_data_file.close
@in_data_path = in_data_file.path
if RUBY_VERSION < '1.9'
in_timing_file = Tempfile.new('asciiio-timing')
else
in_timing_file = Tempfile.new('asciiio-timing', :encoding => 'ascii-8bit')
end
in_timing_file.write(@asciicast.stdout_timing.read)
in_timing_file.close
@in_timing_path = in_timing_file.path
@out_data_path = @in_data_path + '.ts'
@out_timing_path = @in_timing_path + '.ts'
end
def convert_to_typescript
log "converting to typescript..."
system "bash -c './script/convert-to-typescript.sh " +
"#{@in_data_path} #{@in_timing_path} " +
"#{@out_data_path} #{@out_timing_path}'"
raise "Can't convert asciicast ##{@asciicast.id} to typescript" if $? != 0
end
def capture_terminal(delay)
log "capturing terminal output..."
capture_command =
"scriptreplay #{@out_timing_path} #{@out_data_path}; sleep 10"
command = "bash -c 'ASCIICAST_ID=#{@asciicast.id} " +
"COLS=#{@asciicast.terminal_columns} " +
"LINES=#{@asciicast.terminal_lines} " +
"COMMAND=\"#{capture_command}\" " +
"DELAY=#{delay} ./script/capture.sh'"
lines = []
pid, stdin, stdout, stderr = open4(command)
while !stdout.eof?
lines << stdout.readline
end
Process.waitpid pid
status = $?.exitstatus
if status != 0
log "Error capturing output: #{lines.join.inspect}", :error
raise "Can't capture output of asciicast ##{@asciicast.id}"
end
lines.join('')
end
def cleanup
log "cleaning up..."
FileUtils.rm_f([
@in_data_path,
@in_timing_path,
@out_data_path,
@out_timing_path
].compact)
end
private
def log(text, level = :info)
Rails.logger.send(level, "SnapshotWorker: #{text}")
end
end