Can't send a message from xmpp4r? - ruby

I'm trying to test sending a message to one jid account by using xmpp4r:
require 'xmpp4r'
include Jabber
jid = JID::new('alice#wonderland.lit')
password = 'secr3t'
cl = Client::new(jid)
cl.connect('166.78.7.179')
cl.auth(password)
cl.send(Presence.new)
to = 'arthur#wonderland.lit'
subject = 'XMPP4R test'
body = 'Hi, this is a XMPP4R test'
m = Message::new( to, body ).set_type(:chat).set_id('1').set_subject(subject)
cl.send m
But I always get the following exception:
/home/subout/.rvm/gems/ruby-1.9.3-p374#subout/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:118:in `rescue in auth': closed stream (Jabber::ClientAuthenticationFailure)
from /home/subout/.rvm/gems/ruby-1.9.3-p374#subout/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:108:in `auth'
from send_message2.rb:9:in `<main>'

First of all, would you please add Jabber::debug = true setting
before cl.connect and post output here?
Secondly, it looks like there is a problem with XMPP server (are you sure it’s running at
'166.78.7.179'?)
And, the last but not the least, why do you decide
to use “obsolete” xmpp4r rather than it’s modern successor
Blather?

Related

Freeswitch ESL library

I would like understand the data format of Freeswitch ESL library method getBody and also from the ESl how to get the media bugs list on channel issuing the command api uuid_buglist .
My concern is that I can issue the command but how to read the data that comes out is my problem.
Please help.
esl_event_get_body() is a very simple wrapper function that returns event->body from an event.
To get the reply from your cmd you should use handle.last_sr_event->body after using esl_send_recv(&handle, cmd)
you can see my open source project, it is a auto dial project:
https://github.com/nwaycn/nway_ac
here is plain the message of hangup
con = ESLconnection(fs_ip, fs_esl_port, fs_esl_auth)
if con.connected():
thread.start_new_thread(AutoCall,(1,1))
e = con.events('plain','CHANNEL_HANGUP_COMPLETE')
while True:
ee = con.recvEvent()
#print ee
if ee:
my_number = ee.getHeader('Caller-Caller-ID-Number')
dest_number = ee.getHeader('Caller-Destination-Number')
SetNumberIdle(dest_number)
con.disconnect();
here is to call a phone
def CallOut(dial_string,call_number):
con = ESLconnection(fs_ip, fs_esl_port, fs_esl_auth)
if con.connected():
e = con.api(dial_string)
SetNumberBusy(call_number)
print e.getBody()
else:
print 'not Connected'
con.disconnect();

Good request from browser but bad request from ruby?

I'm using the google custom search api and I'm trying to access it through some ruby code:
Here is a snippet of the code
req = Typhoeus::Request.new("https://www.googleapis.com/customsearch/v1?key={my_key}&cx=017576662512468239146:omuauf_lfve&q=" + keyword, followlocation: true)
res = req.run
It appears that the body of the answer is this one:
<p>Your client has issued a malformed or illegal request. <ins>That’s all we know.</ins>
'
from /usr/local/lib/ruby/2.1.0/json/common.rb:155:in `parse'
from main.rb:20:in `initialize'
from main.rb:41:in `new'
from main.rb:41:in `<main>'
When I try to do the same thing from the browser it works like a charm. Even more confusing is that this same code worked 12 hours ago. I only changed the keyword that it should look for, however it started returning the error.
Any suggestions? I'm sure that I have enough credits for more requests
You probably have problems with special characters in your get parameter keyword. If you enter the URL in your browser, the brower adjusts these. However, for ruby you need to escape these characters, in such a way that a string like "sky line" becomes "sky+line" and so on. There is a utility function CGI::escape, which is used like this:
require 'cgi'
CGI::escape("sky line")
=> "sky+line"
Your fixed code would look something like this:
req = Typhoeus::Request.new("https://www.googleapis.com/customsearch/v1?key={my_key}&cx=017576662512468239146:omuauf_lfve&q=" + CGI::escape(keyword), followlocation: true)
res = req.run
However, since you're using Typhoeus anyway, you should be able to use its params parameter and let Typhoeus handle the escaping:
req = Typhoeus::Request.new(
"https://www.googleapis.com/customsearch/v1?&cx=017576662512468239146:omuauf_lfve",
followlocation: true,
params: {q: keyword, key: my_key}
)
res = req.run
There's more examples on Typhoeus' GitHub page.

I am trying to use Curl::Easy.http_put but have some issues with the data argument

I'm struggling with a ruby script to upload some pictures to moodstocks using their http interface
here is the code that I have so far
curb = Curl::Easy.new
curb.http_auth_types = :digest
curb.username = MS_API
curb.password = MS_SECRET
curb.multipart_form_post = true
Dir.foreach(images_directory) do |image|
if image.include? '.jpg'
path = images_directory + image
filename = File.basename(path, File.extname(path))
puts "Upload #{path} with id #{filename}"
raw_url = 'http://api.moodstocks.com/v2/ref/' + filename
encoded_url = URI.parse URI.encode raw_url
curb.url = encoded_url
curb.http_put(Curl::PostField.file('image_file', path))
end
end
and this is the error that I get
/Library/Ruby/Gems/2.0.0/gems/curb-0.8.5/lib/curl/easy.rb:57:in `add': no implicit conversion of nil into String (TypeError)
from /Library/Ruby/Gems/2.0.0/gems/curb-0.8.5/lib/curl/easy.rb:57:in `perform'
from upload_moodstocks.rb:37:in `http_put'
from upload_moodstocks.rb:37:in `block in <main>'
from upload_moodstocks.rb:22:in `foreach'
from upload_moodstocks.rb:22:in `<main>'
I think the problem is in how I give the argument to the http_put method, but I have tried to look for some examples of Curl::Easy.http_put and have found nothing so far.
Could anyone point me to some documentation regarding it or help me out on this.
Thank you in advance
There are several problems here:
1. URI::HTTP instead of String
First, the TypeError you encounter comes from the fact that you pass a URI::HTTP instance (encoded_url) as curb.url instead of a plain Ruby string.
You may want to use encoded_url.to_s, but the question is why do you do this parse/encode here?
2. PUT w/ multipart/form-data
The second problem is related to curb. At the time of writing (v0.8.5) curb does NOT support the ability to perform a HTTP PUT request with multipart/form-data encoding.
If you refer to the source code you can see that:
the multipart_form_post setting is only used for POST requests,
the put_data setter does not support Curl::PostField-s
To solve your problem you need an HTTP client library that can combine Digest Authentication, multipart/form-data and HTTP PUT.
In Ruby you can use rufus-verbs, but you will need to use rest-client to build the multipart body.
There is also HTTParty but it has issues with Digest Auth.
That is why I greatly recommend to go ahead with Python and use Requests:
import requests
from requests.auth import HTTPDigestAuth
import os
MS_API_KEY = "kEy"
MS_API_SECRET = "s3cr3t"
filename = "sample.jpg"
with open(filename, "r") as f:
base = os.path.basename(filename)
uid = os.path.splitext(base)[0]
r = requests.put(
"http://api.moodstocks.com/v2/ref/%s" % uid,
auth = HTTPDigestAuth(MS_API_KEY, MS_API_SECRET),
files = {"image_file": (base, f.read())}
)
print(r.status_code)

Connecting to Yahoo! mail from Ruby

I try to connect to mail Yahoo! account from Ruby using both net/imap and net/pop. But I randomly get error EOFile (from IMAP) or Connection Refused/Reset by peer (from POP). Has anybody tried to connect to Yahoo! Mail and had some experiences about it?
There's a bug in ruby's net/imap library that is exposed when connecting to Yahoo.
The fix is straightforward and described here:
http://redmine.ruby-lang.org/issues/4509
Basically, edit imap.rb and change the inner loop of search_response method from:
token = lookahead
case token.symbol
when T_CRLF
break
when T_SPACE
shift_token
end
data.push(number)
to:
token = lookahead
case token.symbol
when T_CRLF
break
when T_SPACE
shift_token
else
data.push(number)
end
then test with the following code:
require 'net/imap'
Net::IMAP.debug = true
conn = Net::IMAP.new('imap.mail.yahoo.com', 143, false)
conn.instance_eval { send_command('ID ("GUID" "1")') }
conn.authenticate('LOGIN', ARGV[0], ARGV[1] )
conn.select("INBOX")
uids = conn.uid_search(['ALL'])
puts uids.join(',')
conn.logout
conn.disconnect

Ruby: Dynamically defining classes based on user input

I'm creating a library in Ruby that allows the user to access an external API. That API can be accessed via either a SOAP or a REST API. I would like to support both.
I've started by defining the necessary objects in different modules. For example:
soap_connecton = Library::Soap::Connection.new(username, password)
response = soap_connection.create Library::Soap::LibraryObject.new(type, data, etc)
puts response.class # Library::Soap::Response
rest_connecton = Library::Rest::Connection.new(username, password)
response = rest_connection.create Library::Rest::LibraryObject.new(type, data, etc)
puts response.class # Library::Rest::Response
What I would like to do is allow the user to specify that they only wish to use one of the APIs, perhaps something like this:
Library::Modes.set_mode(Library::Modes::Rest)
rest_connection = Library::Connection.new(username, password)
response = rest_connection.create Library::LibraryObject.new(type, data, etc)
puts response.class # Library::Response
However, I have not yet discovered a way to dynamically set, for example, Library::Connection based on the input to Library::Modes.set_mode. What would be the best way to implement this functionality?
Murphy's law prevails; find an answer right after posting the question to Stack Overflow.
This code seems to have worked for me:
module Library
class Modes
Rest = 1
Soap = 2
def self.set_mode(mode)
case mode
when Rest
Library.const_set "Connection", Class.new(Library::Rest::Connection)
Library.const_set "LibraryObject", Class.new(Library::Rest::LibraryObject)
when Soap
Library.const_set "Connection", Class.new(Library::Soap::Connection)
Library.const_set "LibraryObject", Class.new(Library::Soap::LibraryObject)
else
throw "#{mode.to_s} is not a valid Library::Mode"
end
end
end
end
A quick test:
Library::Modes.set_mode(Library::Modes::Rest)
puts Library::Connection.class == Library::Rest::Connection.class # true
c = Library::Connection.new(username, password)

Resources