views:

164

answers:

3

My wife enjoys it when I use my geek abilities to be "romantic" so I had an idea for a ruby script to install on her Mac that would send her quotes and little notes from me throughout the day. I already figured out that I'll be using GeekTool to run a script in the background and I'll use growlnotify to display the messages. Now what I need is a way to update the script from the web in case I change it. I know basically nothing about ruby other than how to interact with the console.

I have 2 goals: 1) Have an XML file with messages. This needs to be update-able from the internet, but be local in case she doesn't have a network connection. 2) Update the script itself from the internet in case I find bugs or want to improve it.

Now I know that I could obviously just manually update the script on her Mac if I wanted to, but I figured this would be a good way to learn some more advanced ruby.

Priority 1 would be the XML file, be able to download a new version if it changes. What ruby things can I use to download a file and save it to a certain place locally?

I have used hpricot before, would that be a good way to go?

Note: My wife's mac is a Macbook, running Leopard (but maybe 10.4, not 100% sure).

EDIT

If anyone is interested in the first version of the script you can find it here

p.s. --> the first version of the script doesn't update itself actually, it just updates the messages.xml file and that's all.

+1  A: 
require 'net/http'

Net::HTTP.start("your.webhost.com") { |http|
  resp = http.get("/messages/messages.xml")
  open("messages.xml", "wb") { |file|
    file.write(resp.body)
  }
}

Something like that ought to work. You can download the Ruby script too, then call.

exec("ruby script2.rb")
#no further lines in script1 will execute
MattMcKnight
Ok, so as far as priority 2, could I have a second ruby script that gets called by the first ruby script AFTER the first ruby script has downloaded and saved the second ruby script?
Pselus
When you say "No further lines in script1 will execute" do you mean at all or until the first script finishes?i.e. can I have 2 different "exec" lines within the same script?
Pselus
I mean at all...one exec line. You'd have to make the other script into a module or a class and load it in if you wanted it access it without an exec.
MattMcKnight
+1  A: 

Won't your wife see you coming if you have a file with xml messages coming randomly through the day ? Wouldn't it be better for you to send a message and for her to receive it instantly ?

You could use the XMPP protocol to do so.
Your wife's application connects itself to the XMPP server; you too. And you can send her a message whenever you want to.
You could even force the messages to be sent with some distance in time between each one of them.
So when she's going nomad without any internet connexion and you know it, you send her 3 or 4 messages by advance. And she'll receive them later.

For the script update, it's a similar problem than what you'd have with any website server.
So I'd open a SSH port on her machine and use capistrano to deploy the most recent version of the application.

Damien MATHIEU
I want the script to run randomly throughout the day. Possibly every 15 minutes display a message to her. These will be predefined messages that can repeat, but I want to be able to add to the messages whenever I feel like it without having access to her machine.
Pselus
Well I'd go for XMPP anyway :)
Damien MATHIEU
A: 

How long are the messages? XML might be a little overkill if they're short. Why not just use a text file with one message per line?

#!/usr/bin/env ruby
require 'open-uri'

def growl_msg(msg)
  %x{growlnotify -m "#{msg}"}
end

def read_msg
  begin
    f = open("http://www.yoursite.com/messages.txt").read
    File.open("messages.txt", 'w') {|f| f.write(f) } #write local copy
  rescue
    f = File.open("messages.txt").read
  end
  growl_msg(f.split("\n").sort_by{rand}[0]) #growl a random line
end

while true do
  read_msg
  sleep(15*60) # 15 minutes between messages
end

Using GeekTool to run the script is probably not necessary either. You can just start the script with nohup myscript.rb and it will keep running until you kill the process.

jhickner