Google डेटा गैजेट बनाना

एरिक बिडेलमैन, Google Data APIs टीम
अक्टूबर 2008

परिचय

ऑडियंस

इस लेख में, Blogger गैजेट बनाने का तरीका बताया गया है. इसमें यह माना गया है कि आपको Google Data API और JavaScript क्लाइंट लाइब्रेरी के बारे में जानकारी है. आपको JavaScript का भी अच्छा ज्ञान होना चाहिए. साथ ही, gadgets.* API.

इस उदाहरण में यह भी दिखाया गया है कि अपने गैजेट में बाहरी लाइब्रेरी का इस्तेमाल कैसे किया जा सकता है. मैंने jQuery का इस्तेमाल किया है. इसका इस्तेमाल मुख्य रूप से यूज़र इंटरफ़ेस (यूआई) इफ़ेक्ट के लिए किया जाता है. साथ ही, मैंने TinyMCE का इस्तेमाल किया है. यह WYSIWYG रिच टेक्स्ट एडिटर प्लगिन है.

वजह

Google Data API में से किसी एक के साथ JSON का इस्तेमाल करने वाला गैजेट बनाने के लिए, बहुत कम JavaScript की ज़रूरत होती है. इस तरह के गैजेट की सबसे बड़ी समस्या यह है कि इसका डेटा सार्वजनिक होता है और इसे सिर्फ़ पढ़ा जा सकता है. ज़्यादा दिलचस्प गैजेट बनाने के लिए, आपको उपयोगकर्ता के निजी डेटा को ऐक्सेस करने की ज़रूरत होती है. इसके लिए, पुष्टि करना ज़रूरी है. अब तक, Google Account APIs का फ़ायदा पाने का कोई बेहतर तरीका नहीं था. AuthSub के लिए ब्राउज़र रीडायरेक्ट की ज़रूरत होती है. साथ ही, ClientLogin, क्लाइंट-साइड पर उपयोगकर्ता के क्रेडेंशियल दिखाता है. type="url" गैजेट को हैक करना भी मुश्किल हो गया है.

OAuth प्रॉक्सी डालें.

OAuth प्रॉक्सी

अगर आपको OAuth के बारे में नहीं पता है, तो यह पुष्टि करने का एक स्टैंडर्ड है. इसकी मदद से, कोई उपयोगकर्ता अपनी निजी जानकारी को किसी दूसरी वेबसाइट या गैजेट के साथ शेयर कर सकता है. OAuth स्पेसिफ़िकेशन के मुताबिक, सभी डेटा अनुरोधों पर डिजिटल हस्ताक्षर होना ज़रूरी है. यह सुरक्षा के लिए बहुत अच्छा है, लेकिन JavaScript गैजेट के मामले में, निजी पासकोड मैनेज करना और डिजिटल हस्ताक्षर बनाना सुरक्षित नहीं है. इसके अलावा, क्रॉस-डोमेन से जुड़ी समस्याएं भी हो सकती हैं.

इन समस्याओं को हल करने के लिए, गैजेट प्लैटफ़ॉर्म की एक सुविधा का इस्तेमाल किया जाता है. इसे OAuth प्रॉक्सी कहा जाता है. OAuth प्रॉक्सी को गैजेट डेवलपर के लिए बनाया गया है, ताकि वे आसानी से काम कर सकें. यह OAuth की पुष्टि करने की ज़्यादातर जानकारी को छिपा देता है और आपके लिए ज़्यादातर काम कर देता है. प्रॉक्सी, आपके गैजेट की ओर से डेटा के अनुरोधों पर हस्ताक्षर करता है. इसलिए, आपको निजी पासकोड मैनेज करने या अनुरोधों पर हस्ताक्षर करने के बारे में चिंता करने की ज़रूरत नहीं है. यह वाकई काम करता है!

OAuth प्रॉक्सी, Shindig नाम के ओपन-सोर्स प्रोजेक्ट पर आधारित है. यह गैजेट स्पेसिफ़िकेशन को लागू करता है.

ध्यान दें: OAuth प्रॉक्सी की सुविधा सिर्फ़ उन गैजेट के लिए उपलब्ध है जो gadgets.* API का इस्तेमाल करते हैं और OpenSocial कंटेनर में चलते हैं. यह लेगसी गैजेट एपीआई के साथ काम नहीं करता.

शुरू करें

इस ट्यूटोरियल के बाकी हिस्से में, उपयोगकर्ता के Blogger डेटा को ऐक्सेस करने के लिए गैजेट बनाने पर फ़ोकस किया जाएगा. हम JavaScript क्लाइंट लाइब्रेरी का इस्तेमाल करके, OAuth प्रॉक्सी की मदद से पुष्टि करने की प्रोसेस के बारे में जानेंगे. इसके बाद, Blogger पर एंट्री पोस्ट करने के बारे में जानेंगे.

पुष्टि करना

सबसे पहले, हमें गैजेट को OAuth का इस्तेमाल करने के लिए कहना होगा. इसके लिए, गैजेट के <ModulePrefs> सेक्शन में <OAuth> एलिमेंट जोड़ें:

<ModulePrefs>
...
<OAuth>
  <Service name="google">
    <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> 
    <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.blogger.com/feeds/" method="GET" /> 
    <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken?
                        oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> 
  </Service>
</OAuth>
...
</ModulePrefs>

<Service> एलिमेंट में मौजूद तीन यूआरएल एंडपॉइंट, Google के OAuth टोकन एंडपॉइंट के मुताबिक होते हैं. क्वेरी पैरामीटर के बारे में यहां बताया गया है:

  • scope

    यह पैरामीटर, अनुरोध यूआरएल में ज़रूरी है. आपका गैजेट, सिर्फ़ इस पैरामीटर में इस्तेमाल किए गए scope(s) से डेटा ऐक्सेस कर पाएगा. इस उदाहरण में, गैजेट Blogger को ऐक्सेस करेगा. अगर आपके गैजेट को एक से ज़्यादा Google Data API ऐक्सेस करने हैं, तो अतिरिक्त scope को %20 के साथ जोड़ें. उदाहरण के लिए, अगर आपको Calendar और Blogger, दोनों को ऐक्सेस करना है, तो स्कोप को http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/ पर सेट करें.

  • oauth_callback

    यह पैरामीटर, अनुमति देने वाले यूआरएल में ज़रूरी नहीं है. उपयोगकर्ता के डेटा का ऐक्सेस देने की मंज़ूरी मिलने के बाद, OAuth की मंज़ूरी वाला पेज इस यूआरएल पर रीडायरेक्ट हो जाएगा. आपके पास इस पैरामीटर को शामिल न करने, इसे अपने "स्वीकार किए गए पेज" पर सेट करने या बेहतर होगा कि आप http://oauth.gmodules.com/gadgets/oauthcallback का इस्तेमाल करें. बाद वाला विकल्प, उपयोगकर्ताओं को बेहतर अनुभव देता है. ऐसा तब होता है, जब वे पहली बार आपका गैजेट इंस्टॉल करते हैं. उस पेज पर JavaScript का एक स्निपेट दिया गया है. इससे पॉप-अप विंडो अपने-आप बंद हो जाती है.

अब हमारे पास OAuth का इस्तेमाल करने वाला गैजेट है. इसलिए, उपयोगकर्ता को अपने डेटा को ऐक्सेस करने की अनुमति देनी होगी. पुष्टि करने की प्रोसेस यहां दी गई है:

  1. गैजेट पहली बार लोड होता है और उपयोगकर्ता के Blogger खाते के डेटा को ऐक्सेस करने की कोशिश करता है.
  2. अनुरोध पूरा नहीं हो सका, क्योंकि उपयोगकर्ता ने गैजेट को ऐक्सेस करने की अनुमति नहीं दी है. अच्छी बात यह है कि जवाब में मिले ऑब्जेक्ट में एक यूआरएल (response.oauthApprovalUrl) होता है. हम उपयोगकर्ता को लॉगिन करने के लिए इस यूआरएल पर भेजेंगे. यह गैजेट "Blogger में साइन इन करें" दिखाता है और इसके href को oauthApprovalUrl की वैल्यू पर सेट करता है.
  3. इसके बाद, उपयोगकर्ता "Blogger में साइन इन करें" पर क्लिक करता है. इससे OAuth की मंज़ूरी वाला पेज, एक अलग विंडो में खुल जाता है. गैजेट, उपयोगकर्ता के लिए अनुमति देने की प्रोसेस पूरी होने का इंतज़ार करता है. इसके लिए, वह एक लिंक दिखाता है: "मैंने ऐक्सेस की अनुमति दे दी है".
  4. पॉप-अप में, उपयोगकर्ता हमारे गैजेट को ऐक्सेस देने या न देने का विकल्प चुन सकता है. "ऐक्सेस दें" पर क्लिक करने के बाद, उन्हें http://oauth.gmodules.com/gadgets/oauthcallback पर ले जाया जाता है और विंडो बंद हो जाती है.
  5. गैजेट को बंद की गई विंडो का पता चलता है. इसके बाद, वह उपयोगकर्ता के डेटा का फिर से अनुरोध करके, Blogger को दूसरी बार ऐक्सेस करने की कोशिश करता है. विंडो बंद होने का पता लगाने के लिए, मैंने पॉपअप हैंडलर का इस्तेमाल किया है. अगर ऐसे कोड का इस्तेमाल नहीं किया जाता है, तो उपयोगकर्ता मैन्युअल तरीके से "मैंने ऐक्सेस की अनुमति दे दी है" पर क्लिक कर सकता है.
  6. अब गैजेट में सामान्य यूज़र इंटरफ़ेस (यूआई) दिखता है. यह व्यू तब तक बना रहेगा, जब तक IssuedAuthSubTokens में जाकर पुष्टि करने वाले टोकन को रद्द नहीं किया जाता.

इसलिए, ऊपर दिए गए चरणों के हिसाब से, गैजेट की तीन अलग-अलग स्थितियां होती हैं:

  1. पुष्टि नहीं हुई है. उपयोगकर्ता को अनुमति पाने की प्रोसेस शुरू करनी होगी.
  2. उपयोगकर्ता से, उसके डेटा को ऐक्सेस करने की अनुमति मिलने का इंतज़ार किया जा रहा है.
  3. पुष्टि हो गई है. गैजेट, सामान्य तौर पर काम कर रहा है.

मैंने अपने गैजेट में, हर स्टेज को अलग करने के लिए <div> कंटेनर इस्तेमाल किए हैं:

<Content type="html">
<![CDATA[

<!-- Normal state of the gadget. The user is authenticated -->       
<div id="main" style="display:none">
  <form id="postForm" name="postForm" onsubmit="savePost(this); return false;">
     <div id="messages" style="display: none"></div>
     <div class="selectFeed">Publish to:
       <select id="postFeedUri" name="postFeedUri" disabled="disabled"><option>loading blog list...</option></select>
     </div>
     <h4 style="clear:both">Title</h4>
     <input type="text" id="title" name="title"/>
     <h4>Content</h4>
     <textarea id="content" name="content" style="width:100%;height:200px;"></textarea>
     <h4 style="float:left;">Labels (comma separated)</h4><img src="blogger.png" style="float:right"/>
     <input type="text" id="categories" name="categories"/>
     <p><input type="submit" id="submitButton" value="Save"/> 
     <input type="checkbox" id="draft" name="draft" checked="checked"/> <label for="draft">Draft?</label></p>
  </form>
</div>

<div id="approval" style="display: none">
  <a href="#" id="personalize">Sign in to Blogger</a>
</div>

<div id="waiting" style="display: none">
  <a href="#" id="approvalLink">I've approved access</a>
</di

<!-- An errors section is not necessary but great to have -->
<div id="errors" style="display: none"></div>
 
<!-- Also not necessary, but great for informing users -->     
<div id="loading">
  <h3>Loading...</h3>
  <p><img src="ajax-loader.gif"></p>
</div>

]]> 
</Content&gt

हर <div> को showOnly() का इस्तेमाल करके अलग से दिखाया जाता है. उस फ़ंक्शन के बारे में ज़्यादा जानकारी के लिए, पूरा उदाहरण गैजेट देखें.

JavaScript क्लाइंट लाइब्रेरी का इस्तेमाल करना

OpenSocial में रिमोट कॉन्टेंट फ़ेच करने के लिए, gadgets.* API का इस्तेमाल करके gadgets.io.makeRequest तरीके को कॉल करें. हालांकि, हम Google Data गैजेट बना रहे हैं. इसलिए, gadgets.io.* एपीआई में बदलाव करने की ज़रूरत नहीं है. इसके बजाय, JavaScript क्लाइंट लाइब्रेरी का इस्तेमाल करें. इसमें Google की हर डेटा सेवा के लिए अनुरोध करने के खास तरीके होते हैं.

ध्यान दें: इस लेख को लिखते समय, JavaScript लाइब्रेरी सिर्फ़ Blogger, Calendar, Contacts, Finance, और Google Base के साथ काम करती है. किसी दूसरे एपीआई का इस्तेमाल करने के लिए, लाइब्रेरी के बिना gadgets.io.makeRequest का इस्तेमाल करें.

लाइब्रेरी लोड हो रही है

JavaScript लाइब्रेरी को लोड करने के लिए, <Content> सेक्शन में सामान्य लोडर शामिल करें. साथ ही, गैजेट के शुरू हो जाने के बाद लाइब्रेरी को इंपोर्ट करें. gadgets.util.registerOnLoadHandler() को कॉलबैक देने से, यह तय करने में मदद मिलेगी कि गैजेट कब तैयार है:

<Content type="html">
<![CDATA[
  ...
  <script src="https://www.google.com/jsapi"></script>
  <script type="text/javascript">
  var blogger = null;  // make our service object global for later
  
  // Load the JS library and try to fetch data once it's ready
  function initGadget() {  
    google.load('gdata', '1.x', {packages: ['blogger']});  // Save overhead, only load the Blogger service
    google.setOnLoadCallback(function () {
      blogger = new google.gdata.blogger.BloggerService('google-BloggerGadget-v1.0');
      blogger.useOAuth('google');
      fetchData();
    });
  }
  gadgets.util.registerOnLoadHandler(initGadget);
  </script>
  ...
]]> 
</Content&gt

blogger.useOAuth('google') को कॉल करने पर, लाइब्रेरी को OAuth प्रॉक्सी का इस्तेमाल करने के लिए कहा जाता है. ऐसा AuthSubJS (पुष्टि करने का सामान्य तरीका) के बजाय किया जाता है. आखिर में, गैजेट fetchData() को कॉल करके, उपयोगकर्ता के Blogger खाते का डेटा वापस पाने की कोशिश करता है. इस तरीके के बारे में यहां बताया गया है.

डेटा फ़ेच किया जा रहा है

अब जब सब कुछ सेट अप हो गया है, तो हम Blogger को डेटा कैसे GET या POST करें?

OpenSocial में, fetchData() नाम के फ़ंक्शन को अपने गैजेट में तय करना एक सामान्य पैराडाइम है. यह तरीका आम तौर पर पुष्टि करने के अलग-अलग चरणों को मैनेज करता है और gadgets.io.makeRequest का इस्तेमाल करके डेटा फ़ेच करता है. JavaScript क्लाइंट लाइब्रेरी का इस्तेमाल करने पर, gadgets.io.makeRequest को blogger.getBlogFeed() के कॉल से बदल दिया जाता है:

function fetchData() {
  jQuery('#errors').hide();
  
  var callback = function(response) {
    if (response.oauthApprovalUrl) {
      // You can set the sign in link directly:
      // jQuery('#personalize').get(0).href = response.oauthApprovalUrl
      
      // OR use the popup.js handler
      var popup = shindig.oauth.popup({
        destination: response.oauthApprovalUrl,
        windowOptions: 'height=600,width=800',
        onOpen: function() {
          showOnly('waiting');
        },
        onClose: function() {
          showOnly('loading');
          fetchData();
        }
      });
      jQuery('#personalize').get(0).onclick = popup.createOpenerOnClick();
      jQuery('#approvalLink').get(0).onclick = popup.createApprovedOnClick();
      
      showOnly('approval');
    } else if (response.feed) {
      showResults(response);
      showOnly('main');
    } else {
      jQuery('#errors').html('Something went wrong').fadeIn();
      showOnly('errors');
    }
  };
  
  blogger.getBlogFeed('http://www.blogger.com/feeds/default/blogs', callback, callback);
}

इस फ़ंक्शन को दूसरी बार कॉल करने पर, response.feed में डेटा होता है.

ध्यान दें: getBlogFeed(), कॉलबैक और गड़बड़ी हैंडलर के लिए एक ही फ़ंक्शन का इस्तेमाल करता है.

Blogger पर कोई एंट्री पोस्ट करना

आखिरी चरण है, ब्लॉग में नई एंट्री पोस्ट करना. नीचे दिए गए कोड से पता चलता है कि जब उपयोगकर्ता "सेव करें" बटन पर क्लिक करता है, तो क्या होता है.

function savePost(form) { 
  jQuery('#messages').fadeOut();
  jQuery('#submitButton').val('Publishing...').attr('disabled', 'disabled');
  
  // trim whitespace from the input tags
  var input = form.categories.value;
  var categories = jQuery.trim(input) != '' ? input.split(',') : [];   
  jQuery.each(categories, function(i, value) {
    var label = jQuery.trim(value);
    categories[i] = {
      scheme: 'http://www.blogger.com/atom/ns#',
      term: label
    };
  });

  // construct the blog post entry
  var newEntry = new google.gdata.blogger.BlogPostEntry({
    title: {
      type: 'text', 
      text: form.title.value
    },
    content: {
      type: 'text', 
      text: form.content.value
    },
    categories: categories
  });
  
  // publish as draft?
  var isDraft = form.draft.checked;
  if (isDraft) {
    newEntry.setControl({draft: {value: google.gdata.Draft.VALUE_YES}});
  }
  
  // callback for insertEntry()
  var handleInsert = function(entryRoot) {
    var entry = entryRoot.entry;
    var str = isDraft ? '(as draft)' : '<a href="' + entry.getHtmlLink().getHref() + '" target="_blankt">View it</a>';

    jQuery('#messages').html('Post published! ' + str).fadeIn();
    jQuery('#submitButton').val('Save').removeAttr('disabled');
  };
  
  // error handler for insertEntry()
  var handleError = function(e) {
    var msg = e.cause ? e.cause.statusText + ': ' : '';
    msg += e.message;
    alert('Error: ' + msg);
  };
  
  blogger.insertEntry(form.postFeedUri.value, newEntry, handleInsert, handleError);
}

नतीजा

अब आपके पास Google Data API के ऊपर गैजेट को कोड करने के लिए बिल्डिंग ब्लॉक हैं.

हमें उम्मीद है कि इस लेख से आपको यह समझने में मदद मिली होगी कि OAuth प्रॉक्सी, गैजेट की पुष्टि करने की प्रोसेस को कितना आसान बना देती है. इस पावर टूल को Google Data JavaScript क्लाइंट लाइब्रेरी के साथ इस्तेमाल करने से, दिलचस्प, इंटरैक्टिव, और बेहतर गैजेट बनाना आसान हो जाता है.

अगर आपको इस लेख के बारे में कोई सवाल पूछना है या कोई टिप्पणी करनी है, तो कृपया Google खातों के एपीआई के बारे में चर्चा करने वाले फ़ोरम पर जाएं.

संसाधन