Last active
December 28, 2015 08:39
-
-
Save jvzr/7473113 to your computer and use it in GitHub Desktop.
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
#!/usr/local/bin/ruby | |
# -*- encoding: utf-8 -*- | |
require "rubygems" | |
require "mail" | |
require "fileutils" | |
require "daemons" | |
# I know I probably shouldn't use constants like that… | |
DEBUG = true | |
DELETE = true | |
# And most definitely not global variables | |
$log = "/Users/johndoe/log.txt" | |
$path = "/Users/johndoe/source/data" | |
$needs_sync = "/Users/johndoe/sync" | |
$needs_generate = "/Users/johndoe/generate" | |
FileUtils.touch($log) | |
# I don't see anything wrong with the following lines. | |
file_size = (File.size($log).to_f / 2**20) | |
if file_size > 0.1 | |
File.write(log, "") | |
end | |
Mail.defaults do | |
retriever_method :imap, | |
:address => "imap.mail.com", | |
:port => 993, | |
:user_name => "johndoe@mail.com", | |
:password => "ph4tpassword", | |
:enable_ssl => true | |
end | |
# OK, here it starts to get hairy. First, global variables, again… | |
# Also, no class, no sane logic, just plain "shell scripting" thinking translated into insanely coded Ruby | |
def set_dates | |
date = Time.now.utc | |
datetmz = Time.now | |
$year = date.strftime("%Y").to_s | |
$month = date.strftime("%02m").to_s | |
$day = date.strftime("%02d").to_s | |
$time = date.strftime("%02T").to_s | |
timetmz = datetmz.strftime("%02T").to_s | |
$now = "#{$year}/#{$month}/#{$day} #{timetmz}" | |
end | |
# This seems about right | |
def slugalize(text, separator = "-") | |
re_separator = Regexp.escape(separator) | |
result = text.to_s | |
result.gsub!(/[^\x00-\x7F]+/, "") | |
result.gsub!(/[^a-z0-9\-_\+]+/i, separator) | |
result.gsub!(/\./, "") | |
result.gsub!(/#{re_separator}{2,}/, separator) | |
result.gsub!(/^#{re_separator}|#{re_separator}$/, "") | |
result.downcase! | |
return result | |
end | |
# This doesn't seem good. My requirement is to reverse fill the log (latest on top) | |
def log(alert) | |
if DEBUG | |
set_dates | |
FileUtils.touch($log) | |
File.open($log, "r") do |orig| | |
File.unlink($log) | |
File.open($log, "w") do |new| | |
new.write "#{$now[5..-1]} - #{alert}\n" | |
new.write(orig.read()) | |
end | |
end | |
end | |
end | |
# OK. I had lots of trouble with these two. Middleman is a long process, | |
# and without doing some kind of process fork or multithreading, the whole | |
# daemon randomly crashes when it arrives here. I'm not sure it is good though. | |
def generate | |
pid = Process.fork do | |
File.delete($needs_generate) | |
log("Generating…") | |
middleman = Process.spawn("middleman build --clean", :chdir => "/Users/johndoe") | |
Process.wait | |
log("Generated.") | |
FileUtils.touch($needs_sync) | |
end | |
Process.detach(pid) | |
end | |
# Here too. s3cmd sync can take a very long time (4 minutes for instance). | |
def sync | |
pid = Process.fork do | |
File.delete($needs_sync) | |
log("Synchronizing…") | |
Dir.chdir("/Users/johndoe") do | |
Dir::mkdir("gzip") unless File.exists?("gzip") | |
FileUtils.rm_rf Dir.glob("gzip/*") | |
FileUtils.cp_r(Dir["build/*"], "gzip") | |
end | |
Dir.chdir("/Users/johndoe/gzip") do | |
`find . -iname "*.*" -type f -exec sh -c "gzip -n -c -9 "{}" > tmp && cat tmp > "{}"" ";"` | |
File.delete("tmp") | |
`find . -name ".DS_Store" -delete` | |
s3cmd = "/usr/local/bin/s3cmd" | |
opts = "-P --rr --delete-removed --guess-mime-type --no-check-md5 --no-preserve -H --add-header=Content-Encoding:gzip" | |
bucket = "s3://www.mybucket.com/" | |
in5minutes = "--add-header=Cache-control:max-age=300,must-revalidate" | |
in15minutes = "--add-header=Cache-control:max-age=900,must-revalidate" | |
in1day = "--add-header=Cache-control:max-age=86400,must-revalidate" | |
in8days = "--add-header=Cache-control:max-age=691200,must-revalidate" | |
sync = `#{s3cmd} sync #{opts} #{in8days} . #{bucket}` | |
sitemap = `#{s3cmd} put #{opts} #{in1day} sitemap.xml #{bucket}sitemap.xml` | |
feed = `#{s3cmd} put #{opts} #{in15minutes} feed.xml #{bucket}feed.xml` | |
archives = `#{s3cmd} put #{opts} --recursive #{in15minutes} archives #{bucket}` | |
index = `#{s3cmd} put #{opts} #{in5minutes} index.html #{bucket}index.html` | |
end | |
log("Synchronized.") | |
end | |
Process.detach(pid) | |
end | |
# This whole function seems right though. | |
def check_mail | |
emails = Mail.find_and_delete(mailbox: "INBOX", what: :first, count: 10, order: :asc) | |
if (emails.length == 0 ) | |
log("No email found.") | |
else | |
emails.each do |email, imap, uid| | |
if email.subject.empty? | |
email.skip_deletion | |
next | |
end | |
subject = email.subject | |
slug = slugalize(subject.dup) | |
if email.body.decoded.empty? | |
email.skip_deletion | |
next | |
end | |
body = email.body.decoded | |
kind = "post" | |
link = body.lines.first.split(/\s+/).find_all { |u| u =~ /^https?:/ }.join | |
if link.match(/^http/) | |
kind = "link" | |
body = body.lines.to_a[1..-1].join | |
end | |
log("#{subject} (#{kind})") | |
path = $path.dup | |
if kind == "link" | |
path << "/links" | |
else | |
path << "/posts" | |
end | |
path << "/%s-%s-%s-%s.markdown" % [$year, $month, $day, slug] | |
open(path, "w") do |str| | |
str << "---\n" | |
str << %Q|title: "#{subject}"\n| | |
if kind == "link" | |
str << "link: #{link}\n" | |
end | |
str << "date: %s-%s-%sT%s\n" % [$year, $month, $day, $time] | |
str << "---\n" | |
str << body.chomp! | |
end | |
url = "http://www.mybucket.com/" | |
url << "linked/" if kind == "link" | |
url << "#{year}/#{month}/#{slug}/" | |
twtsubj = truncate(subject, 115) | |
twtsubj.insert(0, "★ ") if kind == "post" | |
#Twitter.update("#{twtsubj} #{url}") | |
email.skip_deletion if !DELETE | |
end | |
FileUtils.touch($needs_generate) | |
end | |
end | |
############################ | |
log("Daemon started.") | |
# OK, finally, let me explain the whole "files" thing. As it crashed randomly, | |
# the only way to get the script to actually generate the site and sync it | |
# when the daemon starts again. | |
# If the whole thing doesn't crash, I don't think I'd need it then. | |
loop do | |
check_mail | |
if File.exists?($needs_generate) | |
generate | |
end | |
if File.exists?($needs_sync) | |
sync | |
end | |
sleep 300 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment