Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

James Robertson http://www.r0bertson.co.uk

« Newer Snippets
Older Snippets »
Showing 11-20 of 103 total

Converting a numerical string into an array

irb(main):097:0> c = "080629".scan(/\d\d/)
=> ["08", "06", "29"]

Make your own IM bot in Ruby

The following code was copied from the article 'Make your own IM bot in Ruby, and interface it with your Rails app' [rubypond.com].

installation:
git clone git://github.com/ln/xmpp4r.git xmpp4r
cd xmpp4r
rake gem:install
sudo gem install xmpp4r-simple


connect:
require 'rubygems'  
require 'xmpp4r-simple'
messenger = Jabber::Simple.new('my-bot@gmail.com', "bot-password")

send:
messenger.deliver("a-real-person@gmail.com", "Why hello there Mr. Person, your bot is here now!") 

listen:
while true
  messenger.received_messages do |msg|  
    puts msg.body  
    messenger.deliver("a-real-person@gmail.com", "Got your message, thanks!")  
  end  
  sleep 2  
end

at your service:
require 'rubygems'  
require 'xmpp4r-simple'
messenger = Jabber::Simple.new('my-bot@gmail.com', "bot-password")
while true
  messenger.received_messages do |msg|
    user = User.find_by_im_name(msg.from)
    if user
      case msg.body
      when /^help /i
        messenger.deliver(msg.from, "Valid commands are......")  
      when /^status /i
        user.status = msg.body.sub(/^status /i)
        user.save
        messenger.deliver(msg.from, "Thanks #{user.first_name}, your status has been updated")  
      when /^balance\?/i
        messenger.deliver(msg.from, "#{user.first_name}, your current remaining balance is #{user.remaining_balance}")  
      else
        messenger.deliver(msg.from, "Sorry #{user.first_name}, I didn't understand that. Message me with 'help' for a list of commands")  
      end
    else
      messenger.deliver(msg.from, "Sorry, but we've not got this account registered on our system. Sign-up or update your details at http://www.mysite.com/")  
    end    
  end  
  sleep 2  
end

Using Bluetooth to control Asterisk calls.

Redirect an Asterisk call

    de61.old_status = get_status(de61.file) # found is either true or false
    de61.old_location = get_location(de61.file) # location is either 'at home', 'gone to bed' or 'asleep'
    
    while count < 1

      puts 'old status : ' + de61.old_status.to_s
      de61.new_status = check_device(de61.id, de61.name)
      puts 'new_status: ' + de61.new_status.to_s


      if de61.new_status and de61.old_status
        if de61.old_status == false
          puts 'connecting to the bluetooth device ...'
          Thread.new{`rfcomm connect 0 #{de61.id}`}
          sleep 12
        end
        de61.new_location = check_location(de61.id) 
      end
      
      puts 'old_location: ' + de61.old_location.to_s
      puts 'new_location: ' + de61.new_location.to_s
      update_status(de61.project, de61.new_status, de61.new_location) if ((de61.old_status != de61.new_status.to_s) or (de61.old_location != de61.new_location)) 
        
      mystatus = ''
      
      if  (not de61.old_status == de61.new_status) then
        if (de61.new_status.to_s == 'true') then
            mystatus = ' has entered the building'
            callto('SIP/line1')
        elsif  (de61.new_status == false) then
          mystatus = ' has left the building'
          callto('SIP/07736668666@sipgate')
        end
        puts 'updating in or out the building'
        ms = MyStatus.new(mystatus)
      elsif (de61.old_location.to_s != de61.new_location.to_s)
        if de61.old_location.match(/sleep/) and de61.new_location.match(/home|bed/) and not old_mystatus.match(/awoken/) then
          mystatus = ' has awoken'
        elsif (de61.old_location.match(/home|bed/)) and de61.new_location.match(/sleep/) 
          mystatus = ' has gone to sleep'           
        elsif (de61.old_location.match(/home/)) and de61.new_location.match(/bed/) 
          mystatus = ' has gone to bed'
        elsif de61.old_location.match(/bed/) and de61.new_location.match(/home/) 
          mystatus = ' has got out of bed'
        end
        puts 'updating home location'
        ms = MyStatus.new(mystatus) if mystatus != ''
      end


      de61.old_location = de61.new_location
      de61.new_location = 'at home'
      de61.old_status = de61.new_status
      old_mystatus = mystatus
      sleep 7
    end
  end
    
  def callto(dialstring)
    file = File.new('/etc/asterisk/ruby/call-to.txt','w')
    file.puts 'Dial(' + dialstring + ')'
    file.close
  end


file: extensions.conf
exten => 5168666,n,ReadFile(dialplan1=/etc/asterisk/ruby/call-to.txt,130)
exten => 5168666,n,Exec(${dialplan1})

Using Ruby to detect Bluetooth proximity

This Ruby script uses the hcitool and rfcomm to detect the proximity of a bluetooth enabled mobile phone. The signal strength in this script will return a value from 0 to 10, 0 is near and 10 is far, otherwise if there is no connection it will keep on trying.

deviceid = '00:12:D1:E6:57:BE' 
range = ''
count = 0
while count < 1
  # assuming the bt device is already connected get the signal strength value.
  range = `hcitool rssi #{deviceid}`.chomp
  if  range.length > 0
    puts range[/\w+$/]
  else
    puts 'connecting to the bluetooth device ...'
    Thread.new{`rfcomm connect 0 #{deviceid}`}
  end
	
  sleep 7
end



warning (11-Jul-2008): I've found Thread.new to be causing a problem, it appears not to remove itself from the process queue when it is no longer required.

Executing a Ruby script from Asterisk

To run a Ruby script from Asterisk you need 2 things 1) an extension to run the script from 2) a Ruby script.

* Preparing the evironment *
1) create a script directory for Asterisk and ensure it has permission to run the scripts.

* Running the script *
1) Dial extension 3000
2) Listen to the voice say 'hello world'
3) Observe a new output.txt file has been created containing the message 'hello world!'

file: hello-world.rb
#!/usr/bin/ruby

#file : hello-world.rb

file = File.new('/etc/asterisk/ruby/output.txt','w')
file.puts 'hello world!'
file.close

file: extensions.rb
exten => 3000,1,Playback(hello-world)
exten => 3000,n,System(/etc/asterisk/ruby/./hello-world.rb)
exten => 3000,n,Hangup


file: output.txt
hello world!

Adding helpful error messages to your Ruby code

This Ruby code raises an error if the XPath query fails because the attribute being queried did not exist for the given element.

  def map_pattr(node, fieldx, valuex)
    begin
    parameter = node.root.elements["parameter[@field='#{fieldx}']"]
    parameter.add_attribute('value', valuex)
    parameter
    
    rescue
      puts 'feedpopulated.rb: map_attr() the field ' + fieldx + ' was not found in params.'
      raise
    end
  end

Notice that a raise statement is used to ensure that the system error message is raised and any further code execution is halted.

Without adding a customized helpful message I would be left scratching my head trying to work out what the following system error message meant.
./feedpopulated.rb:27:in `map_pattr': undefined method `add_attribute' for nil:NilClass (NoMethodError)
     from ./feedpopulated.rb:51:in `create_record'
     from ./feedpopulated.rb:49:in `each'
     from ./feedpopulated.rb:49:in `create_record'
     from ./recordx.rb:91:in `call_create'
     from ./s3fileuploader_handler.rb:14:in `call'
     from ./s3fileuploader_handler.rb:40:in `invoke'
     from ./uploadtwitteraudio.rb:22:in `initialize'
     from /usr/lib/ruby/1.8/rexml/element.rb:890:in `each'
     from /usr/lib/ruby/1.8/rexml/xpath.rb:53:in `each'
     from /usr/lib/ruby/1.8/rexml/element.rb:890:in `each'
     from ./uploadtwitteraudio.rb:18:in `initialize'
     from ./uploadtwitteraudio.rb:72:in `new'
     from ./uploadtwitteraudio.rb:72


Reference: Programming Ruby: The Pragmatic Programmer's Guide - Exceptions, Catch, and Throw [ruby-doc.org]

Creating a bucket in Amazon S3 through an irb session

1) Log into an irb session, and enter your S3 login details.
require 'rubygems'
require 'aws/s3'

  AWS::S3::Base.establish_connection!(
    :access_key_id     => 'REPLACE_ME',
    :secret_access_key => 'REPLACE_ME'
  )

output:
=> #<AWS::S3::Connection:0xb75e0594 @http=#<Net::HTTP s3.amazonaws.com:80 open=false>, @secret_access_key="", @options={:server=>"s3.amazonaws.com", :access_key_id=>"", :port=>80, :secret_access_key=>"", :persistent=>true}, @access_key_id="19S45GYAGWK8DC2B8VG2">

2) Browse the existing buckets.
AWS::S3::Service.buckets

output:
=> [#<AWS::S3::Bucket:0xb75cc850 @object_cache=[], @attributes={"name"=>"ogg.twitteraudio.com", "creation_date"=>Sat Apr 26 10:40:16 UTC 2008}>, #<AWS::S3::Bucket:0xb75cc83c @object_cache=[], @attributes={"name"=>"t1000", "creation_date"=>Fri Apr 25 21:35:21 UTC 2008}>, #<AWS::S3::Bucket:0xb75cc814 @object_cache=[], @attributes={"name"=>"t2000", "creation_date"=>Fri Apr 25 21:53:15 UTC 2008}>]

3) Browse the buckets in a programmatical way.
AWS::S3::Service.buckets.each {|b| puts b.name}

output:
ogg.twitteraudio.com
t1000
t2000


4) Add a new bucket called t3000.
AWS::S3::Bucket.create('t3000')

output:
=> true

5) Observe adding the bucket again doesn't cause an error.
AWS::S3::Bucket.create('t3000')

output:
=> true

6) View the buckets again.
AWS::S3::Service.buckets

output:
=> [#<AWS::S3::Bucket:0xb75cc850 @object_cache=[], @attributes={"name"=>"ogg.twitteraudio.com", "creation_date"=>Sat Apr 26 10:40:16 UTC 2008}>, #<AWS::S3::Bucket:0xb75cc83c @object_cache=[], @attributes={"name"=>"t1000", "creation_date"=>Fri Apr 25 21:35:21 UTC 2008}>, #<AWS::S3::Bucket:0xb75cc814 @object_cache=[], @attributes={"name"=>"t2000", "creation_date"=>Fri Apr 25 21:53:15 UTC 2008}>]

Note: You would expect t3000 to be in there however it didn't appear possibly because of the bucket permissions.

7) Let's then look for bucket t3000.
t3000 = AWS::S3::Bucket.find('t3000')

output:
=> #<AWS::S3::Bucket:0xb76df724 @object_cache=[], @attributes={"prefix"=>nil, "name"=>"t3000", "marker"=>nil, "max_keys"=>1000, "is_truncated"=>false, "xmlns"=>"http://s3.amazonaws.com/doc/2006-03-01/"}>

8) Now that we've found the bucket let's upload a text file called works.txt.
file = "works.txt"

output:
=> "works.txt"
AWS::S3::S3Object.store(file, open(file), 't3000', :access => :public_read)

output:
=> #<AWS::S3::S3Object::Response:0x-608926458 200 OK>

9) Setting the file access to :public_read allows us to view the file from the http location http://t3000.s3.amazonaws.com/works.txt

References:
http://amazon.rubyforge.org/
upload_to_s3 - Ruby S3 upload client [dzone.com]

*update: 14:30 30 April 2008 *
I didn't use Bucket.objects(:reload) which is the reason why the bucket t3000 didn't show up with the statement Service.buckets

Reference: spatten design - Amazon S3, Ruby and Rails slides [spattendesign.com]

Using ruby to upload multiple files to Amazon S3

This ruby code builds upon the code S3 upload client for Ruby [dzone.com] by reading the account details and file details from XML files.

#!/usr/bin/env ruby
#file : rubys3file2upload.rb

require 'rubygems'
require 'aws/s3'
require 'rexml/document'
include REXML

class S3FileUpload

  def initialize(xml_accounts_file, xml_upload_file)
    initialize_account(xml_accounts_file)
    main(xml_upload_file)
  end

  def initialize_account(accounts_file)

    file = File.new(accounts_file)
    doc = Document.new(file)

    account = doc.root.elements['records/access']
    h = Hash.new
    h[:access_key_id] = account.elements['key_id'].text.to_s
    h[:secret_access_key] = account.elements['secret'].text.to_s
    AWS::S3::Base.establish_connection!(h)

  end

  def main(xml_upload_file)
    file = File.new(xml_upload_file)
    doc = Document.new(file)
puts doc
    doc.root.elements.each('records/file') do |f|
      local_file = f.elements['local'].text.to_s
      bucket = f.elements['bucket'].text.to_s
      mime_type = f.elements['mime_type'].text.to_s
      upload(local_file, mime_type, bucket)
    end
  end

  def upload(local_file, mime_type, bucket)

    base_name = File.basename(local_file)

    puts "Uploading #{local_file} as '#{base_name}' to '#{bucket}'"

    AWS::S3::S3Object.store(
      base_name,
      File.open(local_file),
      bucket,
      :content_type => mime_type,
      :access => :public_read
    )

    puts "Uploaded!"
  end

end

if __FILE__ == $0
  s3fu = S3FileUpload.new('s3accounts.xml', 's3files2upload.xml')
end


file: s3accounts.xml
<s3accounts>
  <summary/>
  <records>
    <access id="100"><name>REPLACE_ME</name><key_id>REPLACE_ME</key_id><secret>REPLACE_ME</secret></access>
  </records>
</s3accounts>


file: s3files2upload.xml
<s3files2upload>
  <summary/>
  <records>
    <file>
      <local>autocomplete.html</local>
      <bucket>t2000</bucket>
      <mime_type>text/html</mime_type>
    </file>
    <file>
      <local>autocomplete2.html</local>
      <bucket>t2000</bucket>
      <mime_type>text/html</mime_type>
    </file>
    <file>
      <local>autocomplete3.html</local>
      <bucket>t2000</bucket>
      <mime_type>text/html</mime_type>
    </file>
  </records>
</s3files2upload>


Note: The file given the correct permission could be read from http://t2000.s3.amazonaws.com/autocomplete.html

Reference: http://amazon.rubyforge.org/

Redirect a URL with Ruby CGI

#!/usr/bin/ruby

require 'cgi'

cgi = CGI.new
print cgi.header({'Status' => '302 Moved', 'location' =>  'http://www.wired.com'})

or
url = 'http://www.wired.com/'
print cgi.header({'status'=>'REDIRECT', 'Location'=>url})


References:
RE: cgi redirect [nagaokaut.ac.jp]
Ruby/CGI - assari [mokehehe.com]
HTTP/1.1: Status Code Definitions [w3.org]

Converting text to SVG

First of all the Ruby code reads the text, splits it into an array and then saves it in XML format.
require 'rexml/document'
include REXML

a = "Open source is a development method for software that harnesses the power of distributed peer 
review and transparency of process. The promise of open source is better quality, higher reliability, 
more flexibility, lower cost, and an end to predatory vendor lock-in.".split(' ') 

doc = Document.new
doc.add_element('text')
oline = Element.new('line')

char_count = 0
a.each do |word|
  
  oword = Element.new('word')
  oword.text = word.to_s
  oword.add_attribute('length',char_count)
  oline << oword 
  char_count += word.length
  
  if char_count > 50
    doc.root << oline
    oline = Element.new('line')
    char_count = 0
  end
end
doc.root << oline
puts char_count
puts doc

Here's a sample of the XML created
<text>
  <line>
    <word length='0'>Open</word><word length='4'>source</word><word length='10'>is</word>
    <word length='12'>a</word><word length='13'>development</word><word length='24'>method</word>
    <word length='30'>for</word><word length='33'>software</word><word length='41'>that</word>
    <word length='45'>harnesses</word>
  </line>
  <line>
    <word length='0'>the</word><word length='3'>power</word>
    <word length='8'>of</word><word length='10'>distributed</word><word length='21'>peer</word>
    <word length='25'>review</word><word length='31'>and</word><word length='34'>transparency</word>
    <word length='46'>of</word><word length='48'>process.</word>
  </line>
  <line>
    <word length='0'>The</word>
    <word length='3'>promise</word><word length='10'>of</word><word length='12'>open</word>
    <word length='16'>source</word><word length='22'>is</word><word length='24'>better</word>
    <word length='30'>quality,</word><word length='38'>higher</word><word length='44'>reliability,</word>
  </line>
  <line>
    <word length='0'>more</word><word length='4'>flexibility,</word><word length='16'>lower</word>
    <word length='21'>cost,</word><word length='26'>and</word><word length='29'>an</word>
    <word length='31'>end</word><word length='34'>to</word><word length='36'>predatory</word>
    <word length='45'>vendor</word>
  </line>
  <line>
    <word length='0'>lock-in.</word>
  </line>
</text>

The XML is then transformed to SVG using the following XSL file
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output encoding="UTF-8"
            method="xml"
            indent="yes"/>
            
  <xsl:template match="text">
    <svg xmlns="http://www.w3.org/2000/svg" width="100%"
                  xmlns:xlink="http://www.w3.org/1999/xlink" >
      <g id="sketch" class="sketch">
        <xsl:apply-templates select="line"/>
      </g>
    </svg>
  </xsl:template>
  
  <xsl:template match="line">
    <xsl:variable name="xfactor">12</xsl:variable>
    <xsl:variable name="yfactor">20</xsl:variable>
    <xsl:variable name="pos" select="position()"></xsl:variable>
    <xsl:apply-templates select="word">
      <xsl:with-param name="xfactor" select="$xfactor"></xsl:with-param>
      <xsl:with-param name="y" select="$pos * $yfactor + 10"></xsl:with-param>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="word">
    <xsl:param name="xfactor"/>
    <xsl:param name="y"/>
    <text xmlns="http://www.w3.org/2000/svg" font-size="12pt" x="{@length * $xfactor +10}" y="{$y}" id="t1"><xsl:value-of select="."/></text>
  </xsl:template>
</xsl:stylesheet>

The final SVG output [twitxr.com] shows 5 lines of text with each word as a separate SVG text element.
« Newer Snippets
Older Snippets »
Showing 11-20 of 103 total