C# bit.ly でURL短縮

Visual Studio 2010 Express で C# 、.NET Framework 4.0 で
bit.ly の Web API を呼び出してURL短縮するツールを作ってみる。

Amazon のURLがTwitterに貼るときにクソ長いので、
毎回 bit.ly で短縮かけてる (amazon.co.jp ドメインは bit.ly で短縮すると amzn.to になる)けれど
そのために bit.ly のページのタブを開いておくのは面倒なので、
Windowsクライアントアプリケーションでもう少し楽にできないかなーと思ったのが動機。

  • bit.ly のアカウントを作る
    • Web API にアクセスするにはアカウントを作る必要があるようなので bit.ly の SIGN UP からアカウントを登録しておく。
    • Twitter や Facebook のアカウントでログインできるようにできるが、
      アカウント登録後に SETTING>PROFILE でメールアドレスの有効チェックとかパスワード設定をしておかないとアプリケーションの登録ができないかも?
  • API_KEY でのURL短縮
    • Web API の呼び出しは通常 OAuth で認証してアクセストークン取得して、みたいな流れでやるけれど、
      まずは手軽な API_KEY を使用してURL短縮を試してみる。
      ちなみに API_KEY を使った呼び出し方は DEPRECATED (非推奨) 。今後廃止される可能性もあるので注意。
    • SETTING>ADVANCED で「Legacy API KEY」という項目に Login ID と API key が記載されているのでメモしておく。
      Firefoxだと選択不可領域になっていてコピペできなくて地味に不便。IEだと選択可能みたいだが。
    • Bitly API Documentation - /v3/shorten にURL短縮の呼び出し方が記載されている。
      要は、Login ID と API KEY、それから短縮させたいURLを渡せば、JSON形式、XML形式または短縮URLだけの文字列が取得できる。
      例えば http://google.com/ の短縮URLだけを取得したければ、以下のようなURLでHTTPアクセスさせればいい。
https://api-ssl.bitly.com/v3/shorten?login=XXXXX&apiKey=XXXXX&longUrl=http://google.com/&format=txt
  • C# でやるならば、System.Net.WebClient でやるのが手っ取り早い。
    渡すURLのエスケープ処理も Uri.EscapeUriString() で忘れずにやっておくこと。
// API_KEY による認証パラメータ
string STR_AUTH_APIKEY = "login={0}&apiKey={1}";

// URL短縮コマンドURL
string STR_URL_SHORTEN = @"https://api-ssl.bitly.com/v3/shorten?{0}&longUrl={1}&format=txt";

WebClient wc = new WebClient();
Stream stream = null;
StreamReader sreader = null;

string url;

string strResult;

try
{
        // URL短縮 shorter の呼び出しURL作成
        url = string.Format(STR_URL_SHORTEN, string.Format(STR_AUTH_APIKEY, "[STR_LOGIN_ID]", "[STR_API_KEY]"), 
            Uri.EscapeUriString("[LONGURL]"));
                
        stream = wc.OpenRead(url);
        sreader = new StreamReader(stream);

        strResult = sreader.ReadToEnd();

        // 結果の出力
        MessageBox.Show(strResult);
}
catch (Exception ex)
{
        MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
        if (stream != null) { stream.Close(); }
        if (sreader != null) { sreader.Close(); }
}
  • OAuth での認証を行ってからのURL短縮
    • OAuth の認証を行うためにアプリケーション固有の CLIENT_ID や CLIENT_SECRET が必要になるので、bit.ly でアプリケーションを登録する。
      SETTING>ADVANCED で、OAuth Applications のリンクからOAuthアプリケーション管理ページが開けるので
      Register an application からアプリケーション登録を行う。
      アプリケーション名やリダイレクト先URL情報などを入力する(私は自サイトURLを入れたが、 bit.ly 自身や google とかのURLでもいいのかどうかは未確認)
      登録すれば CLIENT_ID や CLIENT_SECRET がOAuthアプリケーション管理ページに表示されるようになるのでメモしておく。
    • Bitly API Documentation - Authentication の方法に従って、HTTP POST通信で CLIENT_ID や CLIENT_SECRET、bit.ly アカウントのユーザー名、パスワードを送信してアクセストークンを取得する。
      なお、アクセストークンの取得方法は認証コードを使う方法(Webアプリケーション向き?)とユーザー名、パスワードを使う方法と二種類ある。今回は後者。
https://api-ssl.bitly.com/oauth/access_token
Header: Authorization: Basic XXXXXXXX ← 「CLIENT_ID:CLIENT_SECRET」をBase64でエンコードした文字列
POST Data: 
grant_type=password&username=XXXXX&password=XXXXX
  • アクセストークンはJSON形式で取得できるので、System.Runtime.Serialization.Json でパースするとかが必要。
    参照設定で System.Runtime.Serialization の追加をしておく必要あり。
  • アクセストークンが取得できれば、パラメータがLOGIN_IDとAPI_KEYからアクセストークンに変わるだけでAPI_KEYの時と同様のやり方で短縮URLが取得できる。
[DataContract]
public class BitlyJsonAToken
{
    [DataMember]
    public string access_token;
}

string STR_AUTH_OAUTH = @"access_token={0}";

// OAUTH 認証URL
string STR_URL_OAUTH = @"https://api-ssl.bitly.com/oauth/access_token";

// URL短縮コマンドURL
string STR_URL_SHORTEN = @"https://api-ssl.bitly.com/v3/shorten?{0}&longUrl={1}&format=txt";

WebClient wc = new WebClient();
Stream stream = null;
StreamReader sreader = null;

string token;
string url;

string strResult;

try
{
        // OAUTH アクセストークン取得
        NameValueCollection postdata = new NameValueCollection();
        postdata.Add("grant_type", "password");
        postdata.Add("username", "[STR_USERNAME]");
        postdata.Add("password", "[STR_PASSWORD]");
        wc.Headers.Add("Authorization", "Basic " + 
            Convert.ToBase64String(Encoding.ASCII.GetBytes(
                string.Format("{0}:{1}", "STR_CLIENT_ID", "[STR_CLIENT_SECRET]")
            ))
        );

        strResult = Encoding.Default.GetString(wc.UploadValues(STR_URL_OAUTH, postdata));

        // JSON形式のデータからアクセストークン抽出
        DataContractJsonSerializer jserial = new DataContractJsonSerializer(typeof(BitlyJsonAToken));
        MemoryStream mstream = new MemoryStream(Encoding.Default.GetBytes(strResult));
        BitlyJsonAToken jdata = (BitlyJsonAToken)jserial.ReadObject(mstream);

        if (string.IsNullOrEmpty(jdata.access_token))
        {
            throw new Exception("アクセストークンの取得に失敗しました。");
        }
        token = jdata.access_token;

        // URL短縮 shorter の呼び出しURL作成
        /url = string.Format(STR_URL_SHORTEN, 
string.Format(STR_AUTH_OAUTH, token), Uri.EscapeUriString("[LONGURL]"));

        stream = wc.OpenRead(url);
        sreader = new StreamReader(stream);

        strResult = sreader.ReadToEnd();

        // 結果の出力
        MessageBox.Show(strResult);
}
catch (Exception ex)
{
        MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
        if (stream != null) { stream.Close(); }
        if (sreader != null) { sreader.Close(); }
}
test
test
test