vkontakte_api:VK API用のrubyアダプター

今年の初めに、私はRailsアプリケーションからVK APIを使用する必要がありました。 残念ながら、私に合った宝石は見つかりませんでした:どこかでキャメルケース(rubyコードでは不自然に見える)でメソッドの名前を書くことを余儀なくされました(どこかでomn​​iauthを使用したという事実にもかかわらず)そして一般的に、APIにアクセスするために、ハードコードNet::HTTP 、イベントマシンリアクターをブロックしました。 また、ドキュメントに関しては、何らかの理由ですべてが非常に悲しかったので、ソースコードを常に読む必要がありました。

それでvkontakte_apiが生まれました。 このライブラリを書くための口実として役立った鉄道プロジェクトはすでに休んでいます-しかし、gemは7月にバージョン1.0に達し、重要な変更の口実として機能し、開発を続けています。 faradayを使用すると、ライブラリは、APIメソッドの呼び出し、VKontakteサーバーへのファイルのアップロード、およびオプションの許可をサポートします。前の段落で述べたプログラマーの決定は必要ありません。

vkontakte_apiを使用してAPIをvkontakte_apiする方法を見てみましょう。 例として、OAuth2承認に合格したユーザーのニュースフィード(APIメソッドnewsfeed.get )、 友人のリスト( friends.get )、およびグループ( groups.get )を表示する単純なWebアプリケーションが役立ちます。 そして、次のようになります。



カスタマイズ


認可では、VKontakteのアプリケーション編集ページで取得できるアプリケーションIDとセキュアキーを使用します。 また、redirect_uriも後で説明します。 これらのパラメーターはVkontakteApi.configureブロックで指定されます。このブロックはconfig/initializers/vkontakte_api.rbます。 Railsアプリケーションでは、組み込みのジェネレーターを使用して、デフォルト設定でこのファイルを生成できます。

 $ rails generate vkontakte_api:install 

設定は次のように表示されます。

 # config/initializers/vkontakte_api.rb VkontakteApi.configure do |config| config.app_id = '123' # ID  config.app_secret = 'AbCdE654' #   config.redirect_uri = 'http://vkontakte-on-rails.herokuapp.com/callback' end 

(実際、 もっと多くのオプションが利用可能ですが、残りはここでは必要ありません)

ログイン


VKontakteを介してサイトにomniauthするだけでよいため、 omniauth使用は実用的ではありませんomniauthの機能を使用します。

VKontakteでのアプリケーションの承認でOAuth2プロトコルを使用します。 これは、承認の結果としてアクセストークンが取得されることを意味し、APIメソッドを呼び出すときに転送する必要があります。

それを取得するためのスキームは次のとおりです:ユーザーはVKontakteの認証ページへのリンクをたどり、「許可」ボタンをクリックしてアプリケーションに自分の(ユーザー)データへのアクセスを許可することに同意し、VKontakteはそれをアプリケーションにリダイレクトし、 codeパラメーターをURLに渡します。 さらに、アプリケーションはこのコードを使用してuser_idユーザーのトークンとuser_id別のリクエストで受け取り、セッションに保存します。

CSRF攻撃から保護するために、OAuth2プロトコルは、安全な場所に保存した後、承認のためにユーザーを送信するときに、未定義の値でstateパラメーターを渡すこと推奨します。 ユーザーが戻ったときに、パラメーターで受信したstateと保存された値を確認します。

そのため、ログインページで、VKontakteのアプリケーション認証ページへのリンクを表示する必要があります。 vkontakte_apiは、このページのURLを生成するVkontakteApi.authorization_urlヘルパーを提供します。 scopeを渡す必要があるパラメーターでは-これらは文字(またはコンマで区切られた名前の文字列)の形式でアプリケーションが受け取る権利です-および上記のstate

 # app/controllers/sessions_controller.rb class SessionsController < ApplicationController def new #   state srand session[:state] ||= Digest::MD5.hexdigest(rand.to_s) #  URL   @vk_url = VkontakteApi.authorization_url(scope: [:friends, :groups, :offline, :notify], state: session[:state]) end end 


 <!-- app/views/sessions/new.html.erb --> <%= link_to @vk_url, class: 'btn btn-primary' do %> <i class="icon-home icon-white"></i>    <% end %> 

ここでnotifyscope指定されないならVKontakteがstate無視する何らかの未知の理由に注意されるべきです。

ユーザーがアプリケーションの権限を確認すると、設定で以前に指定されたredirect_uri( SessionsController#callbackへのパスを含む)にリダイレクトされ、 statecodeパラメーターがURLに渡されます。 直前に述べたように、 stateは既に保存されているstateと照合する必要があります。 さらにcodeを詳しく見ていきcode

コードを使用して、アクセストークンを取得できます。そのためには、VKontakteへのリクエストを完了する必要があります。 ユーザーはこのリクエストに一切参加しません。リクエストはサーバーからvk.comに直接送信されます。 このため、 vkontakte_apiはヘルパーvkontakte_apiも提供しcode 。唯一のパラメーターは悪名高いcodeです。

 # encoding: utf-8 class SessionsController < ApplicationController def callback #  state if session[:state].present? && session[:state] != params[:state] redirect_to root_url, alert: ' ,    .' and return end #   @vk = VkontakteApi.authorize(code: params[:code]) #      session[:token] = @vk.token #   id    -    session[:vk_id] = @vk.user_id redirect_to root_url end end 

ユーザーがアプリケーションを終了すると、単にセッションを消去します。

 class SessionsController < ApplicationController def destroy session[:token] = nil session[:vk_id] = nil redirect_to root_url end end 

トークンを受信すると、API自体を操作できます。

APIメソッド呼び出し


APIメソッドを呼び出すには、 VkontakteApi::Clientオブジェクトが必要です。 コンストラクタにトークンを渡すだけです。

次に、クライアント自体でメソッドを呼び出すことができます。 複合名を持つメソッドは、チェーンで呼び出されます: vk.users.get(params) 。 rubyコミュニティで採用されている規則に従って、メソッド名はsnake_case記述されますlikes.getListメソッドはvk.likes.get_listとしてvk.likes.get_listことができます。

すべてのAPIパラメーターには名前が付けられ、パラメーター名でインデックス付けされたハッシュとして渡されますvk.users.get(uid: 1)vk.users.get(uid: 1) 。 APIがコンマで区切られたパラメーターのオブジェクトのコレクションを受け取ることを期待する場合、配列として渡すことができますvkontakte_api自動的にそれvkontakte_api接着します(承認のscopeパラメーターも同様に処理されます)。 この場合、文字列の代わりに文字を使用できます。

そのため、現在のユーザーのニュースフィード、友人、グループが必要です。 ナビゲーションにユーザー名とアバターも表示します。 このデータを取得するためのnewsfeed.getgroups.getgroups.getおよびusers.getメソッドがそれぞれあります(ユーザーIDパラメーターを渡すことで後者を呼び出します)。 newsfeed.getの結果には、ユーザーとグループのIDを含むニュース自体が個別に含まれ、前述のユーザーとグループの配列が個別に含まれます。 ここに示されていないMainController#process_feedメソッドは、各ニュースにそのソース(投稿を書いたユーザーまたはグループ)をキーsource下に追加します。

 class MainController < ApplicationController def index #    API vk = VkontakteApi::Client.new(session[:token]) #     @user = vk.users.get(uid: session[:vk_id], fields: [:screen_name, :photo]).first #   @friends = vk.friends.get(fields: [:screen_name, :sex, :photo, :last_seen]) #   ,      @friends_online = @friends.select { |friend| friend.online == 1 } #  @groups = vk.groups.get(extended: 1) #    - - ;    @groups.shift #    raw_feed = vk.newsfeed.get(filters: 'post') #     @newsfeed = process_feed(raw_feed) end end 

メソッドの結果はHashie::Mashの形式で返されます。Mashhashie gemの標準Hash拡張で、 Hash内のこの要素のキーに対応する名前のメソッドを介して要素にアクセスできます( user.name == user[:name] )。

ナビゲーションでは、VKontakteから受け取った現在のユーザーのアバターと名前を表示する必要があります。

 <%= link_to vk_url(@user), target: '_blank' do %> <%= image_tag(@user.photo, width: 20) %> <%= "#{@user.first_name} #{@user.last_name}" %> <% end %> 

以下、アプリケーションで定義されたいくつかの単純なヘルパー( vk_urlname_foravatar_forなど)が使用されます-それらはすべて非常に簡単であり、必要に応じてここでコードを読むことができます。

次に、ページにニュースフィードを表示します。

 <!-- app/views/main/index.html.erb --> <% @newsfeed.each do |item| %> <tr> <td> <%= link_to vk_url(item.source), target: '_blank' do %> <%= image_tag avatar_for(item.source) %> <% end %> </td> <td class="wide"> <div class="pull-right"><%= formatted_time_for(item.date) %></div> <%= link_to name_for(item.source), vk_url(item.source), target: '_blank' %> <p><%=raw render_links(item.text) %></p> <% item.attachments.each do |attachment| %> <%= render 'attachment', attachment: attachment %> <% end if item.attachments? %> </td> </tr> <% end %> <!-- app/views/main/_attachment.html.erb --> <p> <% case attachment.type %> <% when 'link' %> <%= link_to attachment.link.title, attachment.link.url, target: '_blank' %> <% when 'photo' %> <%= image_tag attachment.photo.src_big %> <% when 'video' %> <%= image_tag attachment.video.image_big %> <% end %> </p> <div class="clearfix"></div> 

最後に、サイドバーの友人とユーザーグループに表示します。

 <!-- app/views/main/_sidebar.html.erb --> <div class="tab-pane active" id="friends_online"> <h6> </h6> <%= render 'friends', friends: @friends_online %> </div> <div class="tab-pane" id="friends"> <h6> </h6> <%= render 'friends', friends: @friends %> </div> <div class="tab-pane" id="groups"> <h6></h6> <%= render 'groups' %> </div> <!-- app/views/main/_friends.html.erb --> <table class="table"> <% if friends.empty? %> <tr> <td>  </td> </tr> <% else %> <% friends.each do |friend| %> <tr> <td> <%= link_to image_tag(friend.photo), vk_url(friend), target: '_blank' %> </td> <td class="wide"> <i class="icon-user"></i> <%= link_to "#{friend.first_name} #{friend.last_name}", vk_url(friend), target: '_blank' %> <br /> <%= online_status(friend) %> </td> </tr> <% end %> <% end %> </table> <!-- app/views/main/_groups.html.erb --> <table class="table"> <% if @groups.empty? %> <tr> <td>    </td> </tr> <% else %> <% @groups.each do |group| %> <tr> <td> <%= link_to image_tag(group.photo), vk_url(group), target: '_blank' %> </td> <td class="wide"> <i class="icon-comment"></i> <%= link_to group.name, vk_url(group), target: '_blank' %> </td> </tr> <% end %> <% end %> </table> 

ライブデモはここで見ることができます (慎重に、無料のheroku)。 VKontakteには何も書き込まれません-すべてのAPIメソッドは、データを読み取り、ページに表示するためにのみ使用されます。 すべてのコードはGithubにあります。

vkontakte_apiに関するその他の資料


Source: https://habr.com/ru/post/J151585/


All Articles