Back to site
Since 2004, our University project has become the Internet's most widespread web hosting directory. Here we like to talk a lot about web servers, web development, networking and security services. It is, after all, our expertise. To make things better we've launched this science section with the free access to educational resources and important scientific material translated to different languages.

Kreiranje beleški u Evernote kroz Ruby

Creating a Note in Evernote from Ruby

Nedavno smo imali priliku da kreiramo beleške u Evernote kroz Evernote API . Bile su to beleške koje su se razlikovale od korišćenja drugih APIs, upravo zbog toga jer Evernote koristi "Thrift" umesto XML/JSON-RPC kao i mnoge druge web aplikacije.

Kao i svake integracije, postoji nekoliko "gotchas" sa ovim. Konkretno, mi smo pronašli da je Ruby orijentisana dokumentacija na Internetu nepotpuna. Osim toga, tu su i glavni izazovi:

  • Mi volimo da simuliramo korisnika koji se preusmerava i autorizujemo aplikaciju u našim integracionim testovima, ali da postignemo sesiju kao da je korisnik to uradio je komplikovano.
  • API ima veliki Java-like osecaj, što nije bilo prirodno uklapanje za Rubi idiome
  • Sadržaji beleški treba da budu završeni u posebnom XML, koja je dokumentovana, ali nije prva stvar koju možete pronaći kada potražite pomoć na Google.
  • Izuzeci odbačeni iz API su šifrirani u početku, dok ne saznate kako da dobijete informacije koje želite od njih.

Bez daljeg odlaganja, u nastavku je pun izvorni kod:

require 'oauth' require 'evernote-thrift' #this is for testing. in production, it's www.evernote.com base = "https://sandbox.evernote.com" # given to you by Evernote key = "developer-key-from-evernote" # given to you by Evernote secret = "developer-secret-from-evernote" # needs to be a valid path in your application callback = "http://www.pollen.io/evernote-oauth-callback" oauth = OAuth::Consumer.new( key,secret,{:site=>base, :authorize_path => "/OAuth.action", :access_token_path=>"/oauth", :request_token_path=>"/oauth"}) #this lets you see raw wire calls oauth.http.set_debug_output($stdout) #this callback is not ignored and is actually used request_token = oauth.get_request_token(:oauth_callback=>callback) puts request_token.inspect #pretend like the user logged in and pushed the "Authorize" button oauth_verifier = pretend_to_authorize_as_user(request_token) #end of pretending like the user logged in #now, finally, get the access_token you wanted and then use it to your heart's content access_token = request_token.get_access_token(:oauth_verifier=>oauth_verifier) puts access_token.inspect # you need to store the url for the note store when you get it in the access_token. #this can differ by user, so don't just use the same one for everybody note_store_url = access_token.params['edam_noteStoreUrl'] access_token_str = access_token.token #Here is where we create an actual note. # This will all feel familiar for someone with a Java background, but if you've # only ever used Ruby it's going to feel really weird. note = Evernote::EDAM::Type::Note.new my_content = "Hello, this is a note from Pollen.io. Please check us out if you need enterprise-grade cloud integration" #This is a special gotcha. The content of your note needs to be wrapped in this special xml note.content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE en-note SYSTEM \"http://xml.evernote.com
/pub/enml2.dtd\"><en-note><![CDATA[#{my_content}]]></en-note>" note.title = "I love Evernote" note.tagNames = ['pollen.io','evernote'] noteStoreTransport = Thrift::HTTPClientTransport.new(note_store_url) noteStoreProtocol = Thrift::BinaryProtocol.new(noteStoreTransport) noteStore = Evernote::EDAM::NoteStore::NoteStore::Client.new(noteStoreProtocol) begin note = noteStore.createNote(access_token_str, note) rescue Evernote::EDAM::Error::EDAMUserException => e #the exceptions that come back from Evernote are hard to read, but really important to keep track of msg = "Caught an exception from Evernote trying to create a note. #{translate_error(e)}" raise msg end

Mi smo gore izostavili nekoliko funkcija zbog jasnoće, pa su sada ovde sve kompletne "sake".

Prvo, funkcija simulira korisnika, preusmeravajući ga u Evernote, logovanje, i pritiskajući "Authorize" dugme. Naravno, u realnim aplikacijama, zapravo bi preusmerili pravi korisnici, ali kao što sam već rekao, mi volimo da simuliramo to u integracionim testovima.

def store_cookies(response) rv = {} cookies = response.get_fields("Set-Cookie") if cookies cookies.each do |cookie| real_cookie = cookie.split('; ')[0] key, value = real_cookie.split("=") rv[key] = real_cookie #yes, setting the whole cookie and not just the value end end rv end #here we are pretending to be the user and submitting the login form as if we were them. In reality, you'd redirect # the user to the url and then wait for Freshbooks to redirect them back to you. def pretend_to_authorize_as_user(request_token) net = Net::HTTP.new("sandbox.evernote.com", 443) net.use_ssl = true net.verify_mode = OpenSSL::SSL::VERIFY_NONE net.set_debug_output $stdout net.read_timeout = 5 net.open_timeout = 5 #force a session to start # this doesn't seem to work unless you have a session start_request = Net::HTTP::Post.new("https://sandbox.evernote.com/Login.action") start_response = net.start do |http| http.request(start_request) end cookies = store_cookies(start_response) #extract the session id from the cookies session_id = cookies['JSESSIONID'].split('=')[1] #now login as if you were that user login_params = {:username=>'a-test-user-name', :password=>'a-test-user-password', :login=>'Sign In', :targetUrl=>CGI.escape("/OAuth.action?oauth_token=#{request_token.token}")} login_request = Net::HTTP::Post.new("https://sandbox.evernote.com/Login.action;jsessionid=#{session_id}") login_request.set_form_data(login_params) login_request.add_field("Cookie", cookies.values.join("; ")) login_request.add_field("Cookie", "JSESSIONID=#{@session_id}") if @session_id login_response = net.start do |http| http.request(login_request) end cookies = cookies.merge(store_cookies(login_response)) #now actually push the "Authorize" button authorize_params = {:authorize=>"Authorize", :oauth_token=>request_token.token} authorize_request = Net::HTTP::Post.new("https://sandbox.evernote.com/OAuth.action") authorize_request.set_form_data(authorize_params) authorize_request.add_field("Cookie", cookies.values.join("; ")) authorize_request.add_field("Cookie", "JSESSIONID=#{@session_id}") if @session_id authorize_response = net.start do |http| http.request(authorize_request) end #now, finally, extract what we came here for in the first place, the access token location = authorize_response['location'].scan(/oauth_verifier=(\d*\w*)/) oauth_verifier = location[0][0] oauth_verifier end

Dalje, naše greške rukovanja code, tako da možete videti, kako da shvatite šta če se dogoditi kada nešto krene naopako

# see: http://www.ruby-doc.org/gems/docs/e/evernote-1.2.0/Evernote/EDAM/Error/EDAMErrorCode.html # see: http://www.ruby-doc.org/gems/docs/e/evernote-1.2.0/Evernote/EDAM/Error/EDAMUserException.html def translate_error(e) error_name = "unknown" case e.errorCode when Evernote::EDAM::Error::EDAMErrorCode::AUTH_EXPIRED error_name = "AUTH_EXPIRED" when Evernote::EDAM::Error::EDAMErrorCode::BAD_DATA_FORMAT error_name = "BAD_DATA_FORMAT" when Evernote::EDAM::Error::EDAMErrorCode::DATA_CONFLICT error_name = "DATA_CONFLICT" when Evernote::EDAM::Error::EDAMErrorCode::DATA_REQUIRED error_name = "DATA_REQUIRED" when Evernote::EDAM::Error::EDAMErrorCode::ENML_VALIDATION error_name = "ENML_VALIDATION" when Evernote::EDAM::Error::EDAMErrorCode::INTERNAL_ERROR error_name = "INTERNAL_ERROR" when Evernote::EDAM::Error::EDAMErrorCode::INVALID_AUTH error_name = "INVALID_AUTH" when Evernote::EDAM::Error::EDAMErrorCode::LIMIT_REACHED error_name = "LIMIT_REACHED" when Evernote::EDAM::Error::EDAMErrorCode::PERMISSION_DENIED error_name = "PERMISSION_DENIED" when Evernote::EDAM::Error::EDAMErrorCode::QUOTA_REACHED error_name = "QUOTA_REACHED" when Evernote::EDAM::Error::EDAMErrorCode::SHARD_UNAVAILABLE error_name = "SHARD_UNAVAILABLE" when Evernote::EDAM::Error::EDAMErrorCode::UNKNOWN error_name = "UNKNOWN" when Evernote::EDAM::Error::EDAMErrorCode::VALID_VALUES error_name = "VALID_VALUES" when Evernote::EDAM::Error::EDAMErrorCode::VALUE_MAP error_name = "VALUE_MAP" end rv = "Error code was: #{error_name}[#{e.errorCode}] and parameter: [#{e.parameter}]" end




Published (Last edited): 28-05-2013 , source: http://cms.pollen.io/2012/12/creating-a-note-in-evernote-from-ruby/