LoginSignup
8
8

More than 5 years have passed since last update.

CoreTweetでPIN番号を手入力せずに認証

Last updated at Posted at 2018-05-13

お久しぶりです.N.Mです.最近は趣味でTwitter APIを使ったGUIアプリケーションをC#で作ってます(C#だとGUIアプリケーションが作りやすいと思ったので).今後不定期で,その制作過程で大変だったことを発信していければと思います.今回はその第1弾.
(次回はウィンドウサイズの調整について

今はこんな感じの,直近のツイートから誰がTL上にいるのかをリストアップするアプリを作っています.
(アプリケーション自体は,ここで配布しております.今後も更新予定です!)
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
TLMem.PNG

CoreTweetの認証

Twitter APIについてはC#のライブラリ"CoreTweet"を利用していまして,ここにも認証の仕方が書いてあるのですが,そのアカウントでアプリを使うことを認証した後に,7桁のPINコードが表示されます.APIをつかうために,そのPINコードを手動で入力するか,HTML解析するかしてOAuth.GetTokensに渡す必要があります.手動で入力する方法はたくさん情報が出てきたので,最初はそれを採用してましたが,使ってるうちに手入力が面倒になったので,今回 HTML解析による取得 に挑戦しました.

環境・前提

  • Visual Studio 2017で開発
  • Twitter APIの利用のためにCoreTweetを使用
  • WPFアプリケーションを制作(Formsではない)

仕組み

認証ページは最初のURLはhttps://api.twitter.com/oauth/authorizeの後にいろいろ文字列がついた状態になっています.そして,認証してもしなくても,最終的にURLがhttps://api.twitter.com/oauth/authorizeになります.認証した場合はHTML内に

<code>7桁のPINコード</code>

が埋め込まれています(そして<code>タグはページのこの部分にしか出てきません).なので,やるべきこととしては

  1. 認証ページを表示して,ユーザに認証させる
  2. ページのリンクがhttps://api.twitter.com/oauth/authorizeになったら,ページのHTMLコードを取得する.
  3. HTMLソースから<code>の文字列を検索し,あれば後ろの7桁のPINコードを取り出し,認証する(なければ認証失敗のエラーを出す).

となります.

1. 認証ページを表示させる

CoreTweetの日本語WikiだとSystem.Diagnostics.Process.Startで認証ページを表示していますが,HTMLソースを抜き取るのが難しそうだったので,認証ページの表示はWPFアプリケーションにWebBrowserのコンポーネントを埋め込むことにしました('twitterWeb'と命名しました).で,WebBrowserNavigateメソッドで認証ページのURLに飛べば表示できます.

TLMemAuth.PNG
こんな感じ.ここから,ユーザが認証したら,すぐにAPIが使える状態にしていきます.

2. ページのURIの取得,HTMLコードの取得

ここでいろいろつまづきました.つまづいたポイントとしては

  • WebBrowserがnullで参照できなかった.
  • WPF(System.Windows.Controls )ではなく,Formsのほう(System.Windows.Forms)の情報ばかり出て混乱した.
  • WPFのWebBrowserからHTMLを抜き取る方法が分からなかった.

の3点ですね.

まず,1点目の参照の問題は,Navigateメソッドを呼び出したあとに,WebBrowserのURLを確認しようとしたんですけど,そのタイミングだと,まだ処理が完了してないのでnullが返ってきてしまうそうです.なので,WebBrowserの処理が完了した際に呼ばれるイベントハンドラLoadCompletedで,もろもろの処理を行います.

twitterWeb.Navigate(session.AuthorizeUri);
LoadCompletedEventHandler twitterWebUpdate = null;

twitterWebUpdate = (tSender, e) =>
{
    string pin = "";
    string finishedUrl = @"https://api.twitter.com/oauth/authorize";
    string url = twitterWeb.Source.AbsoluteUri;
    if (url == finishedUrl)
    {
        //ここにHTMLソースの取得とPINコードの抽出処理を実装                
    }                
};
twitterWeb.LoadCompleted += twitterWebUpdate;

finishedURLに認証後に行くはずのページのURLを,URLtwitterWebの現在のページのURLを格納しておき,この2つが一致したら認証後のページに行ったと判断します.

WebBrowserからのHTMLの取得ですが,Visual StudioのプロジェクトでCOMのmshtmlを参照するようにして,mshtml.IHTMLDocument2を介して,取得するようです(参考).

HTML抽出部分を加えるとこんな感じ

twitterWeb.Navigate(session.AuthorizeUri);
LoadCompletedEventHandler twitterWebUpdate = null;

twitterWebUpdate = (tSender, e) =>
{
    string pin = "";
    string finishedUrl = @"https://api.twitter.com/oauth/authorize";
    string url = twitterWeb.Source.AbsoluteUri;
    if (url == finishedUrl)
    {
         mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)twitterWeb.Document;
         string html = doc.body.innerHTML;
        //ここにPINコードの抽出処理を実装                
    }                
};
twitterWeb.LoadCompleted += twitterWebUpdate;

3. PINコードの抽出

ここまでできれば,あとはhtmlから<code>の文字列をIndexOfメソッドで検索して,
パパパっとSubstringメソッドでPINコードの7桁の数字を抽出して終わり!

twitterWeb.Navigate(session.AuthorizeUri);
LoadCompletedEventHandler twitterWebUpdate = null;

twitterWebUpdate = (tSender, e) =>
{
    string pin = "";
    string finishedUrl = @"https://api.twitter.com/oauth/authorize";
    string url = twitterWeb.Source.AbsoluteUri;
    if (url == finishedUrl)
    {
         mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)twitterWeb.Document;
         string html = doc.body.innerHTML;
         int codeIndex = html.IndexOf("<code>");
         if (codeIndex >= 0)
         {
             //<code>があった=認証に成功した場合
             pin = html.Substring(codeIndex + 6, 7);
             t = OAuth.GetTokens(session, pin);
         }
         else
         {
             //<code>がなかった=認証に失敗した場合
             MessageBox.Show("認証に失敗しました.");
         }                
    }                
};
twitterWeb.LoadCompleted += twitterWebUpdate;

これでTokens変数 tを介して,Twitter APIをいじることができます.

補足

  • 認証ページにはほかにもリンクがありましたが,そこに飛ぼうとすると新しいタブで開かれるためか,Internet Explorerが新規で実行されます.WebBrower側のページは認証のリンク以外では飛ばなかったので,この仕組みでもうまくいっているようです.
8
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8