ソフトウェア」カテゴリーアーカイブ

小学生にも情報教育をば。

どうもみむらです。

いきなり質問ですが、下記の2つの文章の共通点をあげてください。

A.里の秋。

静かな静かな 里の秋
お背戸に木の実の 落ちる夜は
ああ 母さんとただ二人
栗の実 煮てます いろりばた

B.静かな湖畔

静かな湖畔の 森のかげから
もう起きちゃいかがと カッコが鳴く
カッコ カッコ
カッコ カッコ カッコ

 

はい、もうわかりましたよね。

こたえは、誰しもがわかるあれです。

続きを読む

Console Twitter を公開しました。

image

ておくれてない、まだ、まだだっ!!
ということでみむらです。

先日の OAuth の記事 を書いた後、やっぱりクライアントを作りましょうということで。

ttytter っぽいものを意識しましたが、自分が使いやすいように作ってみました。

 

Microsoft .NET Framework 3.5 がある環境であれば実行可能です。
(Windows 7 では標準搭載)

 

http://mimumimu.net/software/#ConsoleTwitter
上記URL よりダウンロード可能です。

 

ただつぶやくだけではなく、下記のコマンドを使うことで様々な操作も可能です。

/rep リプライ一覧を表示
/rep (番号) (ツイート) リプライを送ります。

ex) /rep 01 ておくれてない!

/fav お気に入りに登録したツイートを表示します。
/fav (番号) お気に入りに登録します。
/unfav (番号) お気に入りを解除します。
/rt (番号) リツイートします。
/find (テキスト) 指定したテキストで Twitter 上のツイートを検索して表示します。

 

コンソールで表示されて、全部がキーで行うということで、
シンプルでかつ、操作も覚えやすいのでは無いでしょうか。

 

ということで、よろしくお願いします-。


追記:ソースコード公開しました。

https://github.com/mimura1133/Console-Twitter

Twitter の OAuth 1.0 認証を自分でコード書いてやってみた。

みむらです。

ひとまず、おべんきょーということで、後からも分かるように、
変数を多く使って文字列出力をふんだんに出しながら。

ソースコードが、海から来た侵略者に侵略されていますが、
そんなもの全く気にしない、むしろ、侵略されていないでゲソ!

—-

参考資料:

* http://oauth.net/core/1.0
* http://hueniverse.com/oauth/guide/authentication/
* https://dev.twitter.com/docs/auth/authorizing-request/

—-

https://gist.github.com/1395485

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;

/*
 * この辺を参考に:
 * 
 * http://oauth.net/core/1.0
 * http://hueniverse.com/oauth/guide/authentication/
 * https://dev.twitter.com/docs/auth/authorizing-request
 */

namespace Direct_Commit_Twitter
{
    class Program
    {

        static void Main(string[] args)
        {
            //
            // 使うパラメータは次のようなもの。
            //
            // OAuth Consumer Key       : Consumer Key そのまま。
            // OAuth Token              : Access Token そのまま。 (今回はこれも取得。)
            // OAuth Nonce              : ランダム文字列を与える。 (毎回変更する。)
            // OAuth Signature          : OAuth Signature 以外の値で HMAC-SHA1 をとった値。
            // OAuth Signature Method   : Twitter は HMAC-SHA1 指定っぽいので HMAC-SHA1.
            // OAuth Time Stamp         : UNIX 時間 (1970-01-01 UTC からの秒数) を与える。
            //                          : (今回は GetUNIXTime() メソッドで取得します。)
            // OAuth Version            : 今回は 1.0 を使うので、1.0.
            //

            string consumer_key = "oDcUp76alv6VctYvRx2g";
            string consumer_secret = "mg1U9TEFVafIPQm0Y0YuLR8EZatXiDBvPLiiCConzbg";

            string access_token = "";
            string access_secret = "";

            string tweet_text = "ゲソーゲソー";

            /************************ 以下、黙々と処理 ********************/

            string[] verify_token;

            if (access_token == "" || access_secret == "")
            {

                #region 01. Request Token を取得しなイカ?
                {
                    Console.WriteLine("01 - Token を取得しなイカ?");
                    Console.WriteLine("-------------------------------------------------");

                    Random rand = new Random();
                    byte[] nonce_b = new byte[64];

                    rand.NextBytes(nonce_b);

                    string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                    long unixtime = GetUNIXTime();

                    //
                    // OAuth Signature 生成のために、それ以外で仮のリクエスト文字列を作成する。
                    // この際、各パラメータは ABC 順にソートされている必要がある。
                    //
                    string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/request_token");
                    signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, null, null, null));

                    //
                    // ちゃんとしたリクエスト文字列を作る。
                    //
                    string signature = GetSignature(consumer_secret, null, signature_request);
                    string param = MakeParamString(consumer_key, nonce, signature, unixtime, null, null, null);

                    DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, null, null, null);
                    return;
                    //
                    // 問い合わせ。
                    //
                    Console.WriteLine("* Access : https://api.twitter.com/oauth/request_token?" + param);
                    HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/request_token?" + param);
                    hwr.Method = "POST";
                    WebResponse ret = hwr.GetResponse();
                    verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&');

                    ret.Close();

                    Console.WriteLine();
                    Console.WriteLine("Response : ");
                    foreach (string s in verify_token)
                        Console.WriteLine("> " + s);
                }
                #endregion

                #region 02. Access Token を取得しなイカ?
                {
                    Console.WriteLine();
                    Console.WriteLine("02 - Access Token を取得しなイカ?");
                    Console.WriteLine("-------------------------------------------------");

                    string request_token = "";
                    string request_secret = "";

                    //
                    // ブラウザ開いて認証。
                    //
                    foreach (string s in verify_token)
                    {
                        int p = s.IndexOf("oauth_token=");
                        if (p != -1)
                        {
                            request_token = s.Substring(p + "oauth_token=".Length);
                            break;
                        }
                    }
                    Console.WriteLine("- OAuth Token : " + request_token);
                    Console.WriteLine("* Browser Open : https://twitter.com/oauth/authorize?oauth_token=" + request_token);
                    Process.Start("https://twitter.com/oauth/authorize?oauth_token=" + request_token);

                    //
                    // PIN を入力させる。
                    //
                    Console.Write("\nINPUT PIN : ");
                    string pin = Console.ReadLine();

                    foreach (string s in verify_token)
                    {
                        int p = s.IndexOf("oauth_token_secret=");
                        if (p != -1)
                        {
                            request_secret = s.Substring(p + "oauth_token_secret=".Length);
                            break;
                        }
                    }


                    //
                    // 以下 Twitter ともくもく通信。
                    //

                    Random rand = new Random();
                    byte[] nonce_b = new byte[64];

                    rand.NextBytes(nonce_b);

                    string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                    long unixtime = GetUNIXTime();

                    //
                    // Signature 生成のための一時的なリクエスト文字列を作成。
                    //
                    string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/access_token");
                    signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, request_token, pin, null));

                    string signature = GetSignature(consumer_secret, request_secret, signature_request);
                    string param = MakeParamString(consumer_key, nonce, signature, unixtime, request_token, pin, null);

                    DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, request_token, request_secret, pin);

                    //
                    // 問い合わせ。
                    //
                    Console.WriteLine("* Access : https://api.twitter.com/oauth/access_token?" + param);
                    HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/access_token?" + param);
                    hwr.Method = "POST";
                    hwr.Headers.Add("Authorization", "OAuth");

                    WebResponse ret = hwr.GetResponse();
                    verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&');

                    ret.Close();

                    Console.WriteLine();
                    Console.WriteLine("Response : ");
                    foreach (string s in verify_token)
                    {
                        if (s.IndexOf("oauth_token=") != -1)
                            access_token = s.Substring(s.IndexOf("=") + 1);

                        if (s.IndexOf("oauth_token_secret=") != -1)
                            access_secret = s.Substring(s.IndexOf("=") + 1);

                        Console.WriteLine("> " + s);
                    }
                }
                #endregion

            }

            #region 03. つぶやかなイカ?
            {
                Console.WriteLine();
                Console.WriteLine("03 - つぶやかなイカ?");
                Console.WriteLine("-------------------------------------------------");
                
                Random rand = new Random();
                byte[] nonce_b = new byte[64];

                rand.NextBytes(nonce_b);

                string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                long unixtime = GetUNIXTime();

                string tweet_data = UrlEncode(tweet_text);

                string signature_request = "POST&" + UrlEncode("https://api.twitter.com/1/statuses/update.xml");
                signature_request += "&include_entities%3Dtrue%26" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, access_token, null, tweet_data));
                string signature = GetSignature(consumer_secret, access_secret, signature_request);

                string header_param = "OAuth oauth_consumer_key=\"" + UrlEncode(consumer_key) + "\",oauth_signature_method=\"HMAC-SHA1\"," +
                                      "oauth_timestamp=\"" + unixtime + "\",oauth_nonce=\"" + UrlEncode(nonce) + "\"," +
                                      "oauth_version=\"1.0\",oauth_token=\"" + UrlEncode(access_token) + "\"," +
                                      "oauth_signature=\"" + UrlEncode(signature) + "\",";

                DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, access_token, access_secret, null);
                Console.WriteLine("* Access : https://api.twitter.com/1/statuses/update.xml");
                Console.WriteLine("* Tweet at : " + tweet_text);

                HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/1/statuses/update.xml");
                hwr.Method = "POST";
                hwr.ServicePoint.Expect100Continue = false;
                hwr.Headers.Add(HttpRequestHeader.Authorization, header_param);
                hwr.ContentType = "application/x-www-form-urlencoded";
                var s = new StreamWriter(hwr.GetRequestStream());
                s.Write("status=" + tweet_data + "&include_entities=true");
                s.Close();

                WebResponse ret = hwr.GetResponse();
                Console.WriteLine();
                Console.WriteLine("Response:");
                Console.WriteLine("> "+(new StreamReader(ret.GetResponseStream()).ReadToEnd()));

            }
            #endregion
        }

        // UNIX 時間を返す。
        static long GetUNIXTime()
        {
            return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
        }

        // URLエンコード (どうやらエスケープ文字は大文字にしないといけないらしい。)
        static string UrlEncode(string str)
        {
            string s = HttpUtility.UrlEncode(str);
            return _UrlEncodeUpper(s);
        }

        static string _UrlEncodeUpper(string str)
        {
            int p = str.IndexOf("%");
            if (p != -1)
            {
                str = str.Substring(0, p) + str.Substring(p, 3).ToUpper() + _UrlEncodeUpper(str.Substring(p + 3));
            }
            return str;
        }

        // パラメータ文字列を生成
        static string MakeParamString(string oauth_consumer_key, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_verifier, string status)
        {
            string param = "oauth_consumer_key=" + oauth_consumer_key + "&oauth_nonce=" + oauth_nonce;

            if (oauth_signature != null)
                param += "&oauth_signature=" + oauth_signature;

            param += "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=" + oauth_timestamp;

            if (oauth_token != null)
                param += "&oauth_token=" + oauth_token;

            if (oauth_verifier != null)
                param += "&oauth_verifier=" + oauth_verifier;
            
            param += "&oauth_version=1.0";

            if (status != null)
                param += "&status=" + status;

            return param;
        }

        // Consumer Secret をKey とした、リクエスト文字列のハッシュを求める。
        static string GetSignature(string consumer_secret, string access_token_secret, string param)
        {
            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = Encoding.ASCII.GetBytes(consumer_secret + "&" + access_token_secret);
            byte[] hash = hmacsha1.ComputeHash(Encoding.ASCII.GetBytes(param));
            
            return Convert.ToBase64String(hash);
        }

        // よくやる出力をまとめてみる。
        static void DebugParamOut(string oauth_consumer_key, string oauth_consumer_secret, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_token_secret, string oauth_verifier)
        {
            Console.WriteLine("- OAuth Consumer Key = " + oauth_consumer_key);
            Console.WriteLine("- OAuth Consumer Secret = " + oauth_consumer_secret);
            Console.WriteLine("- OAuth Nonce = " + oauth_nonce);
            if (oauth_signature != null)
                Console.WriteLine("- OAuth Signature = " + oauth_signature);
            Console.WriteLine("- OAuth Time Stamp = " + oauth_timestamp);
            if (oauth_token != null)
                Console.WriteLine("- OAuth Access Token = " + oauth_token);
            if (oauth_token_secret != null)
                Console.WriteLine("- OAuth Access Token Secret = " + oauth_token_secret);
            if (oauth_verifier != null)
                Console.WriteLine("- OAuth Verifier = " + oauth_verifier);
        }
    }
}

 

とりあえず、記事自体がむちゃくちゃ長くなるので、

解説云々は次の記事に。

NuGet で簡単にパッケージを導入する。

案外知られていない気がする。

Ruby や Python では、パッケージを簡単にインストールして利用する方法があって、

Ruby では gem
Python では easy_install

がこれに該当しますかね。

 

.NET にも NuGet という同様の仕掛けが存在し、
利用することが出来ます。

.NET開発の新標準「NuGet」入門(前編) - @IT
詳細な解説についてはここのあたりを見ておくと良いかと思います。

 

注:対象は Visual Studio 2010 以降の Visual Studio に限ります。


分からない人向け:

たとえば、今から Twitter の機能を利用したソフトウェアを作ろうとあなたが思ったとき、
以下の選択肢から一つ選ぶことになると思います。

1.自分で OAuth の認証書いて、アクセスするライブラリを作る。
2.インターネットから既存のライブラリをとってくる。

現代においては、教育目的を除いて 1 を選ぶことは殆ど無いかと思います。
(気に入る形に出来ない場合や、そもそも無い場合は作ることにはなりますが。)

 

となると、現実的な回答としては、2となりますが、
インターネットから探してきて、インストールして・・っていうのは面倒で、
カタカタっと名前を打ったりして、簡単にインストール出来た方がいいわけです。

インストーラが面倒くさいということも考えられるでしょうし、
そもそも、インストーラが無くて、自分で組み込まなければならない場合は面倒になりますし、
友人に教えながら作業するという場合や、雑誌にやり方を載せる場合などにおいては、
友人や読者にファイルのありかを教えなければなりませんし、
複数台に組み込む時なども・・・・ とまぁ、非常にナンセンスな訳です。

 

そんなわけで、 Python の easy_install や Ruby の gem
そして、この記事で触れる .NET の NuGet などのパッケージ管理ソフトウェアを用いることにより、
単純明快でかつ高速に、ライブラリを用意して使い始めることが出来ます。

また、ライブラリに更新があった場合、手動で入れた場合はまたインストールをしなければなりませんが、
大抵こういうパッケージ管理ソフトでは、アップデートも簡単に行える仕様が備わっています。

 

という感じで、長文になりましたが、
導入~更新 まで、ライブラリの利用に関するあらゆることを簡単に使えるようにした物。
それが、パッケージ管理ソフトウェア ということになります。


というわけで本題。

 

1.導入

http://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c
上記URL より、 Download をクリックしてダウンロード、インストーラを起動します。

 

image

上のような画面が出ますので、インストールをクリックし、導入を完了させます。

 

2.開発を始める。

image

いつものように、ソリューションを開きます。

 

3.パッケージを導入する。

image

メニューバーの 「ツール」 → 「Library Package Manager」 → 「Package Manager Console」 をクリックします。

image

コンソールが立ち上がった。

 

今回は例として、

http://www.twitterizer.net/
上記URL にて公開している、「Twitterizer」を導入してみます。

 

image

Install-Package twitterizer

と打って、Enter で実行。

 

image

自動的に依存関係が解決された状態で、参照にライブラリが加わり、使えるようになる。

 

3.コード書いて動かす。

 

image

 

とりあえずこんな感じ。

 


というわけで、適当に超基本的なコマンドだけ、対応表にするとこんな感じなのかなぁ。

コマンド

NuGet

gem

easy_install

hoge をインストール Install-Package hoge gem install hoge easy_install hoge
hoge を更新 Update-Package hoge gem update hoge easy_install –U hoge
全部更新 Update-Package gem update easy_install –U
hoge を削除 Uninstall-Package hoge gem uninstall hoge  

NuGet のコマンドについては、

http://www.atmarkit.co.jp/fdotnet/chushin/nuget_01/nuget_01_02.html
上記URL に大体まとまっているかと思います。

 

そんな感じで。であであ。

SyntaxHighlighter でコードを示したあと、ずたずたに書式が崩れる不具合の対応

どうもみむらです。

とっても見づらいブログ記事で本当に申し訳ございませんでした。
変に改行とかが入って、おそろしく見づらかったことかと思います。

 

ということで、今回はそれの犯人と、
修正の方法。

 

原因:

<pre> </pre> 以降の HTML データが上手く処理されず、
テキストデータとして改行がなされたところに <br /> たぐが自動挿入されたため。

 

対策:

WordPress 内の wpautop というフィルタによって自動挿入されるため、

http://urbangiraffe.com/plugins/disable-wpautop/
上記URL より入手できるプラグインを導入して処理を除去。

 

結果:

対策前:

image

上記のように、文と文が離れていて大変読みづらい状況でした。

 

対策後:

image

本来、当方が記述した際の正しい記述にて表示が行われ、
段落ごとに文章がまとまり、見やすくなっています。

 


というわけで、
WordPress で <pre> を利用してコードを記述している方で、
ずたずたにスタイルが崩れてしまった場合、利用してみてはいかがでしょうか。

ちなみに、RSS フィードに対しても wpautop は適用され、
改行が挿入されますが、
このプラグインでは RSS フィードに対しても有効であり、
かつ、Wordpress をアップデートしても有効となるため、かなり有用かと思います。