إنشاء أداة بيانات من Google

إريك بيدلمان، فريق Google Data APIs
تشرين الأول (أكتوبر) 2008

المقدمة

الجمهور

ستوجهك هذه المقالة خطوة بخطوة خلال إنشاء أداة Blogger. ويفترض أنك على دراية بواجهات برمجة التطبيقات لبيانات Google ومكتبة عميل JavaScript. كما يجب أن تكون بطلاقة في جافا سكريبت، وأن يكون لديك بعض الخبرة في تنفيذ أداة OpenSocial باستخدام الأدوات.* واجهة برمجة التطبيقات.

يوضح هذا المثال أيضًا كيفية استخدام المكتبات الخارجية بنجاح في أدواتك. لقد استخدمت jQuery (لتأثيرات واجهة المستخدم بشكل أساسي) وTinyMCE، وهو مكون إضافي رائع لمحرر النص المنسق WYSIWYG.

الحافز

لا يتطلب الأمر سوى القليل من جافا سكريبت لإنشاء أداة تستخدم JSON مع إحدى واجهات برمجة تطبيقات بيانات Google. إن مصدر الإزعاج الرئيسي لهذه الأداة هو أن البيانات عامة وللقراءة فقط. لإنشاء أدوات أكثر إثارة للاهتمام، تحتاج إلى الوصول إلى بيانات المستخدم الخاصة (شيء يتطلب المصادقة). حتى الآن، لم تكن هناك طريقة رائعة للاستفادة من واجهات برمجة تطبيقات حساب Google. يتطلب AuthSub عمليات إعادة توجيه للمتصفح، ويعرض ClientLogin بيانات اعتماد المستخدم، من جانب العميل. وحتى اختراق أداة type="url" لم يكن ملائمًا.

أدخل خادم وكيل OAuth.

خادم وكيل OAuth

إذا لم تكن معتادًا على استخدام بروتوكول OAuth، فهو معيار مصادقة يسمح للمستخدم بمشاركة بياناته الخاصة مع أداة أو موقع ويب آخر. تتطلب مواصفات OAuth توقيع جميع طلبات البيانات رقميًا. وهذا أمر مهم بالنسبة إلى الأمان، ولكن في حالة أداة جافا سكريبت، تكون إدارة المفاتيح الخاصة وإنشاء التوقيعات الرقمية غير آمنة. هناك أيضًا تعقيد إضافي للمشكلات عبر النطاقات.

ولحسن الحظ، يتم حل هذه المشكلات عن طريق الاستفادة من ميزة تُعرف باسم الخادم الوكيل OAuth في النظام الأساسي للأدوات. تم تصميم خادم وكيل OAuth لتسهيل الحياة على مطوري الأدوات. ويخفي ذلك الكثير من تفاصيل مصادقة OAuth، ما يؤدي إلى صعوباته. يوقّع الخادم الوكيل طلبات البيانات بالنيابة عن أداتك، لذلك ليس هناك حاجة لإدارة المفاتيح الخاصة أو القلق بشأن طلبات التوقيع. إنها تعمل فقط!

يستند خادم وكيل OAuth إلى مشروع مفتوح المصدر يسمى Shindig، وهو عبارة عن تنفيذ لمواصفات الأداة.

ملاحظة: لا يتوفر خادم وكيل OAuth إلا للأدوات التي تستخدم واجهة برمجة تطبيقات gadgets.* وتعمل في حاويات OpenSocial. ولا يتوافق هذا الإعداد مع واجهة برمجة التطبيقات للأدوات القديمة.

البدء

سيركز الجزء المتبقي من هذا البرنامج التعليمي على إنشاء أداة للدخول إلى بيانات المستخدم في Blogger. سنجري عملية المصادقة (باستخدام الخادم الوكيل لـ OAuth)، باستخدام مكتبة عميل جافا سكريبت، وأخيرًا، نشر مشاركة في Blogger.

المصادقة

أولاً، نحتاج إلى إخبار الأداة باستخدام 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(العناصر) المستخدمة في هذه المعلمة. في هذا المثال، ستدخل الأداة إلى Blogger. إذا أرادت الأداة الدخول إلى أكثر من واجهة برمجة تطبيقات لبيانات Google، يمكنك ربط scope من العناصر الإضافية مع %20. على سبيل المثال، إذا كنت تريد الوصول إلى كل من "تقويم Google" وBlogger، يمكنك ضبط النطاق على http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/.

  • oauth_callback

    هذه المعلمة اختيارية في عنوان URL للتفويض. ستتم إعادة توجيه صفحة موافقة OAuth إلى عنوان URL هذا بعد موافقة المستخدم على الوصول إلى بياناته. ويمكنك اختيار ترك هذه المعلمة أو ضبطها على "الصفحة التي تمت الموافقة عليها" أو استخدام http://oauth.gmodules.com/gadgets/oauthcallback إذا كان ذلك مفضلاً. ويقدم الإصدار الأحدث أفضل تجربة للمستخدم عند تثبيت الأداة لأول مرة. وتوفر هذه الصفحة مقتطف جافا سكريبت يغلق النافذة المنبثقة تلقائيًا.

والآن وبعد أن أصبحت أداتنا تستخدم OAuth، على المستخدم الموافقة على الوصول إلى بياناته. في ما يلي خطوات المصادقة:

  1. يتم تحميل الأداة للمرة الأولى وتحاول الدخول إلى بيانات المستخدم في Blogger.
  2. أخفق الطلب نظرًا لأن المستخدم لم يمنح حق الدخول إلى الأداة. لحسن الحظ، يحتوي الكائن المعروض في الاستجابة على عنوان URL (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>

يتم عرض كل <div> بمفرده باستخدام showOnly(). اطلع على المثال الكامل للأداة للحصول على تفاصيل حول هذه الدالة.

استخدام مكتبة عميل JavaScript

لجلب المحتوى البعيد في OpenSocial، يمكنك إجراء استدعاء لطريقة gadgets.io.makeRequest باستخدام واجهة برمجة تطبيقات gadgets.*. ومع ذلك، بما أننا نُنشئ أداة بيانات Google، فلا حاجة إلى لمس واجهات برمجة تطبيقات 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>

يؤدي استدعاء blogger.useOAuth('google') إلى توجيه المكتبة لاستخدام وكيل OAuth (بدلاً من AuthSubJS - وهو طريقة المصادقة العادية). وأخيرًا، تحاول الأداة استرداد بيانات المستخدم في Blogger من خلال الاتصال بـ fetchData(). تم تحديد هذه الطريقة أدناه.

جارٍ جلب البيانات

الآن وبعد الانتهاء من الإعداد، كيف يمكننا GET أو POST بيانات فعليًا في Blogger؟

يتمثل النموذج الشائع في 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.

نأمل أن تكون هذه المقالة قد أعطتك تقديرًا لمدى بساطة خادم وكيل OAuth الذي يجعل مصادقة الأداة. ويُسهِّل الجمع بين أداة التشغيل هذه ومكتبة عميل "جافا سكريبت" في Google Data من إنشاء أدوات تفاعلية وتفاعلية ومتطورة.

إذا كان لديك أي أسئلة أو تعليقات بشأن هذه المقالة، يُرجى زيارتنا في منتدى مناقشة واجهات برمجة التطبيقات لحسابات Google.

الموارد