ایجاد یک ابزارک داده گوگل

اریک بیدلمن، تیم Google Data APIs
اکتبر 2008

معرفی

حضار

این مقاله شما را با ایجاد یک ابزار Blogger راهنمایی می کند. فرض بر این است که شما با APIهای Google Data و کتابخانه سرویس گیرنده جاوا اسکریپت آشنا هستید. همچنین باید به جاوا اسکریپت مسلط باشید و در پیاده‌سازی ابزار OpenSocial با استفاده از ابزارک‌ها تجربه داشته باشید.* API .

این مثال همچنین نحوه استفاده موفقیت آمیز از کتابخانه های خارجی در ابزارهای خود را نشان می دهد. من از jQuery (عمدتاً برای جلوه های رابط کاربری آن) و TinyMCE ، یک افزونه عالی ویرایشگر متن غنی WYSIWYG استفاده کرده ام.

انگیزه

برای ایجاد ابزاری که از JSON با یکی از APIهای Google Data استفاده می کند، جاوا اسکریپت بسیار کمی لازم است. مزاحم اصلی چنین ابزاری این است که داده ها عمومی و فقط خواندنی هستند. برای ساخت ابزارهای جالب تر، باید به داده های خصوصی کاربر دسترسی داشته باشید (چیزی که نیاز به احراز هویت دارد). تا به حال، راه خوبی برای استفاده از APIهای حساب Google وجود نداشته است. AuthSub به تغییر مسیرهای مرورگر نیاز دارد و ClientLogin اعتبار کاربر را در سمت سرویس گیرنده افشا می کند. حتی هک کردن یک ابزار type="url" ناخوشایند بوده است.

پروکسی OAuth را وارد کنید.

پروکسی OAuth

اگر با OAuth آشنایی ندارید، این یک استاندارد احراز هویت است که به کاربر اجازه می دهد تا داده های خصوصی خود را با وب سایت یا ابزار دیگری به اشتراک بگذارد. مشخصات OAuth ایجاب می کند که همه درخواست های داده به صورت دیجیتالی امضا شوند. این برای امنیت عالی است، اما در مورد ابزار جاوا اسکریپت، مدیریت کلیدهای خصوصی و ایجاد امضای دیجیتال ناامن است. همچنین پیچیدگی اضافه ای در مورد مسائل بین دامنه ای وجود دارد.

خوشبختانه، این مشکلات با استفاده از ویژگی پلتفرم گجت ها به نام OAuth Proxy حل شده است. پروکسی OAuth به گونه ای طراحی شده است که زندگی را برای توسعه دهندگان ابزار آسان تر کند. بسیاری از جزئیات احراز هویت OAuth را پنهان می کند و کارهای سنگین را برای شما انجام می دهد. پروکسی درخواست‌های داده را از طرف اسبابک شما امضا می‌کند، بنابراین نیازی به مدیریت کلیدهای خصوصی یا نگرانی در مورد امضای درخواست‌ها نیست. این فقط کار می کند!

پروکسی OAuth بر اساس یک پروژه منبع باز به نام Shindig است که اجرای مشخصات ابزارک است.

توجه: پروکسی OAuth فقط برای ابزارهایی که از gadgets.* API و در ظروف OpenSocial اجرا می شود. برای API اسبابک های قدیمی پشتیبانی نمی شود.

شروع شدن

بقیه این آموزش بر ایجاد ابزاری برای دسترسی به داده های بلاگر کاربر تمرکز دارد. ما از طریق احراز هویت (با استفاده از پروکسی OAuth)، با استفاده از کتابخانه سرویس گیرنده جاوا اسکریپت، و در نهایت، ارسال یک ورودی به بلاگر خواهیم رفت.

احراز هویت

ابتدا باید به ابزارک بگوییم از OAuth استفاده کند. برای انجام این کار، عنصر <OAuth> را در بخش <ModulePrefs> ابزار اضافه کنید:

<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>

سه نقطه پایانی url در عنصر <Service> با نقاط پایانی نشانه OAuth Google مطابقت دارد. در اینجا توضیحاتی در مورد پارامترهای پرس و جو ارائه شده است:

  • scope

    این پارامتر در URL درخواست الزامی است. ابزار شما فقط می‌تواند از scope (های) مورد استفاده در این پارامتر به داده‌ها دسترسی داشته باشد. در این مثال، ابزار به بلاگر دسترسی خواهد داشت. اگر اسبابک شما می‌خواهد به بیش از یک Google Data API دسترسی داشته باشد، scope (های) اضافی را با %20 به هم بچسبانید. به عنوان مثال، اگر می‌خواهید به تقویم و بلاگر دسترسی داشته باشید، دامنه را روی http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/ تنظیم کنید.

  • oauth_callback

    این پارامتر در URL مجوز اختیاری است. صفحه تأیید OAuth پس از تأیید دسترسی کاربر به داده های خود، به این URL هدایت می شود. می‌توانید این پارامتر را کنار بگذارید، آن را روی «صفحه تأییدشده» خودتان تنظیم کنید، یا ترجیحاً از http://oauth.gmodules.com/gadgets/oauthcallback استفاده کنید. زمانی که کاربران برای اولین بار اسبابک شما را نصب می کنند، نسخه بعدی بهترین تجربه کاربری را ارائه می دهد. آن صفحه یک قطعه از جاوا اسکریپت را ارائه می دهد که به طور خودکار پنجره بازشو بسته می شود.

اکنون که ابزار خود را با استفاده از OAuth در اختیار داریم، کاربر باید دسترسی به داده های خود را تأیید کند. در اینجا جریان احراز هویت است:

  1. این ابزار برای اولین بار بارگیری می شود و سعی می کند به داده های بلاگر کاربر دسترسی پیدا کند.
  2. درخواست ناموفق است زیرا کاربر اجازه دسترسی به ابزارک را نداده است. خوشبختانه، شی ای که در پاسخ بازگردانده می شود حاوی یک URL ( response.oauthApprovalUrl ) است که در آن کاربر را برای ورود به سیستم می فرستیم. اسبابک «ورود به بلاگر» را نمایش می‌دهد و href آن را روی مقدار oauthApprovalUrl تنظیم می‌کند.
  3. در مرحله بعد، کاربر روی «ورود به بلاگر» کلیک می‌کند و صفحه تأیید OAuth در یک پنجره جداگانه باز می‌شود. گجت منتظر می ماند تا کاربر فرآیند تأیید را با نمایش پیوندی به پایان برساند: «من دسترسی را تأیید کردم».
  4. در پنجره بازشو، کاربر انتخاب می‌کند که دسترسی به ابزار ما را اعطا یا رد کند. هنگامی که روی "Grant access" کلیک کردند، به http://oauth.gmodules.com/gadgets/oauthcallback منتقل می شوند و پنجره بسته می شود.
  5. این ابزار، پنجره بسته شده را تشخیص می‌دهد و با درخواست مجدد داده‌های کاربر، برای بار دوم به بلاگر دسترسی پیدا می‌کند. برای تشخیص بسته شدن پنجره، من از کنترلر پنجره بازشو استفاده کرده ام. اگر از چنین کدی استفاده نمی کنید، کاربر می تواند به صورت دستی روی "من دسترسی را تایید کرده ام" کلیک کند.
  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>

هر <div> به تنهایی با استفاده از showOnly() نمایش داده می شود. برای جزئیات بیشتر در مورد آن عملکرد ، ابزار نمونه کامل را ببینید.

با استفاده از کتابخانه مشتری جاوا اسکریپت

برای واکشی محتوای راه دور در OpenSocial، با استفاده از ابزارها با روش gadgets.io.makeRequest تماس بگیرید gadgets.* API. با این حال، از آنجایی که ما در حال ساخت ابزار Google Data هستیم، نیازی به لمس API های gadgets.io.* نیست. در عوض، از کتابخانه سرویس گیرنده جاوا اسکریپت استفاده کنید که روش‌های خاصی برای درخواست به هر سرویس Google Data دارد.

توجه : در زمان نوشتن این مقاله، کتابخانه جاوا اسکریپت فقط از Blogger ، Calendar ، Contacts ، Finance و Google Base پشتیبانی می کند. برای استفاده از یکی از APIهای دیگر، از gadgets.io.makeRequest بدون کتابخانه استفاده کنید.

در حال بارگیری کتابخانه

برای بارگیری کتابخانه جاوا اسکریپت، بارگیری مشترک را در بخش <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>

تماس با blogger.useOAuth('google') به کتابخانه می گوید که از پروکسی OAuth (به جای AuthSubJS - روش احراز هویت عادی آن) استفاده کند. در نهایت، این ابزار تلاش می‌کند تا داده‌های بلاگر کاربر را با فراخوانی fetchData() بازیابی کند. آن روش در زیر تعریف شده است.

در حال واکشی داده ها

اکنون که همه چیز تنظیم شده است، چگونه می توانیم داده ها را در بلاگر GET یا POST ؟

یک الگوی رایج در OpenSocial این است که تابعی به نام fetchData() را در ابزار خود تعریف کنید. این روش معمولاً مراحل مختلف احراز هویت را انجام می دهد و داده ها را با استفاده از gadgets.io.makeRequest واکشی می کند. از آنجایی که ما از کتابخانه سرویس گیرنده جاوا اسکریپت استفاده می کنیم، 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);
}

نتیجه

اکنون بلوک‌های سازنده برای شروع کدنویسی یک ابزار در بالای APIهای Google Data را دارید.

امیدواریم این مقاله به شما قدردانی کرده باشد که پروکسی OAuth چقدر ساده احراز هویت ابزارک را انجام می دهد. ترکیب این ابزار قدرت با کتابخانه سرویس گیرنده Google Data JavaScript ساخت ابزارهای جالب، تعاملی و پیچیده را آسان می کند.

اگر سؤال یا نظری در مورد این مقاله دارید، لطفاً در انجمن گفتگوی Google Accounts APIs از ما دیدن کنید.

منابع