きりの日記
Kiri_Feather
Hatena::Blog
hatenablog://blog/17680117127128274073
TwitterのAPI がv1.1になるそうで
hatenablog://entry/17680117127128274131
2013-01-16T21:49:31+09:00
2013-01-16T21:49:31+09:00 Twitterで定期的に投稿するのも面倒なんで、こちらで済ませてしまおうかなとかなんとか。Twitterクライアント&サービス API1.1対応状況リストこれを張っておきたかっただけです。なんでこんなリストを用意したのか、という背景をちょっと書いておきます。 TwitterのAPIについてのお話なんですが、開発関係者だけでなく、一般ユーザーにも影響のあるお話なので軽く目を通して頂ければ幸い。 これまでのおさらい Twitterが提供しているAPIにはバージョンがあります。これは、TwitterがとあるAPIの機能・呼び出し方・応答内容などを変更してしまうと、その瞬間からそのAPIを使っているサ…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>で定期的に投稿するのも面倒なんで、こちらで済ませてしまおうかなとかなんとか。</p><p><a href="https://docs.google.com/spreadsheet/ccc?key=0ArnMQU9tQoZpdENJTmo5ZlJIbi1JLTJLeGJMVk81TUE">Twitterクライアント&サービス API1.1対応状況リスト</a></p><p>これを張っておきたかっただけです。</p><p>なんでこんなリストを用意したのか、という背景をちょっと書いておきます。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>についてのお話なんですが、開発関係者だけでなく、一般ユーザーにも影響のあるお話なので軽く目を通して頂ければ幸い。</p>
<div class="section">
<h4>これまでのおさらい</h4>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>が提供している<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>にはバージョンがあります。これは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>がとある<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の機能・呼び出し方・応答内容などを変更してしまうと、その瞬間からその<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使っているサービスやクライアント(以下クライアントでまとめます)がモロに影響を受けて正しく動作しなくなってしまうためです。そこで、新しいバージョンの<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を設けて、各クライアントが新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>に対応するまで新旧両方の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を提供することで時間に余裕をもたせていたわけです。というのは建前で、これまではバージョン変えずに応答内容の変更とかよくあったわけですが、まぁ、それは置いといて。<br />
で、現在<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>には2つのバージョンがあります。1.0と1.1です。数年間<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を提供していたわりにバージョンが少ないのは、初期の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>はバージョニングされておらず、現在それらの<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>は無くなっているためです。</p>
</div>
<div class="section">
<h4>現在</h4>
<p>現在使える<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>は1.0と1.1の2つのバージョンです。つまり、今がまさに移行のための猶予期間なわけです。昨年の10月頃だったか、1.1がお目見えし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>から開発者へ「さっさと移行しろ」とアナウンスが出されました。期限付きで。<br />
旧来の1.0系<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>は2013年3月5日を持って使えなくなります。公開から約半年の猶予期間ですね。</p><p><span class="deco" style="font-size:small;color:#FF0000;">追記 2013/06/12 1.0系<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の停止は当初予定日から延期されていましたが、本日2013/06/12未明に停止されました。</span><br />
</p>
</div>
<div class="section">
<h4>今後</h4>
<p>既に残り2ヶ月を切っており、各クライアントは対応作業を始めています。ただ、すべてのクライアントが対応するわけではなく、これを節目と開発をやめるクライアントも出てきています。すなわち1.1に対応せず、3月5日を以って使えなくなるクライアントもあるわけです。<br />
現在は様々な<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>クライアントが使われているわけですが、「自分の使っているクライアントは今後も使い続けられるのか?使い続けられないなら他にどんなクライアントが選択肢としてあるのか?」ってのが分かると便利だろうと思い、件のリストを作ったわけです。作ったといっても、私はひな形しか用意してないんですけどね。<br />
クライアントは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>公式のものもありますし、Webも使えるので最終的にはどうとでもなるでしょう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>自体がなくなるわけじゃないので。</p><p>件のリスト、誰でも編集可能なので、ご自分の使っているサービスやクライアントが載っていなければ追記してみて下さい。また、対応状況や開発状況など情報が有りましたら更新していただければ、みんなが幸せになれるかな、と思います。</p><p>ここまで書いてきてなんですが、結構多くのクライアントが1.1対応予定あるみたいで一安心です。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>は過剰なブームを二山ぐらい超えて、アレヤコレヤと問題も出てきたりして落ち着いたんだか下火になったんだか微妙なところに差し掛かっているなーと思う今日このごろ。このまま消えるのか一線を保って定着するのか分かりませんが、乗りかかった船なんでボチボチ追従していくつもりです。</p><p>でわでわ</p>
</div>
Kiri_Feather
InstallShield 2011 Limited Edition
hatenablog://entry/17680117127128274259
2011-06-08T10:50:32+09:00
2011-06-08T10:50:32+09:00 .NET FrameworkベースのWindows フォーム アプリケーションのインストーラーを作った時の話。 まずは環境から。 OS: Windows7 Pro (32bit) IDE: Visual Studio 2010 Pro フレームワーク: .NET Framework 4.0 Full 開発言語: Visual Basic インストーラー: InstallShield 2011 Limited EditionInstallShieldのLimited Editionは、VS2010のPro以上なら無料で使えるので助かります。今回初めて使ったのですが、パッと見分かりやすくてホホホィ…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/.NET%20Framework">.NET Framework</a>ベースの<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a> フォーム アプリケーションの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%E9">インストーラ</a>ーを作った時の話。</p><br />
<p>まずは環境から。</p><br />
<p>OS: <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows7">Windows7</a> Pro (32bit)<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/IDE">IDE</a>: <a class="keyword" href="http://d.hatena.ne.jp/keyword/Visual%20Studio">Visual Studio</a> 2010 Pro<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%20.NET"> .NET</a> Framework 4.0 Full<br />
開発言語: <a class="keyword" href="http://d.hatena.ne.jp/keyword/Visual%20Basic">Visual Basic</a><br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%E9">インストーラ</a>ー: InstallShield 2011 Limited Edition</p><p>InstallShieldのLimited Editionは、VS2010のPro以上なら無料で使えるので助かります。今回初めて使ったのですが、パッと見分かりやすくてホホホィっと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%E9">インストーラ</a>ーが作れちゃいます。</p><br />
<p><a href="http://www.atmarkit.co.jp/fdotnet/chushin/introwinform_12/introwinform_12_02.html">http://www.atmarkit.co.jp/fdotnet/chushin/introwinform_12/introwinform_12_02.html</a></p><br />
<p>が、普通にアシスタントに沿って進めて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>すると、こんな警告が出ます。</p>
<blockquote>
<ul>
<li>6245: One or more of the project's components contain<a class="keyword" href="http://d.hatena.ne.jp/keyword/%20.NET"> .NET</a> properties that require the<a class="keyword" href="http://d.hatena.ne.jp/keyword/%20.NET"> .NET</a> Framework. It is recommended that the release include the<a class="keyword" href="http://d.hatena.ne.jp/keyword/%20.NET"> .NET</a> Framework.</li>
</ul>
</blockquote>
<p>「<a class="keyword" href="http://d.hatena.ne.jp/keyword/.NET%20Framework">.NET Framework</a>に依存しているファイルをインストールするから、セットアップにも<a class="keyword" href="http://d.hatena.ne.jp/keyword/.NET%20Framework">.NET Framework</a>含めるのオススメ」って事なんだけど、警告だけなので無視しても問題はない。けど、今回はまさに、これをするために<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%E9">インストーラ</a>ーに手を出したわけでして。</p><p>で、この警告をダブルクリックして出てくる解決手順を試そうとしたけど、ドキュメントが古いのか手順中の該当項目が存在しない。Webでアレコレ検索してもヒットしない。もしかして、Limited Editionじゃ<a class="keyword" href="http://d.hatena.ne.jp/keyword/.NET%20Framework">.NET Framework</a>を含めることが出来ないのかしら、などと想像は膨らむ一方。</p><br />
<p>で、セットアッププロジェクトを隅から隅まで舐め回したところ、ようやく見つけました。ソリューション<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%AF%A5%B9%A5%D7%A5%ED%A1%BC%A5%E9">エクスプローラ</a>ーで、</p><br />
<p>2 Specify Application Data<br />
└Redistributables</p><br />
<p>です。<br />
<span class="deco" style="font-size:x-small;">分かりにくい。アシスタント内に含めるかどうか質問してくれても良さそうだけど。</span></p><br />
<p>これで該当項目にチェックを付ければ解決、かと思いきや、また別の問題が。選択した再頒布パッケージがない場合は、自動でダウンロードしてくれる親切設計なのですが、そのダウンロードが出来ないと言われてしまう。「Administratorでやってるかい?」と書かれてたので、Adminでやってみたり、通信設定見直したりしたけどダメ。ググってみたところ、ダウンロード先のフォルダに書き込み権限が無いのが原因とのこと。良く見たらProgram Files下だし。なぜ<a class="keyword" href="http://d.hatena.ne.jp/keyword/UAC">UAC</a>出さないし・・・あまりお行儀は良くないけど、一般ユーザーに書き込み権限与えたところ、正常にダウンロードしてくれました。</p><br />
<p>C:\Program Files\InstallShield\2011LE\SetupPrerequisites</p><br />
<p>念のため、ISLEのオプションで指定されている2つのフォルダにも同じ対処をしておきました。私の環境では、これらのフォルダ。</p><br />
<p>C:\Program Files\InstallShield\2011LE\Objects<br />
C:\Program Files\Common Files\Merge Modules</p><br />
<p>余談:オプションでPrerequisitesフォルダを変更できるけど、元のフォルダのファイルを全部移動する必要があるっぽい?(未確認)</p><p>めでたしめでたし。<br />
<br />
<br />
</p>
<blockquote>
<p>2012/06/07追記<br />
どうにも取り回しが悪いので、現在はVSのセットアッププロジェクトを使うことで落ち着いています。私の用途ではこちらで十分でした。</p>
</blockquote>
Kiri_Feather
OAuth(xAuth)のVB.net実装サンプル
hatenablog://entry/17680117127128274420
2010-03-05T00:00:00+09:00
2010-03-05T00:00:00+09:00 OAuthのVB.netサンプルです。お好きにどうぞ。 PIN入力用のメソッドもついていますが、こちらはおまけということで。 オリジナルはこちら。はじめは備忘録として言葉でゴチャっと書いて済まそうと思ってたんですが、見てみたい、という意見を見かけたのでアップしてみた次第。おかげで見落としてた依存関係とか消せてすっきりしました。 使い方サンプル(xAuth) 初期化〜認証まで 'HttpConnectionの初期化(HttpConnection.InitializeConnection呼び出し) 'プロキシ設定と通信タイムアウトの設定です。はじめに一回だけ呼べばOK。 HttpConnectio…
<p>OAuthの<a class="keyword" href="http://d.hatena.ne.jp/keyword/VB.net">VB.net</a>サンプルです。お好きにどうぞ。<br />
PIN入力用のメソッドもついていますが、こちらはおまけということで。<br />
オリジナルは<a href="http://sourceforge.jp/projects/tween/svn/view/trunk/Tween/Connection/?root=tween">こちら</a>。</p><p>はじめは備忘録として言葉でゴチャっと書いて済まそうと思ってたんですが、見てみたい、という意見を見かけたのでアップしてみた次第。おかげで見落としてた依存関係とか消せてすっきりしました。</p>
<div class="section">
<h4>使い方サンプル(xAuth)</h4>
<div class="section">
<h5>初期化〜認証まで</h5>
<pre class="code lang-vb" data-lang="vb" data-unlink><span class="synComment">'HttpConnectionの初期化(HttpConnection.InitializeConnection呼び出し)</span>
<span class="synComment">'プロキシ設定と通信タイムアウトの設定です。はじめに一回だけ呼べばOK。</span>
HttpConnection<span class="synStatement">.</span>InitializeConnection<span class="synStatement">(</span><span class="synConstant">20</span><span class="synStatement">,</span> ProxyType<span class="synStatement">.</span>IE<span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">,</span> <span class="synConstant">0</span><span class="synStatement">,</span> <span class="synConstant">0</span><span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">)</span>
<span class="synComment">'HttpConnectionOAuthのインスタンス化</span>
<span class="synStatement">Dim</span> httpCon <span class="synStatement">as</span> <span class="synStatement">New</span> HttpConnectionOAuth
<span class="synComment">'初期化(コンシューマーキーの設定など)</span>
httpCon<span class="synStatement">.</span><span class="synSpecial">Initialize</span><span class="synStatement">(</span><span class="synConstant">"Your consumerKey"</span><span class="synStatement">,</span> <span class="synConstant">"Your consumerSecret"</span><span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">,</span> <span class="synConstant">"screen_name"</span><span class="synStatement">)</span><span class="synComment"> 'screen_nameはtwitter用</span>
<span class="synComment">'認証</span>
<span class="synStatement">Dim</span> result <span class="synStatement">As</span> <span class="synType">Boolean</span> <span class="synStatement">=</span> httpCon<span class="synStatement">.</span>AuthenticateXAuth<span class="synStatement">(</span><span class="synConstant">"https://api.twitter.com/oauth/access_token"</span><span class="synStatement">,</span> <span class="synConstant">"Your username"</span><span class="synStatement">,</span> <span class="synConstant">"Your password"</span><span class="synStatement">)</span>
<span class="synStatement">If</span> result <span class="synStatement">Then</span>
MessageBox<span class="synStatement">.</span><span class="synPreProc">Show</span><span class="synStatement">(</span><span class="synConstant">"認証成功"</span><span class="synStatement">)</span>
<span class="synStatement">Else</span>
MessageBox<span class="synStatement">.</span><span class="synPreProc">Show</span><span class="synStatement">(</span><span class="synConstant">"認証失敗"</span><span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
</pre>
</div>
<div class="section">
<h5>通信</h5>
<p>取得はこんな感じ。</p>
<pre class="code lang-vb" data-lang="vb" data-unlink><span class="synStatement">Dim</span> param <span class="synStatement">As</span> <span class="synStatement">New</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span>
param<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"count"</span><span class="synStatement">,</span> <span class="synConstant">20</span><span class="synStatement">)</span>
<span class="synStatement">Dim</span> content <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synStatement">Dim</span> statusCode <span class="synStatement">As</span> HttpStatusCode <span class="synStatement">= _</span>
httpCon<span class="synStatement">.</span>GetContent<span class="synStatement">(</span><span class="synConstant">"GET"</span><span class="synStatement">, _</span>
<span class="synStatement">New</span> Uri<span class="synStatement">(</span><span class="synConstant">"http://api.twitter.com/1/statuses/home_timeline.xml"</span><span class="synStatement">), _</span>
param<span class="synStatement">, _</span>
content<span class="synStatement">, _</span>
<span class="synStatement">Nothing)</span>
</pre><p>更新も同じ。</p>
<pre class="code lang-vb" data-lang="vb" data-unlink><span class="synStatement">Dim</span> param <span class="synStatement">As</span> <span class="synStatement">New</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span>
param<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"status"</span><span class="synStatement">,</span> <span class="synConstant">"更新しちゃうよ!"</span><span class="synStatement">)</span>
<span class="synStatement">Dim</span> content <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synStatement">Dim</span> statusCode <span class="synStatement">As</span> HttpStatusCode <span class="synStatement">= _</span>
httpCon<span class="synStatement">.</span>GetContent<span class="synStatement">(</span><span class="synConstant">"POST"</span><span class="synStatement">, _</span>
<span class="synStatement">New</span> Uri<span class="synStatement">(</span><span class="synConstant">"http://api.twitter.com/1/statuses/update.xml"</span><span class="synStatement">), _</span>
param<span class="synStatement">, _</span>
content<span class="synStatement">, _</span>
<span class="synStatement">Nothing)</span>
</pre>
</div>
</div>
<div class="section">
<h4>ソース</h4>
<p>HTTP通信の大元。ストリームとか画像取得とかのメソッドは省略してあります。</p>
<pre class="code lang-vb" data-lang="vb" data-unlink>Imports System<span class="synStatement">.</span>Net
Imports System<span class="synStatement">.</span>IO
Imports System<span class="synStatement">.</span>Collections<span class="synStatement">.</span>Generic
Imports System<span class="synStatement">.</span>Collections<span class="synStatement">.</span>Specialized
Imports System<span class="synStatement">.</span>Text
<span class="synComment">'''<summary></span>
<span class="synComment">'''HttpWebRequest,HttpWebResponseを使用した基本的な通信機能を提供する</span>
<span class="synComment">'''</summary></span>
<span class="synComment">'''<remarks></span>
<span class="synComment">'''プロキシ情報などを設定するため、使用前に静的メソッドInitializeConnectionを呼び出すこと。</span>
<span class="synComment">'''通信方式によって必要になるHTTPヘッダの付加などは、派生クラスで行う。</span>
<span class="synComment">'''</remarks></span>
<span class="synStatement">Public</span> Class HttpConnection
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''プロキシ</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> Shared proxy <span class="synStatement">As</span> WebProxy <span class="synStatement">=</span> <span class="synStatement">Nothing</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''ユーザーが選択したプロキシの方式</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> Shared proxyKind <span class="synStatement">As</span> ProxyType <span class="synStatement">=</span> proxyType<span class="synStatement">.</span>IE
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''クッキー保存用コンテナ</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> Shared cookieContainer <span class="synStatement">As</span> <span class="synStatement">New</span> CookieContainer
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''初期化済みフラグ</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> Shared isInitialize <span class="synStatement">As</span> <span class="synType">Boolean</span> <span class="synStatement">=</span> <span class="synConstant">False</span>
<span class="synStatement">Public</span> <span class="synStatement">Enum</span> ProxyType
None
IE
Specified
<span class="synStatement">End</span> <span class="synStatement">Enum</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''HttpWebRequestオブジェクトを取得する。パラメータはGET/HEAD/DELETEではクエリに、POST/PUTではエンティティボディに変換される。</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<remarks></span>
<span class="synComment"> '''追加で必要となるHTTPヘッダや通信オプションは呼び出し元で付加すること</span>
<span class="synComment"> '''(Timeout,AutomaticDecompression,AllowAutoRedirect,UserAgent,ContentType,Accept,HttpRequestHeader.Authorization,カスタムヘッダ)</span>
<span class="synComment"> '''POST/PUTでクエリが必要な場合は、requestUriに含めること。</span>
<span class="synComment"> '''</remarks></span>
<span class="synComment"> '''<param name="method">HTTP通信メソッド(GET/HEAD/POST/PUT/DELETE)</param></span>
<span class="synComment"> '''<param name="requestUri">通信先URI</param></span>
<span class="synComment"> '''<param name="param">GET時のクエリ、またはPOST時のエンティティボディ</param></span>
<span class="synComment"> '''<param name="withCookie">通信にcookieを使用するか</param></span>
<span class="synComment"> '''<returns>引数で指定された内容を反映したHttpWebRequestオブジェクト</returns></span>
Protected <span class="synStatement">Function</span> CreateRequest<span class="synStatement">(ByVal</span> method <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> requestUri <span class="synStatement">As</span> Uri<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> param <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">), _</span>
<span class="synStatement">ByVal</span> withCookie <span class="synStatement">As</span> <span class="synType">Boolean</span><span class="synStatement"> _</span>
<span class="synStatement">)</span> <span class="synStatement">As</span> HttpWebRequest
<span class="synStatement">If</span> <span class="synStatement">Not</span> isInitialize <span class="synStatement">Then</span> Throw <span class="synStatement">New</span> Exception<span class="synStatement">(</span><span class="synConstant">"Sequence error.(not initialized)"</span><span class="synStatement">)</span>
<span class="synComment"> 'GETメソッドの場合はクエリとurlを結合</span>
<span class="synStatement">Dim</span> ub <span class="synStatement">As</span> <span class="synStatement">New</span> UriBuilder<span class="synStatement">(</span>requestUri<span class="synStatement">.</span>AbsoluteUri<span class="synStatement">)</span>
<span class="synStatement">If</span> method <span class="synStatement">=</span> <span class="synConstant">"GET"</span> OrElse method <span class="synStatement">=</span> <span class="synConstant">"DELETE"</span> OrElse method <span class="synStatement">=</span> <span class="synConstant">"HEAD"</span> <span class="synStatement">Then</span>
ub<span class="synStatement">.</span>Query <span class="synStatement">=</span> CreateQueryString<span class="synStatement">(</span>param<span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Dim</span> webReq <span class="synStatement">As</span> HttpWebRequest <span class="synStatement">=</span> DirectCast<span class="synStatement">(</span>WebRequest<span class="synStatement">.</span>Create<span class="synStatement">(</span>ub<span class="synStatement">.</span>Uri<span class="synStatement">),</span> HttpWebRequest<span class="synStatement">)</span>
<span class="synComment"> 'プロキシ設定</span>
<span class="synStatement">If</span> proxyKind <span class="synStatement"><></span> ProxyType<span class="synStatement">.</span>IE <span class="synStatement">Then</span> webReq<span class="synStatement">.</span>Proxy <span class="synStatement">=</span> proxy
webReq<span class="synStatement">.</span>Method <span class="synStatement">=</span> method
<span class="synStatement">If</span> method <span class="synStatement">=</span> <span class="synConstant">"POST"</span> OrElse method <span class="synStatement">=</span> <span class="synConstant">"PUT"</span> <span class="synStatement">Then</span>
webReq<span class="synStatement">.</span>ContentType <span class="synStatement">=</span> <span class="synConstant">"application/x-www-form-urlencoded"</span>
<span class="synComment"> 'POST/PUTメソッドの場合は、ボディデータとしてクエリ構成して書き込み</span>
Using writer <span class="synStatement">As</span> <span class="synStatement">New</span> StreamWriter<span class="synStatement">(</span>webReq<span class="synStatement">.</span>GetRequestStream<span class="synStatement">)</span>
writer<span class="synStatement">.Write(</span>CreateQueryString<span class="synStatement">(</span>param<span class="synStatement">))</span>
<span class="synStatement">End</span> Using
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synComment"> 'cookie設定</span>
<span class="synStatement">If</span> withCookie <span class="synStatement">Then</span> webReq<span class="synStatement">.</span>CookieContainer <span class="synStatement">=</span> cookieContainer
<span class="synComment"> 'タイムアウト設定</span>
webReq<span class="synStatement">.</span>Timeout <span class="synStatement">=</span> DefaultTimeout
<span class="synStatement">Return</span> webReq
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''HTTPの応答を処理し、応答ボディデータをテキストとして返却する</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<remarks></span>
<span class="synComment"> '''リダイレクト応答の場合(AllowAutoRedirect=Falseの場合のみ)は、headerInfoインスタンスがあればLocationを追加してリダイレクト先を返却</span>
<span class="synComment"> '''WebExceptionはハンドルしていないので、呼び出し元でキャッチすること</span>
<span class="synComment"> '''テキストの文字コードはUTF-8を前提として、エンコードはしていません</span>
<span class="synComment"> '''</remarks></span>
<span class="synComment"> '''<param name="webRequest">HTTP通信リクエストオブジェクト</param></span>
<span class="synComment"> '''<param name="contentText">[OUT]HTTP応答のボディデータ</param></span>
<span class="synComment"> '''<param name="headerInfo">[IN/OUT]HTTP応答のヘッダ情報。ヘッダ名をキーにして空データのコレクションを渡すことで、該当ヘッダの値をデータに設定して戻す</param></span>
<span class="synComment"> '''<param name="withCookie">通信にcookieを使用する</param></span>
<span class="synComment"> '''<returns>HTTP応答のステータスコード</returns></span>
Protected <span class="synStatement">Function</span> GetResponse<span class="synStatement">(ByVal</span> webRequest <span class="synStatement">As</span> HttpWebRequest<span class="synStatement">, _</span>
<span class="synStatement">ByRef</span> contentText <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> headerInfo <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">), _</span>
<span class="synStatement">ByVal</span> withCookie <span class="synStatement">As</span> <span class="synType">Boolean</span><span class="synStatement"> _</span>
<span class="synStatement">)</span> <span class="synStatement">As</span> HttpStatusCode
Try
Using webRes <span class="synStatement">As</span> HttpWebResponse <span class="synStatement">=</span> CType<span class="synStatement">(</span>webRequest<span class="synStatement">.</span>GetResponse<span class="synStatement">(),</span> HttpWebResponse<span class="synStatement">)</span>
<span class="synStatement">Dim</span> statusCode <span class="synStatement">As</span> HttpStatusCode <span class="synStatement">=</span> webRes<span class="synStatement">.</span>StatusCode
<span class="synComment"> 'cookie保持</span>
<span class="synStatement">If</span> withCookie <span class="synStatement">Then</span> SaveCookie<span class="synStatement">(</span>webRes<span class="synStatement">.</span>Cookies<span class="synStatement">)</span>
<span class="synComment"> 'リダイレクト応答の場合は、リダイレクト先を設定</span>
GetHeaderInfo<span class="synStatement">(</span>webRes<span class="synStatement">,</span> headerInfo<span class="synStatement">)</span>
<span class="synComment"> '応答のストリームをテキストに書き出し</span>
<span class="synStatement">If</span> contentText <span class="synStatement">Is</span> <span class="synStatement">Nothing</span> <span class="synStatement">Then</span> Throw <span class="synStatement">New</span> ArgumentNullException<span class="synStatement">(</span><span class="synConstant">"contentText"</span><span class="synStatement">)</span>
<span class="synStatement">If</span> webRes<span class="synStatement">.</span>ContentLength <span class="synStatement">></span> <span class="synConstant">0</span> <span class="synStatement">Then</span>
Using sr <span class="synStatement">As</span> StreamReader <span class="synStatement">=</span> <span class="synStatement">New</span> StreamReader<span class="synStatement">(</span>webRes<span class="synStatement">.</span>GetResponseStream<span class="synStatement">)</span>
contentText <span class="synStatement">=</span> sr<span class="synStatement">.</span>ReadToEnd<span class="synStatement">()</span>
<span class="synStatement">End</span> Using
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Return</span> statusCode
<span class="synStatement">End</span> Using
Catch ex <span class="synStatement">As</span> WebException
<span class="synStatement">If</span> ex<span class="synStatement">.</span>Status <span class="synStatement">=</span> WebExceptionStatus<span class="synStatement">.</span>ProtocolError <span class="synStatement">Then</span>
<span class="synStatement">Dim</span> res <span class="synStatement">As</span> HttpWebResponse <span class="synStatement">=</span> DirectCast<span class="synStatement">(</span>ex<span class="synStatement">.</span>Response<span class="synStatement">,</span> HttpWebResponse<span class="synStatement">)</span>
<span class="synStatement">Return</span> res<span class="synStatement">.</span>StatusCode
<span class="synStatement">End</span> <span class="synStatement">If</span>
Throw ex
<span class="synStatement">End</span> Try
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''HTTPの応答を処理します。応答ボディデータが不要な用途向け。</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<remarks></span>
<span class="synComment"> '''リダイレクト応答の場合(AllowAutoRedirect=Falseの場合のみ)は、headerInfoインスタンスがあればLocationを追加してリダイレクト先を返却</span>
<span class="synComment"> '''WebExceptionはハンドルしていないので、呼び出し元でキャッチすること</span>
<span class="synComment"> '''</remarks></span>
<span class="synComment"> '''<param name="webRequest">HTTP通信リクエストオブジェクト</param></span>
<span class="synComment"> '''<param name="headerInfo">[IN/OUT]HTTP応答のヘッダ情報。ヘッダ名をキーにして空データのコレクションを渡すことで、該当ヘッダの値をデータに設定して戻す</param></span>
<span class="synComment"> '''<param name="withCookie">通信にcookieを使用する</param></span>
<span class="synComment"> '''<returns>HTTP応答のステータスコード</returns></span>
Protected <span class="synStatement">Function</span> GetResponse<span class="synStatement">(ByVal</span> webRequest <span class="synStatement">As</span> HttpWebRequest<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> headerInfo <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">), _</span>
<span class="synStatement">ByVal</span> withCookie <span class="synStatement">As</span> <span class="synType">Boolean</span><span class="synStatement"> _</span>
<span class="synStatement">)</span> <span class="synStatement">As</span> HttpStatusCode
Try
Using webRes <span class="synStatement">As</span> HttpWebResponse <span class="synStatement">=</span> CType<span class="synStatement">(</span>webRequest<span class="synStatement">.</span>GetResponse<span class="synStatement">(),</span> HttpWebResponse<span class="synStatement">)</span>
<span class="synStatement">Dim</span> statusCode <span class="synStatement">As</span> HttpStatusCode <span class="synStatement">=</span> webRes<span class="synStatement">.</span>StatusCode
<span class="synComment"> 'cookie保持</span>
<span class="synStatement">If</span> withCookie <span class="synStatement">Then</span> SaveCookie<span class="synStatement">(</span>webRes<span class="synStatement">.</span>Cookies<span class="synStatement">)</span>
<span class="synComment"> 'リダイレクト応答の場合は、リダイレクト先を設定</span>
GetHeaderInfo<span class="synStatement">(</span>webRes<span class="synStatement">,</span> headerInfo<span class="synStatement">)</span>
<span class="synStatement">Return</span> statusCode
<span class="synStatement">End</span> Using
Catch ex <span class="synStatement">As</span> WebException
<span class="synStatement">If</span> ex<span class="synStatement">.</span>Status <span class="synStatement">=</span> WebExceptionStatus<span class="synStatement">.</span>ProtocolError <span class="synStatement">Then</span>
<span class="synStatement">Dim</span> res <span class="synStatement">As</span> HttpWebResponse <span class="synStatement">=</span> DirectCast<span class="synStatement">(</span>ex<span class="synStatement">.</span>Response<span class="synStatement">,</span> HttpWebResponse<span class="synStatement">)</span>
<span class="synStatement">Return</span> res<span class="synStatement">.</span>StatusCode
<span class="synStatement">End</span> <span class="synStatement">If</span>
Throw ex
<span class="synStatement">End</span> Try
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''クッキーを保存。ホスト名なしのドメインの場合、ドメイン名から先頭のドットを除去して追加しないと再利用されないため</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> <span class="synStatement">Sub</span> SaveCookie<span class="synStatement">(ByVal</span> cookieCollection <span class="synStatement">As</span> CookieCollection<span class="synStatement">)</span>
<span class="synStatement">For</span> <span class="synStatement">Each</span> ck <span class="synStatement">As</span> Cookie <span class="synStatement">In</span> cookieCollection
<span class="synStatement">If</span> ck<span class="synStatement">.</span>Domain<span class="synStatement">.</span>StartsWith<span class="synStatement">(</span><span class="synConstant">"."</span><span class="synStatement">)</span> <span class="synStatement">Then</span>
ck<span class="synStatement">.</span>Domain <span class="synStatement">=</span> ck<span class="synStatement">.</span>Domain<span class="synStatement">.</span>Substring<span class="synStatement">(</span><span class="synConstant">1</span><span class="synStatement">,</span> ck<span class="synStatement">.</span>Domain<span class="synStatement">.</span>Length <span class="synStatement">-</span> <span class="synConstant">1</span><span class="synStatement">)</span>
cookieContainer<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span>ck<span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Next</span>
<span class="synStatement">End</span> <span class="synStatement">Sub</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''headerInfoのキー情報で指定されたHTTPヘッダ情報を取得・格納する。redirect応答時はLocationヘッダの内容を追記する</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="webResponse">HTTP応答</param></span>
<span class="synComment"> '''<param name="headerInfo">[IN/OUT]キーにヘッダ名を指定したデータ空のコレクション。取得した値をデータにセットして戻す</param></span>
<span class="synStatement">Private</span> <span class="synStatement">Sub</span> GetHeaderInfo<span class="synStatement">(ByVal</span> webResponse <span class="synStatement">As</span> HttpWebResponse<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> headerInfo <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">))</span>
<span class="synStatement">If</span> headerInfo <span class="synStatement">Is</span> <span class="synStatement">Nothing</span> <span class="synStatement">Then</span> <span class="synStatement">Exit</span> <span class="synStatement">Sub</span>
<span class="synStatement">If</span> headerInfo<span class="synStatement">.</span><span class="synPreProc">Count</span> <span class="synStatement">></span> <span class="synConstant">0</span> <span class="synStatement">Then</span>
<span class="synStatement">Dim</span> <span class="synPreProc">keys</span><span class="synStatement">(</span>headerInfo<span class="synStatement">.</span><span class="synPreProc">Count</span> <span class="synStatement">-</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">String</span>
headerInfo<span class="synStatement">.</span><span class="synPreProc">Keys</span><span class="synStatement">.</span>CopyTo<span class="synStatement">(</span><span class="synPreProc">keys</span><span class="synStatement">,</span> <span class="synConstant">0</span><span class="synStatement">)</span>
<span class="synStatement">For</span> <span class="synStatement">Each</span> key <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">In</span> <span class="synPreProc">keys</span>
<span class="synStatement">If</span> <span class="synIdentifier">Array</span><span class="synStatement">.</span>IndexOf<span class="synStatement">(</span>webResponse<span class="synStatement">.</span>Headers<span class="synStatement">.</span>AllKeys<span class="synStatement">,</span> key<span class="synStatement">)</span> <span class="synStatement">></span> <span class="synStatement">-</span><span class="synConstant">1</span> <span class="synStatement">Then</span>
headerInfo<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span>key<span class="synStatement">)</span> <span class="synStatement">=</span> webResponse<span class="synStatement">.</span>Headers<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span>key<span class="synStatement">)</span>
<span class="synStatement">Else</span>
headerInfo<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span>key<span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Next</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Dim</span> statusCode <span class="synStatement">As</span> HttpStatusCode <span class="synStatement">=</span> webResponse<span class="synStatement">.</span>StatusCode
<span class="synStatement">If</span> statusCode <span class="synStatement">=</span> HttpStatusCode<span class="synStatement">.</span>MovedPermanently OrElse<span class="synStatement"> _</span>
statusCode <span class="synStatement">=</span> HttpStatusCode<span class="synStatement">.</span>Found OrElse<span class="synStatement"> _</span>
statusCode <span class="synStatement">=</span> HttpStatusCode<span class="synStatement">.</span>SeeOther OrElse<span class="synStatement"> _</span>
statusCode <span class="synStatement">=</span> HttpStatusCode<span class="synStatement">.</span>TemporaryRedirect <span class="synStatement">Then</span>
<span class="synStatement">If</span> headerInfo<span class="synStatement">.</span>ContainsKey<span class="synStatement">(</span><span class="synConstant">"Location"</span><span class="synStatement">)</span> <span class="synStatement">Then</span>
headerInfo<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span><span class="synConstant">"Location"</span><span class="synStatement">)</span> <span class="synStatement">=</span> webResponse<span class="synStatement">.</span>Headers<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span><span class="synConstant">"Location"</span><span class="synStatement">)</span>
<span class="synStatement">Else</span>
headerInfo<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"Location"</span><span class="synStatement">,</span> webResponse<span class="synStatement">.</span>Headers<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span><span class="synConstant">"Location"</span><span class="synStatement">))</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">End</span> <span class="synStatement">Sub</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''クエリコレクションをkey=value形式の文字列に構成して戻す</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="param">クエリ、またはポストデータとなるkey-valueコレクション</param></span>
Protected <span class="synStatement">Function</span> CreateQueryString<span class="synStatement">(ByVal</span> param <span class="synStatement">As</span> IDictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">))</span> <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synStatement">If</span> param <span class="synStatement">Is</span> <span class="synStatement">Nothing</span> OrElse param<span class="synStatement">.</span><span class="synPreProc">Count</span> <span class="synStatement">=</span> <span class="synConstant">0</span> <span class="synStatement">Then</span> <span class="synStatement">Return</span> <span class="synType">String</span><span class="synStatement">.</span><span class="synType">Empty</span>
<span class="synStatement">Dim</span> query <span class="synStatement">As</span> <span class="synStatement">New</span> StringBuilder
<span class="synStatement">For</span> <span class="synStatement">Each</span> key <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">In</span> param<span class="synStatement">.</span><span class="synPreProc">Keys</span>
query<span class="synStatement">.</span>AppendFormat<span class="synStatement">(</span><span class="synConstant">"{0}={1}&"</span><span class="synStatement">,</span> UrlEncode<span class="synStatement">(</span>key<span class="synStatement">),</span> UrlEncode<span class="synStatement">(</span>param<span class="synStatement">(</span>key<span class="synStatement">)))</span>
<span class="synStatement">Next</span>
<span class="synStatement">Return</span> query<span class="synStatement">.</span>ToString<span class="synStatement">(</span><span class="synConstant">0</span><span class="synStatement">,</span> query<span class="synStatement">.</span>Length <span class="synStatement">-</span> <span class="synConstant">1</span><span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''クエリ形式(key1=value1&key2=value2&...)の文字列をkey-valueコレクションに詰め直し</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="queryString">クエリ文字列</param></span>
<span class="synComment"> '''<returns>key-valueのコレクション</returns></span>
Protected <span class="synStatement">Function</span> ParseQueryString<span class="synStatement">(ByVal</span> queryString <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">As</span> NameValueCollection
<span class="synStatement">Dim</span> query <span class="synStatement">As</span> <span class="synStatement">New</span> NameValueCollection
<span class="synStatement">Dim</span> parts<span class="synStatement">()</span> <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> queryString<span class="synStatement">.</span><span class="synPreProc">Split</span><span class="synStatement">(</span><span class="synConstant">"&"</span>c<span class="synStatement">)</span>
<span class="synStatement">For</span> <span class="synStatement">Each</span> part <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">In</span> parts
<span class="synStatement">Dim</span> index <span class="synStatement">As</span> <span class="synType">Integer</span> <span class="synStatement">=</span> part<span class="synStatement">.</span>IndexOf<span class="synStatement">(</span><span class="synConstant">"="</span>c<span class="synStatement">)</span>
<span class="synStatement">If</span> index <span class="synStatement">=</span> <span class="synStatement">-</span><span class="synConstant">1</span> <span class="synStatement">Then</span>
query<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span>Uri<span class="synStatement">.</span>UnescapeDataString<span class="synStatement">(</span>part<span class="synStatement">),</span> <span class="synConstant">""</span><span class="synStatement">)</span>
<span class="synStatement">Else</span>
query<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span>Uri<span class="synStatement">.</span>UnescapeDataString<span class="synStatement">(</span>part<span class="synStatement">.</span>Substring<span class="synStatement">(</span><span class="synConstant">0</span><span class="synStatement">,</span> index<span class="synStatement">)),</span> Uri<span class="synStatement">.</span>UnescapeDataString<span class="synStatement">(</span>part<span class="synStatement">.</span>Substring<span class="synStatement">(</span>index <span class="synStatement">+</span> <span class="synConstant">1</span><span class="synStatement">)))</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Next</span>
<span class="synStatement">Return</span> query
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''2バイト文字も考慮したUrlエンコード</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="str">エンコードする文字列</param></span>
<span class="synComment"> '''<returns>エンコード結果文字列</returns></span>
Protected <span class="synStatement">Function</span> UrlEncode<span class="synStatement">(ByVal</span> stringToEncode <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synStatement">Const</span> UnreservedChars <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synConstant">"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"</span>
<span class="synStatement">Dim</span> sb <span class="synStatement">As</span> <span class="synStatement">New</span> StringBuilder
<span class="synStatement">Dim</span> bytes <span class="synStatement">As</span> <span class="synType">Byte</span><span class="synStatement">()</span> <span class="synStatement">=</span> Encoding<span class="synStatement">.</span>UTF8<span class="synStatement">.</span>GetBytes<span class="synStatement">(</span>stringToEncode<span class="synStatement">)</span>
<span class="synStatement">For</span> <span class="synStatement">Each</span> b <span class="synStatement">As</span> <span class="synType">Byte</span> <span class="synStatement">In</span> bytes
<span class="synStatement">If</span> UnreservedChars<span class="synStatement">.</span>IndexOf<span class="synStatement">(</span><span class="synIdentifier">Chr</span><span class="synStatement">(</span>b<span class="synStatement">))</span> <span class="synStatement"><></span> <span class="synStatement">-</span><span class="synConstant">1</span> <span class="synStatement">Then</span>
sb<span class="synStatement">.</span><span class="synPreProc">Append</span><span class="synStatement">(</span><span class="synIdentifier">Chr</span><span class="synStatement">(</span>b<span class="synStatement">))</span>
<span class="synStatement">Else</span>
sb<span class="synStatement">.</span>AppendFormat<span class="synStatement">(</span><span class="synConstant">"%{0:X2}"</span><span class="synStatement">,</span> b<span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Next</span>
<span class="synStatement">Return</span> sb<span class="synStatement">.</span>ToString<span class="synStatement">()</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synType">#</span>Region <span class="synConstant">"DefaultTimeout"</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''通信タイムアウト時間(ms)</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> Shared timeout <span class="synStatement">As</span> <span class="synType">Integer</span> <span class="synStatement">=</span> <span class="synConstant">20000</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''通信タイムアウト時間(ms)。10〜120秒の範囲で指定。範囲外は20秒とする</span>
<span class="synComment"> '''</summary></span>
Protected Shared <span class="synStatement">Property</span> DefaultTimeout<span class="synStatement">()</span> <span class="synStatement">As</span> <span class="synType">Integer</span>
<span class="synStatement">Get</span>
<span class="synStatement">Return</span> timeout
<span class="synStatement">End</span> <span class="synStatement">Get</span>
<span class="synStatement">Set(ByVal</span> <span class="synPreProc">value</span> <span class="synStatement">As</span> <span class="synType">Integer</span><span class="synStatement">)</span>
<span class="synStatement">Const</span> TimeoutMinValue <span class="synStatement">As</span> <span class="synType">Integer</span> <span class="synStatement">=</span> <span class="synConstant">10000</span>
<span class="synStatement">Const</span> TimeoutMaxValue <span class="synStatement">As</span> <span class="synType">Integer</span> <span class="synStatement">=</span> <span class="synConstant">120000</span>
<span class="synStatement">Const</span> TimeoutDefaultValue <span class="synStatement">As</span> <span class="synType">Integer</span> <span class="synStatement">=</span> <span class="synConstant">20000</span>
<span class="synStatement">If</span> <span class="synPreProc">value</span> <span class="synStatement"><</span> TimeoutMinValue OrElse <span class="synPreProc">value</span> <span class="synStatement">></span> TimeoutMaxValue <span class="synStatement">Then</span>
<span class="synComment"> ' 範囲外ならデフォルト値設定</span>
timeout <span class="synStatement">=</span> TimeoutDefaultValue
<span class="synStatement">Else</span>
timeout <span class="synStatement">=</span> <span class="synPreProc">value</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">End</span> <span class="synStatement">Set</span>
<span class="synStatement">End</span> <span class="synStatement">Property</span>
<span class="synType">#</span><span class="synStatement">End</span> Region
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''通信クラスの初期化処理。タイムアウト値とプロキシを設定する</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<remarks></span>
<span class="synComment"> '''通信開始前に最低一度呼び出すこと</span>
<span class="synComment"> '''</remarks></span>
<span class="synComment"> '''<param name="timeout">タイムアウト値(秒)</param></span>
<span class="synComment"> '''<param name="proxyType">なし・指定・IEデフォルト</param></span>
<span class="synComment"> '''<param name="proxyAddress">プロキシのホスト名orIPアドレス</param></span>
<span class="synComment"> '''<param name="proxyPort">プロキシのポート番号</param></span>
<span class="synComment"> '''<param name="proxyUser">プロキシ認証が必要な場合のユーザ名。不要なら空文字</param></span>
<span class="synComment"> '''<param name="proxyPassword">プロキシ認証が必要な場合のパスワード。不要なら空文字</param></span>
<span class="synStatement">Public</span> Shared <span class="synStatement">Sub</span> InitializeConnection<span class="synStatement">( _</span>
<span class="synStatement">ByVal</span> timeout <span class="synStatement">As</span> <span class="synType">Integer</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> proxyType <span class="synStatement">As</span> ProxyType<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> proxyAddress <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> proxyPort <span class="synStatement">As</span> <span class="synType">Integer</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> proxyUser <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> proxyPassword <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span>
isInitialize <span class="synStatement">=</span> <span class="synConstant">True</span>
ServicePointManager<span class="synStatement">.</span>Expect100Continue <span class="synStatement">=</span> <span class="synConstant">False</span>
DefaultTimeout <span class="synStatement">=</span> timeout <span class="synStatement">*</span> <span class="synConstant">1000</span> <span class="synComment"> 's -> ms</span>
<span class="synStatement">Select</span> <span class="synStatement">Case</span> proxyType
<span class="synStatement">Case</span> proxyType<span class="synStatement">.</span>None
proxy <span class="synStatement">=</span> <span class="synStatement">Nothing</span>
<span class="synStatement">Case</span> proxyType<span class="synStatement">.</span>Specified
proxy <span class="synStatement">=</span> <span class="synStatement">New</span> WebProxy<span class="synStatement">(</span><span class="synConstant">"http://"</span> <span class="synStatement">+</span> proxyAddress <span class="synStatement">+</span> <span class="synConstant">":"</span> <span class="synStatement">+</span> proxyPort<span class="synStatement">.</span>ToString<span class="synStatement">)</span>
<span class="synStatement">If</span> <span class="synStatement">Not</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>proxyUser<span class="synStatement">)</span> OrElse <span class="synStatement">Not</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>proxyPassword<span class="synStatement">)</span> <span class="synStatement">Then</span>
proxy<span class="synStatement">.</span>Credentials <span class="synStatement">=</span> <span class="synStatement">New</span> NetworkCredential<span class="synStatement">(</span>proxyUser<span class="synStatement">,</span> proxyPassword<span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Case</span> proxyType<span class="synStatement">.</span>IE
<span class="synComment"> 'IE設定(システム設定)はデフォルト値なので処理しない</span>
<span class="synStatement">End</span> <span class="synStatement">Select</span>
proxyType <span class="synStatement">=</span> proxyType
<span class="synStatement">End</span> <span class="synStatement">Sub</span>
<span class="synStatement">End</span> Class
</pre><p>それを使ったOAuth。</p>
<pre class="code lang-vb" data-lang="vb" data-unlink>Imports System<span class="synStatement">.</span>Net
Imports System<span class="synStatement">.</span>Collections<span class="synStatement">.</span>Generic
Imports System<span class="synStatement">.</span>Collections<span class="synStatement">.</span>Specialized
Imports System<span class="synStatement">.</span>IO
Imports System<span class="synStatement">.</span>Text
Imports System<span class="synStatement">.</span>Security
<span class="synComment">'''<summary></span>
<span class="synComment">'''OAuth認証を使用するHTTP通信。HMAC-SHA1固定</span>
<span class="synComment">'''</summary></span>
<span class="synComment">'''<remarks></span>
<span class="synComment">'''使用前に認証情報を設定する。認証確認を伴う場合はAuthenticate系のメソッドを、認証不要な場合はInitializeを呼ぶこと。</span>
<span class="synComment">'''</remarks></span>
<span class="synStatement">Public</span> Class HttpConnectionOAuth
Inherits HttpConnection
<span class="synStatement">Implements</span> IHttpConnection
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth署名のoauth_timestamp算出用基準日付(1970/1/1 00:00:00)</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> Shared ReadOnly UnixEpoch <span class="synStatement">As</span> <span class="synStatement">New</span> DateTime<span class="synStatement">(</span><span class="synConstant">1970</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">,</span> <span class="synConstant">0</span><span class="synStatement">,</span> <span class="synConstant">0</span><span class="synStatement">,</span> <span class="synConstant">0</span><span class="synStatement">,</span> DateTimeKind<span class="synStatement">.</span>Unspecified<span class="synStatement">)</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth署名のoauth_nonce算出用乱数クラス</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> Shared ReadOnly NonceRandom <span class="synStatement">As</span> <span class="synStatement">New</span> Random
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuthのアクセストークン。永続化可能(ユーザー取り消しの可能性はある)。</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> token <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuthの署名作成用秘密アクセストークン。永続化可能(ユーザー取り消しの可能性はある)。</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> tokenSecret <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuthのコンシューマー鍵</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> consumerKey <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuthの署名作成用秘密コンシューマーデータ</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> consumerSecret <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''認証成功時の応答でユーザー情報を取得する場合のキー。設定しない場合は、AuthUsernameもブランクのままとなる</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> userIdentKey <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuthの署名作成用秘密コンシューマーデータ</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Private</span> authorizedUsername <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth認証で指定のURLとHTTP通信を行い、結果を返す</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="method">HTTP通信メソッド(GET/HEAD/POST/PUT/DELETE)</param></span>
<span class="synComment"> '''<param name="requestUri">通信先URI</param></span>
<span class="synComment"> '''<param name="param">GET時のクエリ、またはPOST時のエンティティボディ</param></span>
<span class="synComment"> '''<param name="content">[OUT]HTTP応答のボディデータ</param></span>
<span class="synComment"> '''<param name="headerInfo">[IN/OUT]HTTP応答のヘッダ情報。必要なヘッダ名を事前に設定しておくこと</param></span>
<span class="synComment"> '''<returns>HTTP応答のステータスコード</returns></span>
<span class="synStatement">Public</span> <span class="synStatement">Function</span> GetContent<span class="synStatement">(ByVal</span> method <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> requestUri <span class="synStatement">As</span> Uri<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> param <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">), _</span>
<span class="synStatement">ByRef</span> content <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> headerInfo <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">))</span> <span class="synStatement">As</span> HttpStatusCode <span class="synStatement">Implements</span> IHttpConnection<span class="synStatement">.</span>GetContent
<span class="synComment"> '認証済かチェック</span>
<span class="synStatement">If</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>token<span class="synStatement">)</span> <span class="synStatement">Then</span> Throw <span class="synStatement">New</span> Exception<span class="synStatement">(</span><span class="synConstant">"Sequence error. (Token is blank.)"</span><span class="synStatement">)</span>
<span class="synStatement">Dim</span> webReq <span class="synStatement">As</span> HttpWebRequest <span class="synStatement">=</span> CreateRequest<span class="synStatement">(</span>method<span class="synStatement">, _</span>
requestUri<span class="synStatement">, _</span>
param<span class="synStatement">, _</span>
<span class="synConstant">False</span><span class="synStatement">)</span>
<span class="synComment"> 'OAuth認証ヘッダを付加</span>
AppendOAuthInfo<span class="synStatement">(</span>webReq<span class="synStatement">,</span> param<span class="synStatement">,</span> token<span class="synStatement">,</span> tokenSecret<span class="synStatement">)</span>
<span class="synStatement">If</span> content <span class="synStatement">Is</span> <span class="synStatement">Nothing</span> <span class="synStatement">Then</span>
<span class="synStatement">Return</span> GetResponse<span class="synStatement">(</span>webReq<span class="synStatement">,</span> headerInfo<span class="synStatement">,</span> <span class="synConstant">False</span><span class="synStatement">)</span>
<span class="synStatement">Else</span>
<span class="synStatement">Return</span> GetResponse<span class="synStatement">(</span>webReq<span class="synStatement">,</span> content<span class="synStatement">,</span> headerInfo<span class="synStatement">,</span> <span class="synConstant">False</span><span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synType">#</span>Region <span class="synConstant">"認証処理"</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth認証の開始要求(リクエストトークン取得)。PIN入力用の前段</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<remarks></span>
<span class="synComment"> '''呼び出し元では戻されたurlをブラウザで開き、認証完了後PIN入力を受け付けて、リクエストトークンと共にAuthenticatePinFlowを呼び出す</span>
<span class="synComment"> '''</remarks></span>
<span class="synComment"> '''<param name="requestTokenUrl">リクエストトークンの取得先URL</param></span>
<span class="synComment"> '''<param name="requestUri">ブラウザで開く認証用URLのベース</param></span>
<span class="synComment"> '''<param name="requestToken">[OUT]認証要求で戻されるリクエストトークン。使い捨て</param></span>
<span class="synComment"> '''<param name="authUri">[OUT]requestUriを元に生成された認証用URL。通常はリクエストトークンをクエリとして付加したUri</param></span>
<span class="synComment"> '''<returns>取得結果真偽値</returns></span>
<span class="synStatement">Public</span> <span class="synStatement">Function</span> AuthenticatePinFlowRequest<span class="synStatement">(ByVal</span> requestTokenUrl <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> authorizeUrl <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByRef</span> requestToken <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByRef</span> authUri <span class="synStatement">As</span> Uri<span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">Boolean</span>
<span class="synComment"> 'PIN-based flow</span>
authUri <span class="synStatement">=</span> GetAuthenticatePageUri<span class="synStatement">(</span>requestTokenUrl<span class="synStatement">,</span> authorizeUrl<span class="synStatement">,</span> requestToken<span class="synStatement">)</span>
<span class="synStatement">If</span> authUri <span class="synStatement">Is</span> <span class="synStatement">Nothing</span> <span class="synStatement">Then</span> <span class="synStatement">Return</span> <span class="synConstant">False</span>
<span class="synStatement">Return</span> <span class="synConstant">True</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth認証のアクセストークン取得。PIN入力用の後段</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<remarks></span>
<span class="synComment"> '''事前にAuthenticatePinFlowRequestを呼んで、ブラウザで認証後に表示されるPINを入力してもらい、その値とともに呼び出すこと</span>
<span class="synComment"> '''</remarks></span>
<span class="synComment"> '''<param name="accessTokenUrl">アクセストークンの取得先URL</param></span>
<span class="synComment"> '''<param name="requestUri">AuthenticatePinFlowRequestで取得したリクエストトークン</param></span>
<span class="synComment"> '''<param name="pinCode">Webで認証後に表示されるPINコード</param></span>
<span class="synComment"> '''<returns>取得結果真偽値</returns></span>
<span class="synStatement">Public</span> <span class="synStatement">Function</span> AuthenticatePinFlow<span class="synStatement">(ByVal</span> accessTokenUrl <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> requestToken <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> pinCode <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">Boolean</span>
<span class="synComment"> 'PIN-based flow</span>
<span class="synStatement">If</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>requestToken<span class="synStatement">)</span> <span class="synStatement">Then</span> Throw <span class="synStatement">New</span> Exception<span class="synStatement">(</span><span class="synConstant">"Sequence error.(requestToken is blank)"</span><span class="synStatement">)</span>
<span class="synComment"> 'アクセストークン取得</span>
<span class="synStatement">Dim</span> accessTokenData <span class="synStatement">As</span> NameValueCollection <span class="synStatement">=</span> GetOAuthToken<span class="synStatement">(New</span> Uri<span class="synStatement">(</span>accessTokenUrl<span class="synStatement">),</span> pinCode<span class="synStatement">,</span> requestToken<span class="synStatement">,</span> <span class="synStatement">Nothing)</span>
<span class="synStatement">If</span> accessTokenData IsNot <span class="synStatement">Nothing</span> <span class="synStatement">Then</span>
token <span class="synStatement">=</span> accessTokenData<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span><span class="synConstant">"oauth_token"</span><span class="synStatement">)</span>
tokenSecret <span class="synStatement">=</span> accessTokenData<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span><span class="synConstant">"oauth_token_secret"</span><span class="synStatement">)</span>
<span class="synComment"> 'サービスごとの独自拡張対応</span>
<span class="synStatement">If</span> <span class="synStatement">Me.</span>userIdentKey <span class="synStatement"><></span> <span class="synConstant">""</span> <span class="synStatement">Then</span>
authorizedUsername <span class="synStatement">=</span> accessTokenData<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(Me.</span>userIdentKey<span class="synStatement">)</span>
<span class="synStatement">Else</span>
authorizedUsername <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">If</span> token <span class="synStatement">=</span> <span class="synConstant">""</span> <span class="synStatement">Then</span> <span class="synStatement">Return</span> <span class="synConstant">False</span>
<span class="synStatement">Return</span> <span class="synConstant">True</span>
<span class="synStatement">Else</span>
<span class="synStatement">Return</span> <span class="synConstant">False</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth認証のアクセストークン取得。xAuth方式</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="accessTokenUrl">アクセストークンの取得先URL</param></span>
<span class="synComment"> '''<param name="username">認証用ユーザー名</param></span>
<span class="synComment"> '''<param name="password">認証用パスワード</param></span>
<span class="synComment"> '''<returns>取得結果真偽値</returns></span>
<span class="synStatement">Public</span> <span class="synStatement">Function</span> AuthenticateXAuth<span class="synStatement">(ByVal</span> accessTokenUrl <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">,</span> <span class="synStatement">ByVal</span> username <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">,</span> <span class="synStatement">ByVal</span> password <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">Boolean</span> <span class="synStatement">Implements</span> IHttpConnection<span class="synStatement">.</span>Authenticate
<span class="synComment"> 'ユーザー・パスワードチェック</span>
<span class="synStatement">If</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>username<span class="synStatement">)</span> OrElse <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>password<span class="synStatement">)</span> <span class="synStatement">Then</span>
Throw <span class="synStatement">New</span> Exception<span class="synStatement">(</span><span class="synConstant">"Sequence error.(username or password is blank)"</span><span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synComment"> 'xAuthの拡張パラメータ設定</span>
<span class="synStatement">Dim</span> parameter <span class="synStatement">As</span> <span class="synStatement">New</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"x_auth_mode"</span><span class="synStatement">,</span> <span class="synConstant">"client_auth"</span><span class="synStatement">)</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"x_auth_username"</span><span class="synStatement">,</span> username<span class="synStatement">)</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"x_auth_password"</span><span class="synStatement">,</span> password<span class="synStatement">)</span>
<span class="synComment"> 'アクセストークン取得</span>
<span class="synStatement">Dim</span> accessTokenData <span class="synStatement">As</span> NameValueCollection <span class="synStatement">=</span> GetOAuthToken<span class="synStatement">(New</span> Uri<span class="synStatement">(</span>accessTokenUrl<span class="synStatement">),</span> <span class="synConstant">""</span><span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">,</span> parameter<span class="synStatement">)</span>
<span class="synStatement">If</span> accessTokenData IsNot <span class="synStatement">Nothing</span> <span class="synStatement">Then</span>
token <span class="synStatement">=</span> accessTokenData<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span><span class="synConstant">"oauth_token"</span><span class="synStatement">)</span>
tokenSecret <span class="synStatement">=</span> accessTokenData<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span><span class="synConstant">"oauth_token_secret"</span><span class="synStatement">)</span>
<span class="synComment"> 'サービスごとの独自拡張対応</span>
<span class="synStatement">If</span> <span class="synStatement">Me.</span>userIdentKey <span class="synStatement"><></span> <span class="synConstant">""</span> <span class="synStatement">Then</span>
authorizedUsername <span class="synStatement">=</span> accessTokenData<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(Me.</span>userIdentKey<span class="synStatement">)</span>
<span class="synStatement">Else</span>
authorizedUsername <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">If</span> token <span class="synStatement">=</span> <span class="synConstant">""</span> <span class="synStatement">Then</span> <span class="synStatement">Return</span> <span class="synConstant">False</span>
<span class="synStatement">Return</span> <span class="synConstant">True</span>
<span class="synStatement">Else</span>
<span class="synStatement">Return</span> <span class="synConstant">False</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth認証のリクエストトークン取得。リクエストトークンと組み合わせた認証用のUriも生成する</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="accessTokenUrl">リクエストトークンの取得先URL</param></span>
<span class="synComment"> '''<param name="authorizeUrl">ブラウザで開く認証用URLのベース</param></span>
<span class="synComment"> '''<param name="requestToken">[OUT]取得したリクエストトークン</param></span>
<span class="synComment"> '''<returns>取得結果真偽値</returns></span>
<span class="synStatement">Private</span> <span class="synStatement">Function</span> GetAuthenticatePageUri<span class="synStatement">(ByVal</span> requestTokenUrl <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> authorizeUrl <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByRef</span> requestToken <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">As</span> Uri
<span class="synStatement">Const</span> tokenKey <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synConstant">"oauth_token"</span>
<span class="synComment"> 'リクエストトークン取得</span>
<span class="synStatement">Dim</span> reqTokenData <span class="synStatement">As</span> NameValueCollection <span class="synStatement">=</span> GetOAuthToken<span class="synStatement">(New</span> Uri<span class="synStatement">(</span>requestTokenUrl<span class="synStatement">),</span> <span class="synConstant">""</span><span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">,</span> <span class="synStatement">Nothing)</span>
<span class="synStatement">If</span> reqTokenData IsNot <span class="synStatement">Nothing</span> <span class="synStatement">Then</span>
requestToken <span class="synStatement">=</span> reqTokenData<span class="synStatement">.</span><span class="synPreProc">Item</span><span class="synStatement">(</span>tokenKey<span class="synStatement">)</span>
<span class="synComment"> 'Uri生成</span>
<span class="synStatement">Dim</span> ub <span class="synStatement">As</span> <span class="synStatement">New</span> UriBuilder<span class="synStatement">(</span>authorizeUrl<span class="synStatement">)</span>
ub<span class="synStatement">.</span>Query <span class="synStatement">=</span> <span class="synType">String</span><span class="synStatement">.</span><span class="synIdentifier">Format</span><span class="synStatement">(</span><span class="synConstant">"{0}={1}"</span><span class="synStatement">,</span> tokenKey<span class="synStatement">,</span> requestToken<span class="synStatement">)</span>
<span class="synStatement">Return</span> ub<span class="synStatement">.</span>Uri
<span class="synStatement">Else</span>
<span class="synStatement">Return</span> <span class="synStatement">Nothing</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth認証のトークン取得共通処理</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="requestUri">各種トークンの取得先URL</param></span>
<span class="synComment"> '''<param name="pinCode">PINフロー時のアクセストークン取得時に設定。それ以外は空文字列</param></span>
<span class="synComment"> '''<param name="requestToken">PINフロー時のリクエストトークン取得時に設定。それ以外は空文字列</param></span>
<span class="synComment"> '''<param name="parameter">追加パラメータ。xAuthで使用</param></span>
<span class="synComment"> '''<returns>取得結果のデータ。正しく取得出来なかった場合はNothing</returns></span>
<span class="synStatement">Private</span> <span class="synStatement">Function</span> GetOAuthToken<span class="synStatement">(ByVal</span> requestUri <span class="synStatement">As</span> Uri<span class="synStatement">,</span> <span class="synStatement">ByVal</span> pinCode <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">,</span> <span class="synStatement">ByVal</span> requestToken <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">,</span> <span class="synStatement">ByVal</span> parameter <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">))</span> <span class="synStatement">As</span> NameValueCollection
<span class="synStatement">Dim</span> webReq <span class="synStatement">As</span> HttpWebRequest <span class="synStatement">=</span> <span class="synStatement">Nothing</span>
<span class="synComment"> 'HTTPリクエスト生成。PINコードもパラメータも未指定の場合はGETメソッドで通信。それ以外はPOST</span>
<span class="synStatement">If</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>pinCode<span class="synStatement">)</span> AndAlso parameter <span class="synStatement">Is</span> <span class="synStatement">Nothing</span> <span class="synStatement">Then</span>
webReq <span class="synStatement">=</span> CreateRequest<span class="synStatement">(</span><span class="synConstant">"GET"</span><span class="synStatement">,</span> requestUri<span class="synStatement">,</span> <span class="synStatement">Nothing,</span> <span class="synConstant">False</span><span class="synStatement">)</span>
<span class="synStatement">Else</span>
webReq <span class="synStatement">=</span> CreateRequest<span class="synStatement">(</span><span class="synConstant">"POST"</span><span class="synStatement">,</span> requestUri<span class="synStatement">,</span> parameter<span class="synStatement">,</span> <span class="synConstant">False</span><span class="synStatement">)</span><span class="synComment"> 'ボディに追加パラメータ書き込み</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synComment"> 'OAuth関連パラメータ準備。追加パラメータがあれば追加</span>
<span class="synStatement">Dim</span> query <span class="synStatement">As</span> <span class="synStatement">New</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span>
<span class="synStatement">If</span> parameter IsNot <span class="synStatement">Nothing</span> <span class="synStatement">Then</span>
<span class="synStatement">For</span> <span class="synStatement">Each</span> kvp <span class="synStatement">As</span> KeyValuePair<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">In</span> parameter
query<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span>kvp<span class="synStatement">.</span>Key<span class="synStatement">,</span> kvp<span class="synStatement">.</span><span class="synPreProc">Value</span><span class="synStatement">)</span>
<span class="synStatement">Next</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synComment"> 'PINコードが指定されていればパラメータに追加</span>
<span class="synStatement">If</span> <span class="synStatement">Not</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>pinCode<span class="synStatement">)</span> <span class="synStatement">Then</span> query<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_verifier"</span><span class="synStatement">,</span> pinCode<span class="synStatement">)</span>
<span class="synComment"> 'OAuth関連情報をHTTPリクエストに追加</span>
AppendOAuthInfo<span class="synStatement">(</span>webReq<span class="synStatement">,</span> query<span class="synStatement">,</span> requestToken<span class="synStatement">,</span> <span class="synConstant">""</span><span class="synStatement">)</span>
<span class="synComment"> 'HTTP応答取得</span>
Try
<span class="synStatement">Dim</span> contentText <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synConstant">""</span>
<span class="synStatement">Dim</span> status <span class="synStatement">As</span> HttpStatusCode <span class="synStatement">=</span> GetResponse<span class="synStatement">(</span>webReq<span class="synStatement">,</span> contentText<span class="synStatement">,</span> <span class="synStatement">Nothing,</span> <span class="synConstant">False</span><span class="synStatement">)</span>
<span class="synStatement">If</span> status <span class="synStatement">=</span> HttpStatusCode<span class="synStatement">.</span>OK <span class="synStatement">Then</span>
<span class="synStatement">Return</span> ParseQueryString<span class="synStatement">(</span>contentText<span class="synStatement">)</span>
<span class="synStatement">Else</span>
<span class="synStatement">Return</span> <span class="synStatement">Nothing</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
Catch ex <span class="synStatement">As</span> Exception
<span class="synStatement">Return</span> <span class="synStatement">Nothing</span>
<span class="synStatement">End</span> Try
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synType">#</span><span class="synStatement">End</span> Region
<span class="synType">#</span>Region <span class="synConstant">"OAuth認証用ヘッダ作成・付加処理"</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''HTTPリクエストにOAuth関連ヘッダを追加</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="webRequest">追加対象のHTTPリクエスト</param></span>
<span class="synComment"> '''<param name="query">OAuth追加情報+クエリ or POSTデータ</param></span>
<span class="synComment"> '''<param name="token">アクセストークン、もしくはリクエストトークン。未取得なら空文字列</param></span>
<span class="synComment"> '''<param name="tokenSecret">アクセストークンシークレット。認証処理では空文字列</param></span>
<span class="synStatement">Private</span> <span class="synStatement">Sub</span> AppendOAuthInfo<span class="synStatement">(ByVal</span> webRequest <span class="synStatement">As</span> HttpWebRequest<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> query <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">), _</span>
<span class="synStatement">ByVal</span> token <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> tokenSecret <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span>
<span class="synComment"> 'OAuth共通情報取得</span>
<span class="synStatement">Dim</span> parameter <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">=</span> GetOAuthParameter<span class="synStatement">(</span>token<span class="synStatement">)</span>
<span class="synComment"> 'OAuth共通情報にquery情報を追加</span>
<span class="synStatement">If</span> query IsNot <span class="synStatement">Nothing</span> <span class="synStatement">Then</span>
<span class="synStatement">For</span> <span class="synStatement">Each</span> <span class="synPreProc">item</span> <span class="synStatement">As</span> KeyValuePair<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">In</span> query
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synPreProc">item</span><span class="synStatement">.</span>Key<span class="synStatement">,</span> <span class="synPreProc">item</span><span class="synStatement">.</span><span class="synPreProc">Value</span><span class="synStatement">)</span>
<span class="synStatement">Next</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synComment"> '署名の作成・追加</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_signature"</span><span class="synStatement">,</span> CreateSignature<span class="synStatement">(</span>tokenSecret<span class="synStatement">,</span> webRequest<span class="synStatement">.</span>Method<span class="synStatement">,</span> webRequest<span class="synStatement">.</span>RequestUri<span class="synStatement">,</span> parameter<span class="synStatement">))</span>
<span class="synComment"> 'HTTPリクエストのヘッダに追加</span>
<span class="synStatement">Dim</span> sb <span class="synStatement">As</span> <span class="synStatement">New</span> StringBuilder<span class="synStatement">(</span><span class="synConstant">"OAuth "</span><span class="synStatement">)</span>
<span class="synStatement">For</span> <span class="synStatement">Each</span> <span class="synPreProc">item</span> <span class="synStatement">As</span> KeyValuePair<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">In</span> parameter
<span class="synComment"> '各種情報のうち、oauth_で始まる情報のみ、ヘッダに追加する。各情報はカンマ区切り、データはダブルクォーテーションで括る</span>
<span class="synStatement">If</span> <span class="synPreProc">item</span><span class="synStatement">.</span>Key<span class="synStatement">.</span>StartsWith<span class="synStatement">(</span><span class="synConstant">"oauth_"</span><span class="synStatement">)</span> <span class="synStatement">Then</span>
sb<span class="synStatement">.</span>AppendFormat<span class="synStatement">(</span><span class="synConstant">"{0}=""{1}"","</span><span class="synStatement">,</span> <span class="synPreProc">item</span><span class="synStatement">.</span>Key<span class="synStatement">,</span> UrlEncode<span class="synStatement">(</span><span class="synPreProc">item</span><span class="synStatement">.</span><span class="synPreProc">Value</span><span class="synStatement">))</span>
<span class="synStatement">End</span> <span class="synStatement">If</span>
<span class="synStatement">Next</span>
webRequest<span class="synStatement">.</span>Headers<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span>HttpRequestHeader<span class="synStatement">.</span>Authorization<span class="synStatement">,</span> sb<span class="synStatement">.</span>ToString<span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">Sub</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuthで使用する共通情報を取得する</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="token">アクセストークン、もしくはリクエストトークン。未取得なら空文字列</param></span>
<span class="synComment"> '''<returns>OAuth情報のディクショナリ</returns></span>
<span class="synStatement">Private</span> <span class="synStatement">Function</span> GetOAuthParameter<span class="synStatement">(ByVal</span> token <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span>
<span class="synStatement">Dim</span> parameter <span class="synStatement">As</span> <span class="synStatement">New</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_consumer_key"</span><span class="synStatement">,</span> consumerKey<span class="synStatement">)</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_signature_method"</span><span class="synStatement">,</span> <span class="synConstant">"HMAC-SHA1"</span><span class="synStatement">)</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_timestamp"</span><span class="synStatement">,</span> Convert<span class="synStatement">.</span>ToInt64<span class="synStatement">((</span>DateTime<span class="synStatement">.</span>UtcNow <span class="synStatement">-</span> UnixEpoch<span class="synStatement">).</span>TotalSeconds<span class="synStatement">).</span>ToString<span class="synStatement">())</span> <span class="synComment"> 'epoch秒</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_nonce"</span><span class="synStatement">,</span> NonceRandom<span class="synStatement">.Next(</span><span class="synConstant">123400</span><span class="synStatement">,</span> <span class="synConstant">9999999</span><span class="synStatement">).</span>ToString<span class="synStatement">())</span>
parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_version"</span><span class="synStatement">,</span> <span class="synConstant">"1.0"</span><span class="synStatement">)</span>
<span class="synStatement">If</span> <span class="synStatement">Not</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>token<span class="synStatement">)</span> <span class="synStatement">Then</span> parameter<span class="synStatement">.</span><span class="synPreProc">Add</span><span class="synStatement">(</span><span class="synConstant">"oauth_token"</span><span class="synStatement">,</span> token<span class="synStatement">)</span><span class="synComment"> 'トークンがあれば追加</span>
<span class="synStatement">Return</span> parameter
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''OAuth認証ヘッダの署名作成</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="tokenSecret">アクセストークン秘密鍵</param></span>
<span class="synComment"> '''<param name="method">HTTPメソッド文字列</param></span>
<span class="synComment"> '''<param name="uri">アクセス先Uri</param></span>
<span class="synComment"> '''<param name="parameter">クエリ、もしくはPOSTデータ</param></span>
<span class="synComment"> '''<returns>署名文字列</returns></span>
<span class="synStatement">Private</span> <span class="synStatement">Function</span> CreateSignature<span class="synStatement">(ByVal</span> tokenSecret <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> method <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> uri <span class="synStatement">As</span> Uri<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> parameter <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">) _</span>
<span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synComment"> 'パラメタをソート済みディクショナリに詰替(OAuthの仕様)</span>
<span class="synStatement">Dim</span> sorted <span class="synStatement">As</span> <span class="synStatement">New</span> SortedDictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">)(</span>parameter<span class="synStatement">)</span>
<span class="synComment"> 'URLエンコード済みのクエリ形式文字列に変換</span>
<span class="synStatement">Dim</span> paramString <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> CreateQueryString<span class="synStatement">(</span>sorted<span class="synStatement">)</span>
<span class="synComment"> 'アクセス先URLの整形</span>
<span class="synStatement">Dim</span> url <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synType">String</span><span class="synStatement">.</span><span class="synIdentifier">Format</span><span class="synStatement">(</span><span class="synConstant">"{0}://{1}{2}"</span><span class="synStatement">,</span> uri<span class="synStatement">.</span>Scheme<span class="synStatement">,</span> uri<span class="synStatement">.</span>Host<span class="synStatement">,</span> uri<span class="synStatement">.</span>AbsolutePath<span class="synStatement">)</span>
<span class="synComment"> '署名のベース文字列生成(&区切り)。クエリ形式文字列は再エンコードする</span>
<span class="synStatement">Dim</span> signatureBase <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> <span class="synType">String</span><span class="synStatement">.</span><span class="synIdentifier">Format</span><span class="synStatement">(</span><span class="synConstant">"{0}&{1}&{2}"</span><span class="synStatement">,</span> method<span class="synStatement">,</span> UrlEncode<span class="synStatement">(</span>url<span class="synStatement">),</span> UrlEncode<span class="synStatement">(</span>paramString<span class="synStatement">))</span>
<span class="synComment"> '署名鍵の文字列をコンシューマー秘密鍵とアクセストークン秘密鍵から生成(&区切り。アクセストークン秘密鍵なくても&残すこと)</span>
<span class="synStatement">Dim</span> key <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">=</span> UrlEncode<span class="synStatement">(</span>consumerSecret<span class="synStatement">)</span> <span class="synStatement">+</span> <span class="synConstant">"&"</span>
<span class="synStatement">If</span> <span class="synStatement">Not</span> <span class="synType">String</span><span class="synStatement">.</span>IsNullOrEmpty<span class="synStatement">(</span>tokenSecret<span class="synStatement">)</span> <span class="synStatement">Then</span> key <span class="synStatement">+=</span> UrlEncode<span class="synStatement">(</span>tokenSecret<span class="synStatement">)</span>
<span class="synComment"> '鍵生成&署名生成</span>
<span class="synStatement">Dim</span> hmac <span class="synStatement">As</span> <span class="synStatement">New</span> Cryptography<span class="synStatement">.</span>HMACSHA1<span class="synStatement">(</span>Encoding<span class="synStatement">.</span>ASCII<span class="synStatement">.</span>GetBytes<span class="synStatement">(</span>key<span class="synStatement">))</span>
<span class="synStatement">Dim</span> hash <span class="synStatement">As</span> <span class="synType">Byte</span><span class="synStatement">()</span> <span class="synStatement">=</span> hmac<span class="synStatement">.</span>ComputeHash<span class="synStatement">(</span>Encoding<span class="synStatement">.</span>ASCII<span class="synStatement">.</span>GetBytes<span class="synStatement">(</span>signatureBase<span class="synStatement">))</span>
<span class="synStatement">Return</span> Convert<span class="synStatement">.</span>ToBase64String<span class="synStatement">(</span>hash<span class="synStatement">)</span>
<span class="synStatement">End</span> <span class="synStatement">Function</span>
<span class="synType">#</span><span class="synStatement">End</span> Region
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''初期化。各種トークンの設定とユーザー識別情報設定</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="consumerKey">コンシューマー鍵</param></span>
<span class="synComment"> '''<param name="consumerSecret">コンシューマー秘密鍵</param></span>
<span class="synComment"> '''<param name="accessToken">アクセストークン</param></span>
<span class="synComment"> '''<param name="accessTokenSecret">アクセストークン秘密鍵</param></span>
<span class="synComment"> '''<param name="userIdentifier">アクセストークン取得時に得られるユーザー識別情報。不要なら空文字列</param></span>
<span class="synStatement">Public</span> <span class="synStatement">Sub</span> <span class="synSpecial">Initialize</span><span class="synStatement">(ByVal</span> consumerKey <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> consumerSecret <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> accessToken <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> accessTokenSecret <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> userIdentifier <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span>
<span class="synStatement">Me.</span>consumerKey <span class="synStatement">=</span> consumerKey
<span class="synStatement">Me.</span>consumerSecret <span class="synStatement">=</span> consumerSecret
<span class="synStatement">Me.</span>token <span class="synStatement">=</span> accessToken
<span class="synStatement">Me.</span>tokenSecret <span class="synStatement">=</span> accessTokenSecret
<span class="synStatement">Me.</span>userIdentKey <span class="synStatement">=</span> userIdentifier
<span class="synStatement">End</span> <span class="synStatement">Sub</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''初期化。各種トークンの設定とユーザー識別情報設定</span>
<span class="synComment"> '''</summary></span>
<span class="synComment"> '''<param name="consumerKey">コンシューマー鍵</param></span>
<span class="synComment"> '''<param name="consumerSecret">コンシューマー秘密鍵</param></span>
<span class="synComment"> '''<param name="accessToken">アクセストークン</param></span>
<span class="synComment"> '''<param name="accessTokenSecret">アクセストークン秘密鍵</param></span>
<span class="synComment"> '''<param name="username">認証済みユーザー名</param></span>
<span class="synComment"> '''<param name="userIdentifier">アクセストークン取得時に得られるユーザー識別情報。不要なら空文字列</param></span>
<span class="synStatement">Public</span> <span class="synStatement">Sub</span> <span class="synSpecial">Initialize</span><span class="synStatement">(ByVal</span> consumerKey <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> consumerSecret <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> accessToken <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> accessTokenSecret <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> username <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> userIdentifier <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span>
<span class="synSpecial">Initialize</span><span class="synStatement">(</span>consumerKey<span class="synStatement">,</span> consumerSecret<span class="synStatement">,</span> accessToken<span class="synStatement">,</span> accessTokenSecret<span class="synStatement">,</span> userIdentifier<span class="synStatement">)</span>
authorizedUsername <span class="synStatement">=</span> username
<span class="synStatement">End</span> <span class="synStatement">Sub</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''アクセストークン</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Public</span> ReadOnly <span class="synStatement">Property</span> AccessToken<span class="synStatement">()</span> <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synStatement">Get</span>
<span class="synStatement">Return</span> token
<span class="synStatement">End</span> <span class="synStatement">Get</span>
<span class="synStatement">End</span> <span class="synStatement">Property</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''アクセストークン秘密鍵</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Public</span> ReadOnly <span class="synStatement">Property</span> AccessTokenSecret<span class="synStatement">()</span> <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synStatement">Get</span>
<span class="synStatement">Return</span> tokenSecret
<span class="synStatement">End</span> <span class="synStatement">Get</span>
<span class="synStatement">End</span> <span class="synStatement">Property</span>
<span class="synComment"> '''<summary></span>
<span class="synComment"> '''認証済みユーザー名</span>
<span class="synComment"> '''</summary></span>
<span class="synStatement">Public</span> ReadOnly <span class="synStatement">Property</span> AuthUsername<span class="synStatement">()</span> <span class="synStatement">As</span> <span class="synType">String</span> <span class="synStatement">Implements</span> IHttpConnection<span class="synStatement">.</span>AuthUsername
<span class="synStatement">Get</span>
<span class="synStatement">Return</span> authorizedUsername
<span class="synStatement">End</span> <span class="synStatement">Get</span>
<span class="synStatement">End</span> <span class="synStatement">Property</span>
<span class="synStatement">End</span> Class
</pre><p>他の類似クラスとの共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>のために定義したインターフェース</p>
<pre class="code lang-vb" data-lang="vb" data-unlink>Imports System<span class="synStatement">.</span>Net
<span class="synStatement">Public</span> Interface IHttpConnection
<span class="synStatement">Function</span> GetContent<span class="synStatement">(ByVal</span> method <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> requestUri <span class="synStatement">As</span> Uri<span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> param <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">), _</span>
<span class="synStatement">ByRef</span> content <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">, _</span>
<span class="synStatement">ByVal</span> headerInfo <span class="synStatement">As</span> Dictionary<span class="synStatement">(</span>Of <span class="synType">String</span><span class="synStatement">,</span> <span class="synType">String</span><span class="synStatement">))</span> <span class="synStatement">As</span> HttpStatusCode
<span class="synStatement">Function</span> Authenticate<span class="synStatement">(ByVal</span> url <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">,</span> <span class="synStatement">ByVal</span> username <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">,</span> <span class="synStatement">ByVal</span> password <span class="synStatement">As</span> <span class="synType">String</span><span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">Boolean</span>
ReadOnly <span class="synStatement">Property</span> AuthUsername<span class="synStatement">()</span> <span class="synStatement">As</span> <span class="synType">String</span>
<span class="synStatement">End</span> Interface
</pre>
</div>
Kiri_Feather
Ubuntu 8.04 LTS(Hardy Heron)のClamAV(0.94.x)サポート打ち切り
hatenablog://entry/17680117127128275969
2009-12-14T00:00:00+09:00
2009-12-14T00:00:00+09:00 ちょっとメモ。運用しているUbuntu 8.04(Hardy Heron)で動かしているClamAVが10月頃からウィルスを捕まえなくなっていてなぜだろう?と思っていたのですが、今日になって原因が判明した。 [Clamav-announce] End of Life Announcement: ClamAV 0.94.x http://lurker.clamav.net/message/20091006.143601.d27bbd20.ja.html 2009年10月6日のMLで流れてた。 すでに2ヶ月経過しているけど、Ubuntuのセキュリティアップデートには更新が来てない。新しいバージョン…
<p>ちょっとメモ。</p><p>運用している<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a> 8.04(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Hardy%20Heron">Hardy Heron</a>)で動かしている<a class="keyword" href="http://d.hatena.ne.jp/keyword/ClamAV">ClamAV</a>が10月頃からウィルスを捕まえなくなっていてなぜだろう?と思っていたのですが、今日になって原因が判明した。</p><br />
<p>[<a class="keyword" href="http://d.hatena.ne.jp/keyword/Clamav">Clamav</a>-announce] End of Life Announcement: <a class="keyword" href="http://d.hatena.ne.jp/keyword/ClamAV">ClamAV</a> 0.94.x<br />
<a href="http://lurker.clamav.net/message/20091006.143601.d27bbd20.ja.html">http://lurker.clamav.net/message/20091006.143601.d27bbd20.ja.html</a></p><br />
<p>2009年10月6日のMLで流れてた。</p><br />
<p>すでに2ヶ月経過しているけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>のセキュリティアップデートには更新が来てない。新しいバージョンの<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>には0.95系が乗っているみたいだけど。次のLTSのリリースは来年の4月頃なわけで、あと4ヶ月も待っていられない。</p><p>で、色々探したら、backportsには0.95が入ってた。安定運用を第一に考えていたので、souces.listにはbackportsは入れてなかったのです。</p><br />
<p>で、souces.listの<a class="keyword" href="http://d.hatena.ne.jp/keyword/hardy">hardy</a>-backports行のコメントを外して更新したら、無事<a class="keyword" href="http://d.hatena.ne.jp/keyword/clamav">clamav</a>だけ更新がかかった。一安心。</p><br />
<p>この件に関しては、(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>側で全パッケージを把握するのは難しいにしても)バージョンアップしないと新しい定義ファイルが受け付けられない、というセキュリティ的に致命的な問題なので、security updateで対応して欲しかったなぁ、と思った次第。</p>
Kiri_Feather
TweetUp Tokyo 09 へ行ってきた
hatenablog://entry/17680117127128276184
2009-10-18T23:54:37+09:00
2009-10-18T23:54:37+09:00 10月15日に恵比寿で行われたTwitterオフィシャルのユーザーイベントへ行ってきました。 数週間前に行われた、こちらもオフィシャルの開発者イベントに出席したばかりだったこともあり初めは欠席するつもりだったのですが、ありがたいことにLTのお誘いを頂いたので出席を決めました。イベント一週間前にお誘いを頂き、それからプレゼン資料を作りはじめたわけですが、お題を決めるのに時間を取られました。作りはじめたらサクッっと出来たのですが、途中ファイル形式の指定があって焼き直したり、いつの間にか資料提出の締切が早まったりと、微妙に準備不足な感がありました。最終的には、会場へ向かう電車のなかで最終確認をする羽…
<p>10月15日に恵比寿で行われた<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>オフィシャルのユーザーイベントへ行ってきました。<br />
数週間前に行われた、こちらもオフィシャルの開発者イベントに出席したばかりだったこともあり初めは欠席するつもりだったのですが、ありがたいことにLTのお誘いを頂いたので出席を決めました。</p><p>イベント一週間前にお誘いを頂き、それからプレゼン資料を作りはじめたわけですが、お題を決めるのに時間を取られました。作りはじめたらサクッっと出来たのですが、途中ファイル形式の指定があって焼き直したり、いつの間にか資料提出の締切が早まったりと、微妙に準備不足な感がありました。最終的には、会場へ向かう電車のなかで最終確認をする羽目に。</p><p>家も勤務先も田舎のため、事前に決められていた集合時間には間に合わず、皆さんと同じ時間に受付をしました。ですが、Webからの参加申込をしていなかったためか参加者名簿に名前がない、というアクシデントも。すんなり通して頂けましたけど。</p><p>すぐに開発者の方々(cheebowさん、lynmockさん、takuma104さん)に会えたのは助かりました。</p><p>イベントが始まると、会場は人だらけで動き回るのに苦労するほど。開始してしばらくすると、そこかしこで話が盛り上がりはじめ、オープニングのbizの話を聞くのも難しい状態に。早々に諦めましたよ。</p><p>まぁ、それはいいとして、一番困ったのは、<span style="font-size:large;font-weight:bold;">「誰が誰だかわからん!!」</span>ことでした。名札にアイコン必須です。ちぃ覚えた!<br />
もう少し人数少なければコミュニケーションの取りようもあったと思うのですが。</p><p>日本専用携帯電話向け<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>公式サイト <a href="http://twtr.jp">http://twtr.jp</a> の発表があり、会場は盛り上がりました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>は未対応のようで残念でしたが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>には対応していました。<br />
その後、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Willcom">Willcom</a>の公式コンテンツ対応と新<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHS">PHS</a>の発表があり、いよいよクライアント開発者のLTです。</p><br />
<p>始めはTwit!のcheebowさん。クライアント開発の苦労話と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE">命名</a>裏話を面白おかしく話されました。さすがうまいっす。みんなつぶやきのことをtwitって言うのやめようぜ!w</p><p>次に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B7%C8%C2%D3%C9%B4%B7%CA">携帯百景</a>のkimzaさん。元々は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>と連携していなかったとは驚き。単体サービスとしても面白そうだな、と認識を改めました。赤字はなんとかなるといいですねw</p><p>NatsuLion for <a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>のtakuma104さん。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>向けの<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%A5%A2%A5%D7%A5%EA">iPhoneアプリ</a>をこれでもか!と紹介されました。すげーな<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>。でも、実は最近話題のTiltShiftの方もすごく気になっちゃいました。</p><p>P3:PeraPeraPrvのlynmockさん。P3の魅力(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">マルチプラットフォーム</a>、カスタマイズ幅、大槍さんアイコンw)を詰め込んだプレゼンでした。グッズ楽しげ。欲しいわー。</p><p>そして私。お題は「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>の出会い力」。開発寄りの話題にするか、クライアントアピールにするか、など悩んだのですが、ユーザーイベントなのでクライアントの話も絡めつつ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>自体にフォーカスしてみました。ある意味無難なお題になっちゃったかな?まぁ、大外しするよりはいいか、と。<br />
お題は、まぁ流行りってことでつけたんですが、後でご本人登場して、ひそかに冷や汗かきました。<br />
内容は、クライアント作ってたら協力者がいっぱいできて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>ってすごいと思った、という体験談。そこから膨らませて、テレビでも話題になってるしどんどん広めて行きましょう!という締めに持って行った感じです。<br />
こんなところがいいよね、とか書こうかとも思ったのですが、そんなこと語れるほど偉くも頭良くもないので体験談にとどめました。ここはぜひDGさんに頑張って欲しいところ。</p><p>その後、なんとか数人の方々とお話させて頂きました。ほんの数人でしたけど。</p><p>イベント終わった後は、cheebowさん、lynmockさん、arawasさん、takuma104さんと軽く飲みました。<br />
みんな面白いし、こっちの方が落ち着きますねw<br />
ぜひまた飲みたいです。</p><p>初のLTという貴重な体験と、ネットの向こう側にいた皆さんと実際に引き合わせてくれたこのイベントは、本当に良い思い出になりそうです。</p><p>091019追記<br />
LT資料 <a href="http://www.slideshare.net/kirifeather/kirifeathers-lt-in-tweetup-tokyo-09-fall">http://www.slideshare.net/kirifeather/kirifeathers-lt-in-tweetup-tokyo-09-fall</a></p><p>This diary was written with <a href="http://d.hatena.ne.jp/aroooy/searchdiary?word=%2a%5bHatenaSync%5d">HatenaSync</a></p>
Kiri_Feather
ReTweetについての戸惑い
hatenablog://entry/17680117127128276069
2009-10-18T00:51:12+09:00
2009-10-18T00:51:12+09:00 RTって、 周知(晒し上げ、オープンチャット) 引用返信 に使われています。 で、引用返信の時と周知の時って、内容を見ればどっちの用途で使ったのか分かるんですが、見栄えも機能(到達範囲)も同じ訳です。 一方、通常の返信は、ある程度到達範囲が絞られていて、返信元の発言情報も付加されていて、より会話っぽくなります。通常の返信はお互い向き合って普通の声量で話しているイメージなのですが、引用返信はそっぽを向いて大声を張り上げて返事をするイメージです。こちらが通常返信で話しかけているのに相手が引用返信で返して来ると、「なんですぐ隣にいるのにそっぽ向いて返事するのさ」、と感じて、私は戸惑ってしまうのです。…
<p>RTって、</p>
<ul>
<li>周知(晒し上げ、オープンチャット)</li>
<li>引用返信</li>
</ul><p>に使われています。<br />
で、引用返信の時と周知の時って、内容を見ればどっちの用途で使ったのか分かるんですが、見栄えも機能(到達範囲)も同じ訳です。<br />
一方、通常の返信は、ある程度到達範囲が絞られていて、返信元の発言情報も付加されていて、より会話っぽくなります。</p><p>通常の返信はお互い向き合って普通の声量で話しているイメージなのですが、引用返信はそっぽを向いて大声を張り上げて返事をするイメージです。</p><p>こちらが通常返信で話しかけているのに相手が引用返信で返して来ると、「なんですぐ隣にいるのにそっぽ向いて返事するのさ」、と感じて、私は戸惑ってしまうのです。</p><p>両者の違いを知らずに使っている人も多いと思いますので、多くの方にこの違いを知って頂けたらいいな、と思うわけでした。</p><p>This diary was written with <a href="http://d.hatena.ne.jp/aroooy/searchdiary?word=%2a%5bHatenaSync%5d">HatenaSync</a></p>
Kiri_Feather
マークについて
hatenablog://entry/17680117127128276329
2009-10-04T00:54:49+09:00
2009-10-04T00:54:49+09:00 APIについては、まあ予想通りの反応。 ただ、「webモードとかapiモードって何?」という反応については説明不足だったかな、と反省しています。あと、警告メッセージの文章もイマイチ分かりにくい、もしくは誤解を招いたかと、こちらも反省点。で、意外だったのはフィルタヒット時のマークについて。今回、新着時未読クリアを実装するにあたって、フィルタヒット時は除外するようにしたのですが、その目印としてヒットマーク有無で判定するようにしました。で、以前の「何もしない」というよくわからない名称のオプションを排して、マークを全てに付けるように変更しました。活用している、という話をあまり聞かなかったのでこの変更に…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>については、まあ予想通りの反応。<br />
ただ、「webモードとか<a class="keyword" href="http://d.hatena.ne.jp/keyword/api">api</a>モードって何?」という反応については説明不足だったかな、と反省しています。あと、警告メッセージの文章もイマイチ分かりにくい、もしくは誤解を招いたかと、こちらも反省点。</p><p>で、意外だったのはフィルタヒット時のマークについて。</p><p>今回、新着時未読クリアを実装するにあたって、フィルタヒット時は除外するようにしたのですが、その目印としてヒットマーク有無で判定するようにしました。</p><p>で、以前の「何もしない」というよくわからない名称のオプションを排して、マークを全てに付けるように変更しました。活用している、という話をあまり聞かなかったのでこの変更に踏み切ったわけですが、油断していました。</p><p>全てにマークがついて不便なのでバージョンアップしない、といった意見がある一方で、「♪」マークって何?というつぶやきも見かけるわけで、なかなか難しいところです。</p><p>不便、という意見以上に新着時未読クリアが便利!という意見が多ければこのままでもいいかと思ったのですが、予想以上に少なかったという(汗<br />
完全に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CE%A2%CC%DC">裏目</a>にでた修正となりました。</p><p>マークを活用しているユーザーがいることが分かったので、この機能はパワーアップして再実装しようと思います。</p><p>フィルタ(振り分けルール)周りを弄るので、要望のあった除外条件も合わせて実装してみるつもりです。</p><p>機能の変更は難しいね、というお話でした。</p><p>This diary was written with <a href="http://d.hatena.ne.jp/aroooy/searchdiary?word=%2a%5bHatenaSync%5d">HatenaSync</a></p>
Kiri_Feather
Tween0700リリース-変更内容と所感など
hatenablog://entry/17680117127128276468
2009-10-02T01:55:00+09:00
2009-10-02T01:55:00+09:00 久しぶりにTween関連エントリー。 投稿日時 webのhtmlに日時情報が追加されていたので、一抹の不安を感じながらも対応してみました。消えてからずうっとまっていましたし。 ただ、これはいつものtwitter不具合の匂いがするんですよね・・・ APIモード あと、APIモードをデフォルトに変更。これについてはまたそのうち。 フィルタヒット時動作 フィルタヒット時の動作を三択から二択に。何もしない、という表現が分かりにくかったのと、新着時未読クリア機能を追加したことによります。選択肢はコピーと移動で、ヒットマーク(♪)は必ず付くようになりました。 新着時未読クリア 新着時未読クリアですが、クリ…
<p>久しぶりにTween<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%D8%CF%A2%A5%A8%A5%F3%A5%C8%A5%EA%A1%BC">関連エントリー</a>。</p>
<div class="section">
<h4>投稿日時</h4>
<p>webのhtmlに日時情報が追加されていたので、一抹の不安を感じながらも対応してみました。消えてからずうっとまっていましたし。<br />
ただ、これはいつもの<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>不具合の匂いがするんですよね・・・</p>
</div>
<div class="section">
<h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>モード</h4>
<p>あと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>モードをデフォルトに変更。これについてはまたそのうち。</p>
</div>
<div class="section">
<h4>フィルタヒット時動作</h4>
<p>フィルタヒット時の動作を三択から二択に。何もしない、という表現が分かりにくかったのと、新着時未読クリア機能を追加したことによります。選択肢はコピーと移動で、ヒットマーク(♪)は必ず付くようになりました。</p>
</div>
<div class="section">
<h4>新着時未読クリア</h4>
<p>新着時未読クリアですが、クリアする際にフィルタヒットしたものは除外するようにしました。また、クリアするのはRecentタブのみを対象にします。</p>
</div>
<div class="section">
<h4>bit.lyとj.mp</h4>
<p>bit.lyとj.mpの選択を分離。<br />
bit.lyを使いたい、というシチュエーションがあるらしいので。</p>
</div>
<div class="section">
<h4>ショートカット追加</h4>
<p>キーボード操作の利便性向上のため、PageUp/Downに対応するショートカット、f/bを追加しました。自分が不便だったので。本当はC-f/bにしたかったんだけど、やり過ぎ感あったので思い止まりました。</p>
</div>
<div class="section">
<h4>follower情報</h4>
<p>follower情報取得をカーソル対応。片思い表示が正しくない問題が解消されるはずです。</p><br />
<p>今後ですが、フォロー、リムーブをブラウザを開かず、必要な情報を確認しながら出来るようにすることと、そのユーザーの過去発言を取得したいな、と思っています。</p><p>This diary was written with <a href="http://d.hatena.ne.jp/aroooy/searchdiary?word=%2a%5bHatenaSync%5d">HatenaSync</a></p>
</div>
Kiri_Feather
twitter不具合
hatenablog://entry/17680117127128276882
2009-09-16T16:40:23+09:00
2009-09-16T16:40:23+09:00 ここ一週間ぐらいtwitterの調子が悪かったんですが、今日は比較的調子良さそう。不具合情報の収集しているとドキドキするのでこのまま調子いいと嬉しいなぁ。
<p>ここ一週間ぐらい<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>の調子が悪かったんですが、今日は比較的調子良さそう。不具合情報の収集しているとドキドキするのでこのまま調子いいと嬉しいなぁ。</p>
Kiri_Feather
開発者ミーティング
hatenablog://entry/17680117127128276823
2009-09-16T16:40:22+09:00
2009-09-16T16:40:22+09:00 twitterとデジタルガレージ主催で、東京で開催されたデベロッパーミーティングに参加してきました。「これは!?」という特ダネ情報はありませんでしたが、ちーぼーさん、りんもっくさん、akrさん、t_traceさん、あらわずさんなどなど、開発者の方々と会えたのは有意義でした。楽しかったー。公式じゃなくていいのでまたやりたいです。
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%B8%A5%BF%A5%EB%A5%AC%A5%EC%A1%BC%A5%B8">デジタルガレージ</a>主催で、東京で開催された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D9%A5%ED%A5%C3%A5%D1">デベロッパ</a>ーミーティングに参加してきました。「これは!?」という特ダネ情報はありませんでしたが、ちーぼーさん、りんもっくさん、<a class="keyword" href="http://d.hatena.ne.jp/keyword/akr">akr</a>さん、t_traceさん、あらわずさんなどなど、開発者の方々と会えたのは有意義でした。楽しかったー。公式じゃなくていいのでまたやりたいです。</p>
Kiri_Feather
テーマ追加
hatenablog://entry/17680117127128276758
2009-09-16T16:40:21+09:00
2009-09-16T16:40:21+09:00 テーマが追加されて、見栄えが少し変わりましたね。デフォルトアイコンも変わったようです。
<p>テーマが追加されて、見栄えが少し変わりましたね。デフォルトアイコンも変わったようです。</p>
Kiri_Feather
Tweenの紹介
hatenablog://entry/17680117127128276674
2009-09-16T16:40:20+09:00
2009-09-16T16:40:20+09:00 2週間ほど前だと思いますが、TwitterのWebページ(ユーザーのhome)の右サイドバー中にTweenが紹介されるようになりました。今のところ、もばついとTweenでランダムに表示されるようです。ありがたいなぁ。
<p>2週間ほど前だと思いますが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>のWebページ(ユーザーのhome)の右サイドバー中にTweenが紹介されるようになりました。今のところ、もばついとTweenでランダムに表示されるようです。</p><p>ありがたいなぁ。</p>
Kiri_Feather
twitter公式ナビゲーター[ついなび] twinavi
hatenablog://entry/17680117127128276592
2009-09-16T16:40:19+09:00
2009-09-16T16:40:19+09:00 ついに日本語のTwitter公式サイトができました。「twitter公式ナビゲーター[ついなび] twinavi」 http://twinavi.jp/これでようやく人に勧めやすくなりそうです。 このサイトは、デジタルガレージの子会社CGMマーケティングが運営しているようです。サイトの目的とか目指すところとかは書かれていませんが、ナビゲーターっていうぐらいですから、まぁ、そういう目的のところです。で、「Twitterって何?」とか「Twitter使い方ガイド」という導入部分へアクセスしやすいというのが良い点です。多分、twitterのヘルプページとか辿れば、似たような話は書かれていると思います…
<p>ついに日本語の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>公式サイトができました。</p><p>「<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>公式ナビゲーター[ついなび] twinavi」 <a href="http://twinavi.jp/">http://twinavi.jp/</a></p><p>これでようやく人に勧めやすくなりそうです。<br />
このサイトは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%B8%A5%BF%A5%EB%A5%AC%A5%EC%A1%BC%A5%B8">デジタルガレージ</a>の子会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/CGM">CGM</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>が運営しているようです。</p><p>サイトの目的とか目指すところとかは書かれていませんが、ナビゲーターっていうぐらいですから、まぁ、そういう目的のところです。</p><p>で、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>って何?」とか「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>使い方ガイド」という導入部分へ<span style="font-weight:bold;">アクセスしやすい</span>というのが良い点です。多分、<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>のヘルプページとか辿れば、似たような話は書かれていると思います。</p><p>こういう、<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>の概要とか便利な点や楽しい点などを<span style="font-weight:bold;">公式な</span>サイトとして用意したのは大きいだろうなぁ、と思います。巷には<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>を紹介するもっと良いブログ記事がありますので、そういうブログの紹介とかもしてどんどん盛り上がってくれることを期待して紹介してみました。</p>
Kiri_Feather
Win7対応について
hatenablog://entry/17680117127128276960
2009-09-14T00:00:00+09:00
2009-09-14T00:00:00+09:00 TweenのWin7対応ですが、RCでの動作報告もあり、一応動くようです。ですが、パフォーマンスが悪かったり、設定により動かない場合もあるらしい、という話も聞いています。 今のところ、私の環境にWin7が加わる予定がないため、動作確認とか不具合対応とかどうしたものか、と思っていました。で、この間「ふぁぼったーでGoogleAdsenseを通すためのフィルタを設定した」、とか「究極のスモールスタートの方法 自宅サーバからEC2へ」、「モバツイッターがEC2に移転したその後の話を聞いてきた(Amazon EC2 ナイトセミナ 第2回)」といった話を聞きまして、開発コストを賄えないかと調べ始めたわけ…
<p>Tweenの<a class="keyword" href="http://d.hatena.ne.jp/keyword/Win7">Win7</a>対応ですが、RCでの動作報告もあり、一応動くようです。ですが、パフォーマンスが悪かったり、設定により動かない場合もあるらしい、という話も聞いています。</p><br />
<p>今のところ、私の環境に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Win7">Win7</a>が加わる予定がないため、動作確認とか不具合対応とかどうしたものか、と思っていました。で、この間「<a href="http://twitter.com/ono_matope/statuses/3723367847">ふぁぼったーでGoogleAdsenseを通すためのフィルタを設定した</a>」、とか「<a href="http://www.milkstand.net/fsgarage/archives/001631.html">究極のスモールスタートの方法 自宅サーバからEC2へ</a>」、「<a href="http://d.hatena.ne.jp/rx7/20090908/p1">モバツイッターがEC2に移転したその後の話を聞いてきた(Amazon EC2 ナイトセミナ 第2回)</a>」といった話を聞きまして、開発コストを賄えないかと調べ始めたわけです。(当面の目標は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Win7">Win7</a>購入です。)</p><br />
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D5%A5%A3%A5%EA%A5%A8%A5%A4%A5%C8">アフィリエイト</a>とか<a class="keyword" href="http://d.hatena.ne.jp/keyword/Adsense">Adsense</a>とか、大雑把なイメージ(リンクをクリックして収入を得る)しか持っていなかったので、勉強になりました。</p><br />
<p>幸い、ついこの間移転した<a class="keyword" href="http://d.hatena.ne.jp/keyword/sourceforge.jp">sourceforge.jp</a>の<a href="http://sourceforge.jp/projects/tween/wiki/FrontPage">Tweenまとめサイト</a>では、GoogleAdsenseが使えるとのことだったので、申請を出し、先日承認が下りたので、ぺたぺた貼ってみました。</p><br />
<p>さらに、「副収入で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Win7">Win7</a>買えないかな〜」と呟いたら、「受け口があれば寄付しますよ」と言っていただいたので、<a href="http://sourceforge.jp/projects/tween/wiki/%E5%AF%84%E4%BB%98">寄付の受け口</a>を作ってみました。実はこっちの方がサービスが色々あってややこしかったです。結局、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon%A5%AE%A5%D5%A5%C8%B7%F4">Amazonギフト券</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%DD%A5%A4%A5%F3%A5%C8">はてなポイント</a>、ぷちカンパでお願いすることにしました。</p><br />
<br />
<p>「こんなことやってないで開発したい!」というのが本音なのですが、背に腹は代えられません。とりあえずここまでやって一段落ついたので、また開発を続けたいと思っています。</p>
Kiri_Feather
Twitterの発言アーカイブ
hatenablog://entry/17680117127128277043
2009-09-04T00:00:00+09:00
2009-09-04T00:00:00+09:00 Twitterでは、自分の発言は3200ポストまでしか取得できません。(多分、溜め込んでいるとは思うけど、取得する術がない。)でも、自分でアウトプットした情報は、日記として読み返したり、メモ代わりにつぶやいた情報を後で検索したりしたいのです。そこで、前回の日記で書いたアーカイブ方法でバックアップを取っています。LoudTwitterやtwtr2srcでは、はてなダイアリーに送りつけていますが、これには一つ問題があります。はてなダイアリーに限らず、ほとんどのブログ系サービスには容量に限界がありますし、サービス自体の存続も保証されません。私の場合、公開が主目的ではないので、どうせメールでブログ更新…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>では、自分の発言は3200ポストまでしか取得できません。(多分、溜め込んでいるとは思うけど、取得する術がない。)</p><p>でも、自分でアウトプットした情報は、日記として読み返したり、メモ代わりにつぶやいた情報を後で検索したりしたいのです。そこで、前回の日記で書いた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>方法でバックアップを取っています。</p><p><a href="http://www.loudtwitter.com/">LoudTwitter</a>や<a href="http://twtr2src.ogaoga.org/">twtr2src</a>では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%C0%A5%A4%A5%A2%A5%EA%A1%BC">はてなダイアリー</a>に送りつけていますが、これには一つ問題があります。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%C0%A5%A4%A5%A2%A5%EA%A1%BC">はてなダイアリー</a>に限らず、ほとんどのブログ系サービスには容量に限界がありますし、サービス自体の存続も保証されません。私の場合、公開が主目的ではないので、どうせメールでブログ更新するなら、直接自分にメールを送ってもいいのですが、味気ないので<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Reader">Google Reader</a>でブログのフィードを取得して、二重でバックアップするようにしています。</p><p>現在、<a class="keyword" href="http://d.hatena.ne.jp/keyword/twtr2src">twtr2src</a>の不具合時バックアップとして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>のプロファイルページのフィードも購読していますが、こちらはやめようと思います。1発言1記事なので、記事数が嵩張って邪魔なのです。</p><p>一点怖いのは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Reader">Google Reader</a>の仕様です。今のところ古い記事も溜め込んでいますが、いつ古い情報が切り落とされるのか分かりません。そう考えると、メールで取っておいた方がいいのかな、などと悩んでいるところです。</p>
Kiri_Feather
LoudTwitterに変わるもの
hatenablog://entry/17680117127128277098
2009-07-14T13:50:53+09:00
2009-07-14T13:50:53+09:00 LoudTwitterの存続が怪しいので、自前で用意してみた。9/4追記:復活しましたね。一安心。絶賛ドネーション受付中です。でもtwtr2srcに移行しました。まだβですが全く問題ありません。類似サービスとして、t2bとか、専用サイトまで用意してくれるTwilogなどもあります。 仕様や注意点 取得結果をメール送信するので、自分宛に送ってもいいし、はてダに送ってもいい。 手抜き仕様として、200件しか取得しません。一日200件以上発言する人はページング処理など追加する必要があります。 抽出範囲は前日分(0:00〜23:59)となります。前日分なので、cron回すときは日付が変わってからにして…
<p><del datetime="2009-09-04T09:40:55+09:00">LoudTwitterの存続が怪しいので、自前で用意してみた。</del></p><p><ins datetime="2009-09-04T09:40:55+09:00">9/4追記:復活しましたね。一安心。絶賛<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%CD%A1%BC%A5%B7%A5%E7%A5%F3">ドネーション</a>受付中です。でも<a href="http://twtr2src.ogaoga.org/">twtr2src</a>に移行しました。まだβですが全く問題ありません。類似サービスとして、<a href="http://t2b.utilz.jp/">t2b</a>とか、専用サイトまで用意してくれる<a href="http://twilog.org/">Twilog</a>などもあります。</ins><br />
</p>
<div class="section">
<h4>仕様や注意点</h4>
<p>取得結果をメール送信するので、自分宛に送ってもいいし、はてダに送ってもいい。<br />
手抜き仕様として、200件しか取得しません。一日200件以上発言する人はページング処理など追加する必要があります。<br />
抽出範囲は前日分(0:00〜23:59)となります。前日分なので、cron回すときは日付が変わってからにしてください。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>の認証はBasicです。oAuthは面倒です。<br />
メール送信はmb_send_mailを素で使っているので、mailコマンドでメール送信できる環境が必要かも。<br />
メールの書式はLoudTwitterに似せてありますが、各発言へのリンクは張っていませんのであしからず。<br />
未確認事項として、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%B3%A1%BC%A5%C7%A5%A3%A5%F3%A5%B0">エンコーディング</a>に<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTF-8">UTF-8</a>を指定していますが、これは環境依存かもしれません。文字化けするようなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/EUC">EUC</a>-JPや<a class="keyword" href="http://d.hatena.ne.jp/keyword/Shift_JIS">Shift_JIS</a>なんかも試してみて下さい。でも半角カナは化けます。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>だけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/cli">cli</a>から実行することを想定しています。アカウント情報も埋め込みなので、<span style="color:#FF0000;">Webから使うのはやめた方がいいと思います。</span></p>
</div>
<div class="section">
<h4>環境</h4>
<p>私は自前の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>鯖で動かしました。</p>
</div>
<div class="section">
<h4>導入</h4>
<div class="section">
<h5>My <a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a></h5>
<p>まずは、My <a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>という<a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>クラスを入手する。<br />
これは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>をラップしたもの。<br />
<a href="http://www.phpclasses.org/browse/package/4075.html">http://www.phpclasses.org/browse/package/4075.html</a><br />
ただし、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>はPOSTメソッドで取得しようとするので、このままでは動きません。<br />
myTimeLineParse関数内の、CURLOPT_POST指定部分を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%E1%A5%F3%A5%C8%A5%A2%A5%A6%A5%C8">コメントアウト</a>します。</p>
<pre class="code lang-php" data-lang="php" data-unlink>// curl_setopt($ch, CURLOPT_POST, true);
</pre>
</div>
<div class="section">
<h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/cUrl">cUrl</a></h5>
<p>この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/cURL">cURL</a>を使うので、「php5-<a class="keyword" href="http://d.hatena.ne.jp/keyword/curl">curl</a>」パッケージをインストール。</p>
</div>
<div class="section">
<h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/cli">cli</a></h5>
<p>cronで回すので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/cli">cli</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%D7%A5%EA%A5%BF">インタプリタ</a>用パッケージ「php5-<a class="keyword" href="http://d.hatena.ne.jp/keyword/cli">cli</a>」をインストール。</p>
</div>
<div class="section">
<h5>今回の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a></h5>
<p>で、今回作った<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>はこれ。</p>
<pre class="code lang-php" data-lang="php" data-unlink><span class="synSpecial"><?php</span>
<span class="synStatement">$</span><span class="synIdentifier">username</span> <span class="synStatement">=</span> '<span class="synConstant">xxxxxxxx</span>';
<span class="synStatement">$</span><span class="synIdentifier">password</span> <span class="synStatement">=</span> '<span class="synConstant">xxxxxxxx</span>';
<span class="synStatement">$</span><span class="synIdentifier">send_to</span> <span class="synStatement">=</span> "<span class="synConstant">xxxxxxxx@d.hatena.ne.jp</span>";
<span class="synStatement">$</span><span class="synIdentifier">from</span> <span class="synStatement">=</span> "<span class="synConstant">xxxxxxxx@xxxxx.xx.jp</span>";
<span class="synPreProc">require_once</span><span class="synSpecial">(</span>'<span class="synConstant">./my_twitter.php</span>'<span class="synSpecial">)</span>;
<span class="synStatement">$</span><span class="synIdentifier">twitter</span> <span class="synStatement">=</span> <span class="synPreProc">new</span> MyTwitter<span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">username</span>, <span class="synStatement">$</span><span class="synIdentifier">password</span><span class="synSpecial">)</span>;
<span class="synStatement">$</span><span class="synIdentifier">archive</span> <span class="synStatement">=</span> <span class="synStatement">$</span><span class="synIdentifier">twitter</span><span class="synType">-></span>userTimeline<span class="synSpecial">(</span><span class="synConstant">200</span><span class="synSpecial">)</span>;
<span class="synStatement">$</span><span class="synIdentifier">tcount</span> <span class="synStatement">=</span> <span class="synIdentifier">count</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">archive</span><span class="synSpecial">)</span>;
<span class="synStatement">if</span> <span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">tcount</span> <span class="synStatement">></span> <span class="synConstant">0</span><span class="synSpecial">)</span>
<span class="synSpecial">{</span>
<span class="synStatement">$</span><span class="synIdentifier">body</span> <span class="synStatement">=</span> '';
<span class="synStatement">$</span><span class="synIdentifier">today</span> <span class="synStatement">=</span> <span class="synIdentifier">mktime</span><span class="synSpecial">(</span><span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synIdentifier">date</span><span class="synSpecial">(</span>'<span class="synConstant">m</span>'<span class="synSpecial">)</span>, <span class="synIdentifier">date</span><span class="synSpecial">(</span>'<span class="synConstant">d</span>'<span class="synSpecial">)</span>, <span class="synIdentifier">date</span><span class="synSpecial">(</span>'<span class="synConstant">Y</span>'<span class="synSpecial">))</span>;
<span class="synStatement">$</span><span class="synIdentifier">yesterday</span> <span class="synStatement">=</span> <span class="synStatement">$</span><span class="synIdentifier">today</span> <span class="synStatement">-</span> <span class="synConstant">86400</span>;
<span class="synStatement">for</span> <span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">i</span> <span class="synStatement">=</span> <span class="synConstant">0</span>; <span class="synStatement">$</span><span class="synIdentifier">i</span> <span class="synStatement"><</span> <span class="synStatement">$</span><span class="synIdentifier">tcount</span>; <span class="synStatement">$</span><span class="synIdentifier">i</span><span class="synStatement">++</span><span class="synSpecial">)</span>
<span class="synSpecial">{</span>
<span class="synStatement">$</span><span class="synIdentifier">tm</span> <span class="synStatement">=</span> <span class="synIdentifier">strtotime</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">archive</span><span class="synSpecial">[</span><span class="synStatement">$</span><span class="synIdentifier">i</span><span class="synSpecial">][</span>'<span class="synConstant">created_at</span>'<span class="synSpecial">])</span>;
<span class="synStatement">if</span> <span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">tm</span> <span class="synStatement">>=</span> <span class="synStatement">$</span><span class="synIdentifier">yesterday</span> <span class="synStatement">and</span> <span class="synStatement">$</span><span class="synIdentifier">tm</span> <span class="synStatement"><</span> <span class="synStatement">$</span><span class="synIdentifier">today</span><span class="synSpecial">)</span>
<span class="synSpecial">{</span>
<span class="synStatement">$</span><span class="synIdentifier">sts</span> <span class="synStatement">=</span> <span class="synIdentifier">date</span><span class="synSpecial">(</span>'<span class="synConstant">H:i </span>', <span class="synStatement">$</span><span class="synIdentifier">tm</span><span class="synSpecial">)</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">archive</span><span class="synSpecial">[</span><span class="synStatement">$</span><span class="synIdentifier">i</span><span class="synSpecial">][</span>'<span class="synConstant">text</span>'<span class="synSpecial">]</span> <span class="synStatement">.</span> "<span class="synSpecial">\n</span>";
<span class="synStatement">$</span><span class="synIdentifier">body</span> <span class="synStatement">=</span> <span class="synStatement">$</span><span class="synIdentifier">body</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">sts</span>;
<span class="synSpecial">}</span>
<span class="synSpecial">}</span>
<span class="synIdentifier">mb_language</span><span class="synSpecial">(</span>"<span class="synConstant">japanese</span>"<span class="synSpecial">)</span>;
<span class="synIdentifier">mb_internal_encoding</span><span class="synSpecial">(</span>"<span class="synConstant">UTF-8</span>"<span class="synSpecial">)</span>;
<span class="synStatement">$</span><span class="synIdentifier">subj</span> <span class="synStatement">=</span> <span class="synIdentifier">date</span><span class="synSpecial">(</span>'<span class="synConstant">Y/m/d分</span>', <span class="synStatement">$</span><span class="synIdentifier">yesterday</span><span class="synSpecial">)</span>;
<span class="synIdentifier">mb_send_mail</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">send_to</span>, <span class="synStatement">$</span><span class="synIdentifier">subj</span>, <span class="synStatement">$</span><span class="synIdentifier">body</span>, "<span class="synConstant">From:</span>"<span class="synStatement">.$</span><span class="synIdentifier">from</span><span class="synSpecial">)</span>;
<span class="synSpecial">}</span>
<span class="synSpecial">?></span>
</pre><p>protectedじゃない人の発言取るときは認証要らないんだけど、面倒なのでそのまま。<br />
冒頭の4行を書き換えれば使えると思います。(通常Fromヘッダは不要ですね。)<br />
あと、my_<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>.<a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>のインポート先は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>.iniでパスを通してあるところ(例:/usr/share/<a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>:/usr/share/<a class="keyword" href="http://d.hatena.ne.jp/keyword/pear">pear</a>)に配置するか、フルパスで指定するかしてあげればよいかと。cronから実行するときは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%EA%C2%D0%A5%D1%A5%B9">相対パス</a>だとうまくいかないみたい。</p><br />
<p>あとは、my_<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>.<a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>と上記<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を適当なフォルダに配置して、cronで回します。</p>
</div>
</div>
Kiri_Feather
TenageM:オフラインに焦点を当てたWM用Twitter投稿ツール。
hatenablog://entry/17680117127128277327
2009-04-29T15:18:20+09:00
2009-04-29T15:18:20+09:00 要:.Net Compact Framework 2.0 ※Willcom03(WindowsMobile6.1 Classic)で動作確認。他環境でも多分行ける。根拠はない。 どんな人が使うの? パケットは従量制が基本 通信するなら無線か有線 いつも接続を「既定のインターネット設定」にして、勝手にダイヤルアップしないようにしている そんな人。つまり俺。 タイムラインの取得は? ありません。割り切り大事。目指せ単機能ツール。 使い道ないんじゃない? そうですね。 とは言っても、定額で使いまくりの人だって使えます。 接続を「センタ名称設定」にしておいて、なんらかの手段で事前にダイヤルアップ接続を…
<p>要:.Net Compact Framework 2.0<br />
※<a class="keyword" href="http://d.hatena.ne.jp/keyword/Willcom03">Willcom03</a>(WindowsMobile6.1 Classic)で動作確認。他環境でも多分行ける。根拠はない。<br />
<br />
</p>
<div class="section">
<h4>どんな人が使うの?</h4>
<ul>
<li>パケットは従量制が基本</li>
<li>通信するなら無線か有線</li>
<li>いつも接続を「既定のインターネット設定」にして、勝手にダイヤルアップしないようにしている</li>
</ul><p>そんな人。つまり俺。<br />
<br />
</p>
</div>
<div class="section">
<h4>タイムラインの取得は?</h4>
<p>ありません。割り切り大事。目指せ単機能ツール。<br />
<br />
</p>
</div>
<div class="section">
<h4>使い道ないんじゃない?</h4>
<p>そうですね。<br />
とは言っても、定額で使いまくりの人だって使えます。<br />
接続を「センタ名称設定」にしておいて、なんらかの手段で事前にダイヤルアップ接続を確立している必要はありますが。<br />
接続が確立されてない場合は、アプリで発言を保存しておきますので、あとでまとめて投稿できます。<br />
電波の届きにくいところなんかで使えるのではないでしょうか。<br />
でも、そういう使い方は検証してません。なので、アプリで「オフラインモード」とかは持ってません。それなりに判定します。<br />
<br />
</p>
</div>
<div class="section">
<h4>機能</h4>
<ul>
<li>投稿時オン/オフライン判定</li>
<li>発言保存機能。以下の場合は保存します。
<ul>
<li>投稿時にオフライン</li>
<li>投稿失敗(ネットワークやサービスの問題)</li>
<li>保存ボタン</li>
</ul></li>
<li>保存発言の1件削除、全件削除</li>
<li>保存発言をまとめて投稿(20秒に1発言:近所迷惑対応)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>対応(他アプリと連携。投稿即終了)</li>
</ul><p><br />
Today常駐は.netの機能だけでは難しそうだったのでやめました。<br />
<br />
</p>
</div>
<div class="section">
<h4>私の場合</h4>
<p>Actionキー長押しに割り当てて、電車で思いついたことを保存したりしてます。<br />
<br />
</p>
</div>
<div class="section">
<h4>入手&導入</h4>
<p>以下からどうぞ。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%E9">インストーラ</a>ーとか作ってません。多分みんな使わないから。<br />
使う場合は、事前に\Application Data(だっけ?)に「TenageM」というフォルダを手動で作ってください。手抜きですね。</p><br />
<p><a href="http://tween.sourceforge.jp/TenageM.exe">http://tween.sourceforge.jp/TenageM.exe</a></p><p></p>
</div>
<div class="section">
<h4>ソース</h4>
<p>ライセンスとか気にしない。お行儀悪くてすいません。<br />
ソースは<a class="keyword" href="http://d.hatena.ne.jp/keyword/coderepos">coderepos</a>に置いてあります。<br />
煮るなり焼くなり改変するなり流用するなり。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>から捨てなければお好きにどうぞ。</p><br />
<p><a href="http://coderepos.org/share/browser/lang/vb2005/TenageM">http://coderepos.org/share/browser/lang/vb2005/TenageM</a></p>
</div>
Kiri_Feather
WindowsMobile用Twitter投稿単機能ツール0.0.0.1α
hatenablog://entry/17680117127128277403
2009-04-21T00:00:00+09:00
2009-04-21T00:00:00+09:00 お試しで作ってみた。ただ単に投稿するだけ。UIもない。 とりあえず、MortScriptと組み合わせて使ってみようかと思う。 Today常駐できて、オフライン時は発言溜め込めるようにするのが最終目標。 動作も遅くて実用になるのか分からないので、今は公開しない。 ほしい人は教えてください。(もちろん自己責任)
<p>お試しで作ってみた。ただ単に投稿するだけ。UIもない。<br />
とりあえず、MortScriptと組み合わせて使ってみようかと思う。<br />
Today常駐できて、オフライン時は発言溜め込めるようにするのが最終目標。</p><br />
<p>動作も遅くて実用になるのか分からないので、今は公開しない。<br />
ほしい人は教えてください。(もちろん自己責任)</p>
Kiri_Feather
js(wscript)製twitter投稿・取得ツール
hatenablog://entry/17680117127128277485
2009-04-15T00:00:00+09:00
2009-04-15T00:00:00+09:00 ぷーる様が公開しているブログ「muumoo.jp」 http://muumoo.jp/ でjs製のtwitter投稿ツールが公開されています。手軽につぶやきたいときは、ランチャのbluewindから呼び出して使っていました。 で、jsで投稿できるんだから、取得もできそうだよね、と思って探したら、このブログでバージョンアップ版として公開されていました。 http://muumoo.jp/news/2008/06/24/0twitterclientjs.html 喜び勇んで試してみたのですが、最近のtwitter側仕様変更のため動きません。ならば、と修正と微妙な変更を加えましたので、ここで公開いた…
<p>ぷーる様が公開しているブログ「muumoo.jp」 <a href="http://muumoo.jp/">http://muumoo.jp/</a> でjs製の<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>投稿ツールが公開されています。手軽につぶやきたいときは、ランチャの<a class="keyword" href="http://d.hatena.ne.jp/keyword/bluewind">bluewind</a>から呼び出して使っていました。</p><br />
<p>で、jsで投稿できるんだから、取得もできそうだよね、と思って探したら、このブログでバージョンアップ版として公開されていました。</p><br />
<p><a href="http://muumoo.jp/news/2008/06/24/0twitterclientjs.html">http://muumoo.jp/news/2008/06/24/0twitterclientjs.html</a></p><br />
<p>喜び勇んで試してみたのですが、最近の<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>側仕様変更のため動きません。ならば、と修正と微妙な変更を加えましたので、ここで公開いたします。<br />
とりあえず、twitterclient2.jsとでもしておきます。<br />
<br />
</p>
<pre class="code lang-javascript" data-lang="javascript" data-unlink>(<span class="synIdentifier">function</span>() <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> Twitter = <span class="synIdentifier">function</span>(id, pass)<span class="synIdentifier">{</span>
<span class="synIdentifier">this</span>.id = id;
<span class="synIdentifier">this</span>.pass = pass;
<span class="synIdentifier">this</span>.log = <span class="synIdentifier">{}</span>;
<span class="synIdentifier">}</span>;
Twitter.prototype.Update = <span class="synIdentifier">function</span>(message) <span class="synIdentifier">{</span>
<span class="synStatement">return</span> <span class="synIdentifier">this</span>._get(<span class="synConstant">'http://twitter.com/statuses/update.json'</span>, message, <span class="synConstant">'POST'</span>);
<span class="synIdentifier">}</span>
Twitter.prototype.FriendTimeline = <span class="synIdentifier">function</span>() <span class="synIdentifier">{</span>
<span class="synStatement">return</span> <span class="synIdentifier">this</span>._format(eval(<span class="synIdentifier">this</span>._get(<span class="synConstant">'http://twitter.com/statuses/friends_timeline.json'</span>, <span class="synStatement">null</span>, <span class="synConstant">'GET'</span>)));
<span class="synIdentifier">}</span>
Twitter.prototype.Mentions = <span class="synIdentifier">function</span>() <span class="synIdentifier">{</span>
<span class="synStatement">return</span> <span class="synIdentifier">this</span>._format(eval(<span class="synIdentifier">this</span>._get(<span class="synConstant">'http://twitter.com/statuses/mentions.json'</span>, <span class="synStatement">null</span>, <span class="synConstant">'GET'</span>)));
<span class="synIdentifier">}</span>
Twitter.prototype._get = <span class="synIdentifier">function</span>(url, data, method) <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> xmlhttp = <span class="synStatement">new</span> ActiveXObject(<span class="synConstant">'Msxml2.XMLHTTP'</span>);
xmlhttp.open(method, url, <span class="synConstant">false</span>, <span class="synIdentifier">this</span>.id, <span class="synIdentifier">this</span>.pass);
xmlhttp.setRequestHeader(<span class="synConstant">'Content-Type'</span>, <span class="synConstant">'application/x-www-form-urlencoded'</span>);
xmlhttp.send(data);
<span class="synStatement">if</span>(xmlhttp.<span class="synStatement">status</span> != 200) WScript.echo(xmlhttp.<span class="synStatement">status</span> + <span class="synConstant">' '</span> + xmlhttp.statusText);
<span class="synStatement">return</span> xmlhttp.responseText;
<span class="synIdentifier">}</span>
Twitter.prototype._format = <span class="synIdentifier">function</span>(items) <span class="synIdentifier">{</span>
<span class="synStatement">if</span>(items.length == 0) <span class="synStatement">return</span> <span class="synConstant">''</span>;
<span class="synIdentifier">var</span> statuses = <span class="synConstant">''</span>;
items.sort(<span class="synIdentifier">function</span>(a, b)<span class="synIdentifier">{</span> <span class="synStatement">return</span> a.id - b.id; <span class="synIdentifier">}</span>);
<span class="synStatement">for</span>(<span class="synIdentifier">var</span> i = 0; i < items.length; i++) <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> item = items<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>;
<span class="synStatement">if</span>(<span class="synIdentifier">this</span>.log<span class="synIdentifier">[</span>item.id<span class="synIdentifier">]</span>) <span class="synStatement">continue</span>;
<span class="synIdentifier">var</span> t = item.created_at.split(<span class="synConstant">' '</span>);
<span class="synIdentifier">var</span> d = <span class="synStatement">new</span> <span class="synType">Date</span>(t<span class="synIdentifier">[</span>1<span class="synIdentifier">]</span> + <span class="synConstant">' '</span> + t<span class="synIdentifier">[</span>2<span class="synIdentifier">]</span> + <span class="synConstant">','</span> + t<span class="synIdentifier">[</span>5<span class="synIdentifier">]</span> + <span class="synConstant">' '</span> + t<span class="synIdentifier">[</span>3<span class="synIdentifier">]</span> + <span class="synConstant">' '</span> + t<span class="synIdentifier">[</span>4<span class="synIdentifier">]</span>);
<span class="synIdentifier">var</span> line =
<span class="synConstant">'●'</span> +
item.user.screen_name + <span class="synConstant">' ['</span> +
d.getFullYear() + <span class="synConstant">'.'</span> +
(d.getMonth() + 1) + <span class="synConstant">'.'</span> +
d.getDate() + <span class="synConstant">' '</span> +
d.getHours() + <span class="synConstant">':'</span> +
d.getMinutes() + <span class="synConstant">'] '</span> + <span class="synSpecial">'\n'</span> +
item.text + <span class="synSpecial">'\n'</span>;
<span class="synIdentifier">this</span>.log<span class="synIdentifier">[</span>item.id<span class="synIdentifier">]</span> = 1;
statuses += line;
<span class="synIdentifier">}</span>
<span class="synStatement">return</span> statuses;
<span class="synIdentifier">}</span>
<span class="synIdentifier">var</span> args = WScript.Arguments;
<span class="synStatement">if</span>(args.length < 2) <span class="synStatement">return</span>;
<span class="synIdentifier">var</span> twitter = <span class="synStatement">new</span> Twitter(args.Item(0), args.Item(1));
<span class="synStatement">if</span>(args.length == 2) <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> statuses = twitter.FriendTimeline();
<span class="synStatement">if</span>(statuses.length > 0) WScript.echo(statuses);
<span class="synIdentifier">}</span> <span class="synStatement">else</span> <span class="synStatement">if</span>(args.length == 3 && args.Item(2) == <span class="synConstant">'@'</span>) <span class="synIdentifier">{</span>
<span class="synStatement">while</span>(<span class="synConstant">true</span>) <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> statuses = twitter.Mentions();
<span class="synStatement">if</span>(statuses.length > 0) WScript.echo(statuses);
WScript.Sleep(60 * 1000 * 10); <span class="synComment">// interval 10min</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span> <span class="synStatement">else</span> <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> statuses = <span class="synIdentifier">[]</span>;
<span class="synStatement">for</span>(<span class="synIdentifier">var</span> i = 2; i < args.length; i++) <span class="synIdentifier">{</span>
statuses.push(args.Item(i));
<span class="synIdentifier">}</span>
twitter.Update(<span class="synConstant">'status='</span> + encodeURIComponent(statuses.join(<span class="synConstant">' '</span>)));
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>)();
</pre>
<div class="section">
<h4>使い方</h4>
<p>オリジナルとほぼ変わりません。</p>
<ul>
<li>WScriptで実行すると、結果がダイアログで表示されます。</li>
</ul><p>wscript twitterclient2.js ユーザー名 パスワード</p>
<ul>
<li>CScriptで実行すると、結果が標準出力(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%D7%A5%ED%A5%F3%A5%D7%A5%C8">コマンドプロンプト</a>)に出力されます。</li>
</ul><p>cscript twitterclient2.js ユーザー名 パスワード<br />
<br />
</p>
</div>
<div class="section">
<h4>オリジナルとの変更点</h4>
<ul>
<li>タイムライン取得は一度きりで(常駐せずに)結果を表示して終了します。引数はユーザー名とパスワードです。</li>
<li>返信取得は常駐します。10分ごとにチェックします。引数はユーザー名とパスワードと@です。</li>
</ul><p>(例:wscript twitterclient2.js ユーザー名 パスワード @)</p>
<ul>
<li>発言も一度きりで常駐しません。引数はユーザー名とパスワードと投稿内容です。間違って@のみの投稿をしてしまうと、裏で返信取得として常駐しちゃうのでお気をつけください。</li>
<li>表示フォーマットを微調整</li>
</ul>
</div>
<div class="section">
<h4>注意</h4>
<p>タイムライン取得の場合、常駐しないため、cscriptで実行すると結果が一瞬で閉じてしまって見えません(汗<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%D7%A5%ED%A5%F3%A5%D7%A5%C8">コマンドプロンプト</a>から実行すれば見えるのですが、基本的にはWScriptからの実行を想定しています。(仕事中のチラミとかを想定)</p><br />
<p>返信取得は常駐するので、どちらで実行しても問題ありません。(不意の@を教えてほしいので、常駐します。)</p><br />
<p>あと、取得に関しては大なり小なりは文字化けします。<br />
固定で置換すればよさそうですが、サボってます。</p><br />
<p>常駐した場合の終了方法ですが、cscriptならCtrl-cで。wscriptの場合は、タスクマネージャからwscript.exeを終了させてください。</p>
</div>
Kiri_Feather
Tween
hatenablog://entry/17680117127128277645
2008-11-25T19:17:06+09:00
2008-11-25T19:17:06+09:00 Tween is the client program of twitter. Software requirements OS: Windows 2k/XP/Vista .Net Framework2.0 SP1(or later) Overview Not use twitter API, but get the html(/home,/replies,/directmessage) from twitter web page and scrape it. State is beta, so if you have any problems or requests, please cont…
<p>Tween is the client program of <a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>.</p>
<div class="section">
<h4>Software requirements</h4>
<ul>
<li>OS: <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a> 2k/XP/<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vista">Vista</a></li>
<li>.Net Framework2.0 SP1(or later)</li>
</ul>
</div>
<div class="section">
<h4>Overview</h4>
<p><del datetime="2010-05-08T11:02:28+09:00">Not use <a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>, but get the html(/home,/replies,/directmessage) from <a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a> web page and scrape it.</del><br />
State is beta, so if you have any problems or requests, please contact to @kiri_feather freely.</p>
</div>
<div class="section">
<h4>Operation manual(Japanese only)</h4>
<p>Please visit <a href="http://sourceforge.jp/projects/tween/wiki/FrontPage">Manual Site</a>. (Author <a href="http://twitter.com/syo68k/">@syo68k</a>)</p><p>(Thanks a lot!)<br />
<br />
</p>
</div>
<div class="section">
<h4>Screen shot</h4>
<p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/Kiri_Feather/20071206162730" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/K/Kiri_Feather/20071206/20071206162730.jpg" alt="f:id:Kiri_Feather:20071206162730j:image" title="f:id:Kiri_Feather:20071206162730j:image" class="hatena-fotolife" itemprop="image"></a></span><br />
</p>
</div>
<div class="section">
<h4>Additional icons for Tween(Japanese only)</h4>
<p>The icons using in Tween are created by Minami.(Thanks a lot!)</p><p>You can replace the icons in Tween. Make a folder in the binary placed folder, and rename 'icons', then put some icons in the folder.</p><p>You can get extra icons here.<br />
<a href="http://sourceforge.jp/projects/tween/wiki/%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E9%85%8D%E5%B8%83">http://sourceforge.jp/projects/tween/wiki/%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E9%85%8D%E5%B8%83</a><br />
</p>
</div>
<div class="section">
<h4>Download site</h4>
<p>Latest version<br />
<a href="http://sourceforge.jp/projects/tween/wiki/%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89">http://sourceforge.jp/projects/tween/wiki/%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89</a></p><br />
<p><a href="http://d.hatena.ne.jp/Kiri_Feather/20071121">More informations</a> (Developer's site. Japanese only)</p>
</div>
Kiri_Feather
TwitterとのHTTP通信内容
hatenablog://entry/17680117127128277754
2008-06-03T00:00:00+09:00
2008-06-03T00:00:00+09:00 HTTPヘッダについて keep-alive,connectionは変更する可能性あり。 <サインイン> URL:http://twitter.com/sessions ヘッダ: POST /sessions HTTP/1.1 HOST: twitter.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0 適当でもOK Accept-Encoding: gzip,deflate Connection: close Cookie: 初回は空。以後はTwi…
<pre class="code" data-lang="" data-unlink>HTTPヘッダについて
keep-alive,connectionは変更する可能性あり。
<サインイン>
URL:http://twitter.com/sessions
ヘッダ:
POST /sessions HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0 適当でもOK
Accept-Encoding: gzip,deflate
Connection: close
Cookie: 初回は空。以後はTwitter関連接続で保持しているクッキー
Content-Type: application/x-www-form-urlencoded
Content-Length: データサイズ
データ:username_or_email=ユーザーID&password=パスワード
HTTP応答 302
<Recent取得>
URL:http://twitter.com/home
クエリ:
1ページ目 =なし
2ページ目以降=?page=n
ヘッダ:
GET /home HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
HTTP応答:200
<Replies取得>
※Recent取得との違いは、URLのみ
URL:http://twitter.com/replies
クエリ:
1ページ目 =なし
2ページ目以降=?page=n
ヘッダ:
GET /replies HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
HTTP応答:200
<受信DirectMessage取得>
※Recent取得との違いは、URLと1ページ目もクエリを付けていること。(なくても可)
URL:http://twitter.com/direct_messages
クエリ:?page=n
ヘッダ:
GET /direct_messages HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
HTTP応答:200
<送信DirectMessage取得>
※Recent取得との違いは、URLと1ページ目もクエリを付けていること。(なくても可)
URL:http://twitter.com/direct_messages/sent
クエリ:?page=n
ヘッダ:
GET /direct_messages/sent HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
HTTP応答:200
<投稿(Web)>
※通常、@、DMで差異なし
URL:http://twitter.com/status/update
クエリ:?page=1&tab=home
ヘッダ:
POST /status/update HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: text/javascript, text/html, application/xml, text/xml, */*
x-prototype-version: 1.6.0.1
x-requested-with: XMLHttpRequest
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Content-Length: データサイズ
データ:authenticity_token=認証トークン&authenticity_token=認証トークン&status=発言内容
HTTP応答 200
<投稿(API)>
※通常、@、DMで差異なし
URL:http://twitter.com/statuses/update.xml
クエリ:?page=1&tab=home
ヘッダ:
POST /statuses/update.xml HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Connection: close
Content-Type: application/x-www-form-urlencoded
Accept: text/html, */*
X-Twitter-Client: Tween
X-Twitter-Client-Version: 0.0.8.0
X-Twitter-Client-URL: http://www.asahi-net.or.jp/~ne5h-ykmz/tween.xml
Authorization: Basic ユーザー名:パスワードのBASE64エンコード
Content-Length: データサイズ
データ:status=発言内容&source=Tween
HTTP応答 200
<発言削除(DM除く)>
URL:http://twitter.com/status/destroy/発言ID
ヘッダ:
POST /status/destroy/発言ID HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Content-Type: application/x-www-form-urlencoded
Accept: text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*
Referer: http://twitter.com/home
Content-Length: データサイズ
データ:authenticity_token=認証トークン
HTTP応答 200
<DirectMessage削除>
URL:http://twitter.com/direct_messages/destroy/発言ID
ヘッダ:
GET /direct_messages/destroy/発言ID HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
HTTP応答:200
<Fav追加>
URL:http://twitter.com/favourings/create/発言ID
ヘッダ:
POST /favourings/create/発言ID HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: text/javascript, text/html, application/xml, text/xml, */*
x-prototype-version: 1.6.0.1
x-requested-with: XMLHttpRequest
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Content-Length: データサイズ
データ:authenticity_token=認証トークン
HTTP応答 200
<Fav削除>
URL:http://twitter.com/favourings/destroy/発言ID
ヘッダ:
POST /favourings/destroy/発言ID HTTP/1.1
HOST: twitter.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
Accept-Encoding: gzip,deflate
Connection: close
Cookie: Twitter関連接続で保持しているクッキー
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: text/javascript, text/html, application/xml, text/xml, */*
x-prototype-version: 1.6.0.1
x-requested-with: XMLHttpRequest
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Content-Length: データサイズ
データ:authenticity_token=認証トークン
HTTP応答 200</pre>
Kiri_Feather
GoogleReaderPreviewEnhancedでキーボードショートカットを使えるように
hatenablog://entry/17680117127128277873
2008-03-05T02:05:18+09:00
2008-03-05T02:05:18+09:00 <<<追記>>> 最新版で直っていると思います。今日はTweenではない話。 最近Fx2からFx3β3に乗り換えたり、キーボードランチャ(倉)を導入したりで、キーボードオペレーションをちょこちょこ見直していました。 なるべくアドオンやグリモンの導入は控えめにして、元々メモリ食いのFxを少しでも軽く使えるように心がけていました。常用しているのは、 Googlebar Lite Greasemonkey Remember The Milk for GMail ぐらい。 グリモンは、 AutoPagerize GoogleReaderPreviewEnhanced(リンク先を画面内にフレーム表示) …
<p><<<追記>>><br />
最新版で直っていると思います。</p><p>今日はTweenではない話。<br />
最近Fx2からFx3β3に乗り換えたり、キーボードランチャ(倉)を導入したりで、キーボードオペレーションをちょこちょこ見直していました。<br />
なるべくアドオンやグリモンの導入は控えめにして、元々メモリ食いのFxを少しでも軽く使えるように心がけていました。常用しているのは、</p>
<ul>
<li>Googlebar Lite</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Greasemonkey">Greasemonkey</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Remember%20The%20Milk">Remember The Milk</a> for <a class="keyword" href="http://d.hatena.ne.jp/keyword/GMail">GMail</a></li>
</ul><p>ぐらい。<br />
グリモンは、</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/AutoPagerize">AutoPagerize</a></li>
<li>GoogleReaderPreviewEnhanced(リンク先を画面内にフレーム表示)</li>
</ul><p>といったところ。(少ないでしょ?)</p><br />
<p>キーボードで操作を済ませようとすると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/LDRize">LDRize</a>+Minibufferはすごく便利なので、導入してみました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>検索結果の移動をキーボードで済ませられるようになって便利便利。</p><br />
<p>ただ、前々から気になっていたのがGoogleReaderPreviewEnhancedのキーボードショートカット。通常Shift+Vで機能するはずなのに利かない。これが不満だけど、便利なので捨てる気にもなれず悶々としていたんですが、一度グリモンも作ってみたいなーと思っていたので、勉強がてら改造してみました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>自体、ほとんど触ったことがないんですけどねw</p><br />
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>用にと<a class="keyword" href="http://d.hatena.ne.jp/keyword/FireBug">FireBug</a>を導入して、DOMなどを眺めつつ、試行錯誤を繰り返してたら、なんとか動くようになりました。この拡張自体、あんまり使っている人がいない気がしますが、自分用にソースを張っておきます。</p>
<pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synComment">// Google Reader Preview Enhanced</span>
<span class="synComment">// version 1.07d + KiriCustomize</span>
<span class="synComment">// 2008-03-06</span>
<span class="synComment">// Copyright (c) 2007, Julien CAROSI (jcarosi@gmail.com)</span>
<span class="synComment">// Released under the GPL license</span>
<span class="synComment">// http://www.gnu.org/copyleft/gpl.html</span>
<span class="synComment">//</span>
<span class="synComment">// --------------------------------------------------------------------</span>
<span class="synComment">//</span>
<span class="synComment">// This is a Greasemonkey user script.</span>
<span class="synComment">//</span>
<span class="synComment">// To install, you need Greasemonkey Firefox extension : http://greasemonkey.mozdev.org/</span>
<span class="synComment">// Then restart Firefox and revisit this script.</span>
<span class="synComment">// Click on install.</span>
<span class="synComment">//</span>
<span class="synComment">// --------------------------------------------------------------------</span>
<span class="synComment">// ==UserScript==</span>
<span class="synComment">// @name GPE</span>
<span class="synComment">// @namespace http://userscripts.org/scripts/show/9455</span>
<span class="synComment">// @description Adds a "Preview button" that allows you to view actual article in a frame. Clicking again on that button goes back to RSS view. Does work both in List view and expanded view.</span>
<span class="synComment">// @include http://reader.google.com/reader/*</span>
<span class="synComment">// @include https://reader.google.com/reader/*</span>
<span class="synComment">// @include http://www.google.com/reader/*</span>
<span class="synComment">// @include https://www.google.com/reader/*</span>
<span class="synComment">// ==/UserScript==</span>
<span class="synComment">//</span>
<span class="synComment">// --------------------------------------------------------------------</span>
<span class="synComment">// This script adds a "Preview button" that allows you to view actual article in a frame.</span>
<span class="synComment">// Clicking again on that button goes back to RSS view. Does work both in List view and expanded view.</span>
<span class="synComment">//</span>
<span class="synComment">// Feel free to address comments or improvement suggestions to jcarosi@gmail.com</span>
<span class="synComment">//</span>
<span class="synComment">// --------------------------------------------------------------------</span>
<span class="synComment">// Changelog :</span>
<span class="synComment">// v1.07d + KiriCustomize : ショートカットキーShift+Vを有効に</span>
<span class="synComment">// v1.07d : makes scrolling to top of article work again because google's code was changed. Same for shortcut</span>
<span class="synComment">// v1.07c : fixes problem with Shift V shortcut that prevented typing capital V in GR's dialog boxes</span>
<span class="synComment">// added support for https urls</span>
<span class="synComment">// v1.07b : makes scrolling to top of article work again because google's code was changed. Same for shortcut</span>
<span class="synComment">// v1.07a : makes the script work again because google's code was changed.</span>
<span class="synComment">// added a try/catch statement in order to make the script work even if the code changes again, though not scrolling to the top of article</span>
<span class="synComment">// so people can still use the script until an upgrade is released</span>
<span class="synComment">// v1.07 : allows clicking on an article's title to show the preview, so you don't need to scroll it down to preview it (was opening the article in a new window previously, now not needed with preview functionnality)</span>
<span class="synComment">// v1.06a : fixes compatibility with "find as you type" firefox functionality</span>
<span class="synComment">// v1.06 : adds a keyboard shortcut for previewing an article. Now you can press Shift-V to go to preview mode or go back to rss view.</span>
<span class="synComment">// v1.05a : adds better support for Better GReader extension.</span>
<span class="synComment">// v1.05 : makes the script work again because offline functionnality broke it when it was added by Google.</span>
<span class="synComment">// v1.0 : initial release.</span>
<span class="synComment">// --------------------------------------------------------------------</span>
<span class="synComment">// Tested on Firefox 1.5 and 2.0</span>
<span class="synComment">// --------------------------------------------------------------------</span>
<span class="synIdentifier">function</span> getFirstElementMatchingClassName(root,tag,<span class="synStatement">class</span>)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> elements=root.getElementsByTagName(tag); <span class="synIdentifier">var</span> i=0;
<span class="synStatement">while</span> (elements<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span> && !elements<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>.className.match(<span class="synStatement">class</span>)) <span class="synIdentifier">{</span> i++; <span class="synIdentifier">}</span>
<span class="synStatement">return</span> ((!elements<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>) ? <span class="synStatement">null</span> : (elements<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>));
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> getElementsByClassName(root,tag,<span class="synStatement">class</span>)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> elements = root.getElementsByTagName(tag);
<span class="synIdentifier">var</span> results = <span class="synStatement">new</span> <span class="synType">Array</span>();
<span class="synStatement">for</span>(<span class="synIdentifier">var</span> i=0; i<elements.length; i++) <span class="synIdentifier">{</span> <span class="synStatement">if</span>(elements<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>.className.indexOf(<span class="synStatement">class</span>)>-1) <span class="synIdentifier">{</span> results.push(elements<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>); <span class="synIdentifier">}</span> <span class="synIdentifier">}</span>
<span class="synStatement">return</span> (results);
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> findParentNode(el,tag,<span class="synStatement">class</span>)
<span class="synIdentifier">{</span>
el=el.parentNode;
<span class="synStatement">if</span> (<span class="synIdentifier">arguments</span>.length==3)
<span class="synIdentifier">{</span>
<span class="synComment">// Find first element's parent node matching tag and className</span>
<span class="synStatement">while</span> (el.nodeName.toLowerCase()!=<span class="synConstant">'body'</span> && (el.nodeName.toLowerCase()!=tag || (el.className!=<span class="synStatement">class</span> && el.className.indexOf(<span class="synStatement">class</span>+<span class="synConstant">' '</span>)==-1))) <span class="synIdentifier">{</span> el=el.parentNode; <span class="synIdentifier">}</span>
<span class="synStatement">return</span> ((el.nodeName.toLowerCase()!=<span class="synConstant">'body'</span>) ? el : <span class="synConstant">false</span>);
<span class="synIdentifier">}</span>
<span class="synStatement">else</span>
<span class="synIdentifier">{</span>
<span class="synComment">// Find first element's parent node matching tag</span>
<span class="synStatement">while</span> (el.nodeName.toLowerCase()!=<span class="synConstant">'body'</span> && el.nodeName.toLowerCase()!=tag) <span class="synIdentifier">{</span> el=el.parentNode; <span class="synIdentifier">}</span>
<span class="synStatement">return</span> ((el.nodeName.toLowerCase()!=<span class="synConstant">'body'</span>) ? el : <span class="synConstant">false</span>);
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> addStyles(css)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> head=<span class="synStatement">document</span>.getElementsByTagName(<span class="synConstant">'head'</span>)<span class="synIdentifier">[</span>0<span class="synIdentifier">]</span>;
<span class="synStatement">if</span> (head)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> style=<span class="synStatement">document</span>.createElement(<span class="synConstant">'style'</span>);
style.type=<span class="synConstant">'text/css'</span>;
style.innerHTML=css;
head.appendChild(style);
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> catchEntryAdded(e)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> el=e.target;
<span class="synStatement">if</span> (el.nodeName==<span class="synConstant">'DIV'</span> && el.className.indexOf(<span class="synConstant">'entry'</span>)>-1)
<span class="synIdentifier">{</span>
<span class="synStatement">if</span> (el.className.indexOf(<span class="synConstant">'entry-actions'</span>)>-1)
<span class="synIdentifier">{</span>
<span class="synComment">// Expanding article in list view</span>
addPreviewButton(el);
<span class="synIdentifier">}</span>
<span class="synStatement">else</span> <span class="synStatement">if</span> (getFirstElementMatchingClassName(el,<span class="synConstant">'tbody'</span>,<span class="synConstant">'card-tbody'</span>))
<span class="synIdentifier">{</span>
<span class="synComment">// Adding article in expanded view</span>
addPreviewButton(getFirstElementMatchingClassName(el,<span class="synConstant">'div'</span>,<span class="synConstant">'entry-actions'</span>));
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> addPreviewButton(el)
<span class="synIdentifier">{</span>
<span class="synComment">// Top link</span>
<span class="synIdentifier">var</span> entry=findParentNode(el,<span class="synConstant">'div'</span>,<span class="synConstant">'entry'</span>);
<span class="synIdentifier">var</span> link=getFirstElementMatchingClassName(entry,<span class="synConstant">'a'</span>,<span class="synConstant">'entry-title-link'</span>);
link.addEventListener(<span class="synConstant">'click'</span>, previewMouseClick, <span class="synConstant">false</span>);
<span class="synComment">// link.addEventListener('click', function(e) { if (e.ctrlKey) { previewMouseClick(e); } }, false);</span>
<span class="synComment">// Bottom button</span>
<span class="synIdentifier">var</span> preview=<span class="synStatement">document</span>.createElement(<span class="synConstant">'span'</span>);
preview.className=<span class="synConstant">'item-preview preview link'</span>;
preview.innerHTML=<span class="synConstant">'Preview'</span>;
el.appendChild(preview);
preview.addEventListener(<span class="synConstant">'click'</span>, previewMouseClick, <span class="synConstant">false</span>);
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> calcEntryIndex(e)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> index=0;
<span class="synStatement">while</span> (e.previousSibling)
<span class="synIdentifier">{</span>
index++;
e=e.previousSibling;
<span class="synIdentifier">}</span>
<span class="synStatement">return</span> index;
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> previewMouseClick(e)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> el=e.target;
<span class="synIdentifier">var</span> entry=findParentNode(el,<span class="synConstant">'div'</span>,<span class="synConstant">'entry'</span>);
<span class="synIdentifier">var</span> index = calcEntryIndex(entry);
preview(entry,index);
e.preventDefault();
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> previewShortcut()
<span class="synIdentifier">{</span>
<span class="synComment">// Add below 3 lines by Kiri 2008-3-6</span>
<span class="synIdentifier">var</span> entry=<span class="synStatement">document</span>.getElementById(<span class="synConstant">'current-entry'</span>);
<span class="synIdentifier">var</span> index = calcEntryIndex(entry);
preview(entry,index);
<span class="synComment">// Delete below 6 lines by Kiri 2008-3-6</span>
<span class="synComment">// var index=unsafeWindow.s.ma;</span>
<span class="synComment">// if (index>-1)</span>
<span class="synComment">// {</span>
<span class="synComment">// // An article is selected, preview it</span>
<span class="synComment">// preview(getEntryDOMObject(index),index);</span>
<span class="synComment">// }</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> preview(entry,index)
<span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> preview;
<span class="synIdentifier">var</span> button = getFirstElementMatchingClassName(entry,<span class="synConstant">'span'</span>,<span class="synConstant">'item-preview'</span>);
<span class="synComment">// Update entry with preview mode, need to do it before scrolling, because scrolling will repaint preview button (list view only)</span>
<span class="synStatement">if</span> (entry.className.indexOf(<span class="synConstant">'preview'</span>)==-1)
<span class="synIdentifier">{</span>
entry.className=entry.className+<span class="synConstant">' preview'</span>;
preview=<span class="synConstant">true</span>;
<span class="synIdentifier">}</span>
<span class="synStatement">else</span>
<span class="synIdentifier">{</span>
entry.className=entry.className.replace(<span class="synConstant">'preview'</span>,<span class="synConstant">''</span>);
preview=<span class="synConstant">false</span>;
<span class="synIdentifier">}</span>
<span class="synComment">// Need to scroll before changing entry-body, because scrolling repaints article from scratch (list view only)</span>
scrollTo(index);
root = getEntryDOMObject(index);
<span class="synIdentifier">var</span> body = getFirstElementMatchingClassName(entry,<span class="synConstant">'div'</span>,<span class="synConstant">'entry-body'</span>);
<span class="synIdentifier">var</span> ins = body.getElementsByTagName(<span class="synConstant">'ins'</span>)<span class="synIdentifier">[</span>0<span class="synIdentifier">]</span>;
<span class="synStatement">if</span> (preview)
<span class="synIdentifier">{</span>
<span class="synComment">// classic mode-> preview mode</span>
<span class="synComment">// hide rss item</span>
ins.style.display=<span class="synConstant">'none'</span>;
<span class="synComment">// iframe creation/display</span>
<span class="synIdentifier">var</span> iframe = getFirstElementMatchingClassName(entry,<span class="synConstant">'iframe'</span>,<span class="synConstant">'preview'</span>);
<span class="synStatement">if</span> (iframe)
<span class="synIdentifier">{</span>
<span class="synComment">// iframe already in document, display it</span>
iframe.style.display=<span class="synConstant">'block'</span>;
<span class="synIdentifier">}</span>
<span class="synStatement">else</span>
<span class="synIdentifier">{</span>
<span class="synComment">// iframe not in document, create it</span>
iframe = <span class="synStatement">document</span>.createElement(<span class="synConstant">'iframe'</span>);
iframe.setAttribute(<span class="synConstant">'width'</span>,<span class="synConstant">'100%'</span>);
iframe.setAttribute(<span class="synConstant">'height'</span>,<span class="synConstant">'500px'</span>);
iframe.setAttribute(<span class="synConstant">'src'</span>,getFirstElementMatchingClassName(entry,<span class="synConstant">'a'</span>,<span class="synConstant">'entry-title-link'</span>));
iframe.className=<span class="synConstant">'preview'</span>;
body.appendChild(iframe);
<span class="synIdentifier">}</span>
<span class="synComment">// Scale article container to fullwidth</span>
body.setAttribute(<span class="synConstant">'style'</span>,<span class="synConstant">'max-width: 98%'</span>);
<span class="synIdentifier">}</span>
<span class="synStatement">else</span>
<span class="synIdentifier">{</span>
<span class="synComment">// preview mode -> classic mode</span>
<span class="synComment">// hide iframe</span>
<span class="synIdentifier">var</span> iframe = getFirstElementMatchingClassName(entry,<span class="synConstant">'iframe'</span>,<span class="synConstant">'preview'</span>);
<span class="synStatement">if</span> (iframe) iframe.style.display=<span class="synConstant">'none'</span>;
<span class="synComment">// show rss item</span>
ins.style.display=<span class="synConstant">'block'</span>;
<span class="synComment">// Go back to initial width</span>
body.removeAttribute(<span class="synConstant">'style'</span>,<span class="synConstant">''</span>);
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> handleKeypress(e)
<span class="synIdentifier">{</span>
<span class="synComment">// Handle a Shift-V keypress</span>
<span class="synStatement">if</span> (e.target.nodeName.toLowerCase()!=<span class="synConstant">'input'</span> && e.shiftKey && e.keyCode==86)
<span class="synIdentifier">{</span>
previewShortcut();
e.preventDefault();
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> getEntryDOMObject(index)
<span class="synIdentifier">{</span>
<span class="synComment">// Because of repaint, entry doesn't point to correct DOM object, we need to find entry using index</span>
<span class="synIdentifier">var</span> entries=<span class="synStatement">document</span>.getElementById(<span class="synConstant">'entries'</span>);
<span class="synIdentifier">var</span> i=0;
entry=entries.firstChild;
<span class="synStatement">while</span> ((i++)<index)
<span class="synIdentifier">{</span>
entry=entry.nextSibling;
<span class="synIdentifier">}</span>
<span class="synStatement">return</span> entry;
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> scrollTo(index)
<span class="synIdentifier">{</span>
<span class="synComment">// Force scrolling to top of article</span>
<span class="synStatement">try</span>
<span class="synIdentifier">{</span>
<span class="synStatement">location</span>.href = <span class="synConstant">'javascript:void(s.ma=-1);'</span>;
<span class="synStatement">location</span>.href = <span class="synConstant">'javascript:void(s.hf('</span>+index+<span class="synConstant">'));'</span>;
<span class="synIdentifier">}</span>
<span class="synStatement">catch</span>(err) <span class="synIdentifier">{</span> <span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> restyle()
<span class="synIdentifier">{</span>
<span class="synComment">// Overwrites Better GReader extension css modifications regarding entry-actions class.</span>
<span class="synComment">// Indeed, entry-actions was set to "float : right", thus div was not in document flow.</span>
<span class="synComment">// Then, clicking on preview button let entry actions div in place instead of going down automatically when iframe was added.</span>
<span class="synComment">// That's why I use here text-align: right. That has the same effect, but keeps div in document flow.</span>
<span class="synComment">// restyle() is called after document load, in order to ensure that Better GReader has already added its styles modifications</span>
<span class="synIdentifier">var</span> styles = <span class="synStatement">document</span>.getElementsByTagName(<span class="synConstant">'head'</span>)<span class="synIdentifier">[</span>0<span class="synIdentifier">]</span>.getElementsByTagName(<span class="synConstant">'style'</span>);
<span class="synIdentifier">var</span> i=0;
<span class="synStatement">while</span> (i<styles.length)
<span class="synIdentifier">{</span>
<span class="synStatement">if</span> (styles<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>.innerHTML.indexOf(<span class="synConstant">'.entry-actions { float:right !important; }'</span>)>-1)
<span class="synIdentifier">{</span>
styles<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>.innerHTML=styles<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>.innerHTML.replace(<span class="synConstant">'.entry-actions { float:right !important; }'</span>,<span class="synConstant">'.entry-actions { text-align: right; !important; }'</span>);
<span class="synIdentifier">}</span>
i++;
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">function</span> init()
<span class="synIdentifier">{</span>
restyle();
addStyles(<span class="synConstant">'span.item-preview { background: url("data:image/gif,GIF89a%10%00%10%00%D5%13%00%D8%D8%D8%FA%FA%FA%CB%CB%CB%C8%C8%C8%D2%D2%D2%BA%BA%BA%C6%C6%C6%A1%A1%A1%9C%9C%9C%BD%BD%BD%C9%C9%C9%AB%AB%AB%F4%F4%F4%BF%BF%BF%FC%FC%FC%DB%DB%DB%AD%AD%AD%FF%FF%FF%CC%CC%CC%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%13%00%2C%00%00%00%00%10%00%10%00%00%06I%C0%89pH%2C%1A%8F%C8d%F1!i%3A%9F%8F%E1%03B%ADZ%A9%D1%89%04%12%E9z%BF%10%89p%FB-G%C2c%AE%D9%8B%D6%AA%03_%F8Y%EC%8E%C8%E3%F3%F4%9AM</span><span class="synSpecial">\'</span><span class="synConstant">%7B%1D%0E%60t%00W%85%10%00RO%8A%12YJ%8E%8EA%00%3B") no-repeat; padding-left: 16px; } div.entry.preview span.item-preview { background: url("data:image/gif,GIF89a%10%00%10%00%A2%05%00%D8%D8%D8%DB%DB%DB%AD%AD%AD%CC%CC%CC%FE%9A%20%FF%FF%FF%00%00%00%00%00%00!%F9%04%01%00%00%05%00%2C%00%00%00%00%10%00%10%00%00%03%3BX%BA%DC%FE0%B60%AA%BDa%05%C1%BB%E7Y1%08Di%9E%C2%A0%8C%A6%D7%AA%22Y%CA2%91%AE%B5%3B%C3%EC%7C%EE%B8%D6%CF%C6%AB%0D%89%0A%C0g)%00h.%D0AHB%A5%26%00%00%3B") no-repeat; padding-left: 16px; }'</span>);
<span class="synIdentifier">}</span>
<span class="synStatement">document</span>.body.addEventListener(<span class="synConstant">'DOMNodeInserted'</span>, catchEntryAdded, <span class="synConstant">false</span>);
<span class="synStatement">document</span>.addEventListener(<span class="synConstant">'keydown'</span>,handleKeypress, <span class="synConstant">false</span>);
<span class="synStatement">window</span>.addEventListener(<span class="synConstant">'load'</span>,init,<span class="synConstant">false</span>);
</pre>
Kiri_Feather
0.0.4.3
hatenablog://entry/17680117127128278289
2008-02-23T02:22:53+09:00
2008-02-23T02:22:53+09:00 URL中のTwitterコマンドを無視するように修正 更新履歴はこちら→http://d.hatena.ne.jp/Kiri_Feather/20071121 ダウンロードはこちら→http://www.asahi-net.or.jp/~ne5h-ykmz/index.html
<ul>
<li>URL中の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>コマンドを無視するように修正</li>
</ul><p><br />
更新履歴はこちら→<a href="http://d.hatena.ne.jp/Kiri_Feather/20071121">http://d.hatena.ne.jp/Kiri_Feather/20071121</a><br />
ダウンロードはこちら→<a href="http://www.asahi-net.or.jp/~ne5h-ykmz/index.html">http://www.asahi-net.or.jp/~ne5h-ykmz/index.html</a></p>
Kiri_Feather
0.0.4.4
hatenablog://entry/17680117127128278230
2008-02-23T02:22:52+09:00
2008-02-23T02:22:52+09:00 リスト描画方式変更(0.0.4.1〜3よりメモリにやさしい、と思う) Fav追加/削除を同期処理に戻した Fav追加/削除したとき、発言詳細の名前文字色を即時変更するようにした DMリストで「ステータスを開く」コマンドを無効にした(まだ暴発しますが・・・) Twitterコマンドの判別条件を緩和。発言に失敗した場合はお知らせいただけると助かります。 発言詳細の表示が変更された場合のナビゲート音を出さないように変更 複数発言のFav時に、確認メッセージを追加
<ul>
<li>リスト描画方式変更(0.0.4.1〜3よりメモリにやさしい、と思う)</li>
<li>Fav追加/削除を同期処理に戻した</li>
<li>Fav追加/削除したとき、発言詳細の名前文字色を即時変更するようにした</li>
<li>DMリストで「ステータスを開く」コマンドを無効にした(まだ暴発しますが・・・)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>コマンドの判別条件を緩和。発言に失敗した場合はお知らせいただけると助かります。</li>
<li>発言詳細の表示が変更された場合のナビゲート音を出さないように変更</li>
<li>複数発言のFav時に、確認メッセージを追加</li>
</ul>
Kiri_Feather
0.0.4.5
hatenablog://entry/17680117127128278160
2008-02-23T02:22:51+09:00
2008-02-23T02:22:51+09:00 Fav削除でエラーが発生する問題に対応
<ul>
<li>Fav削除でエラーが発生する問題に対応</li>
</ul>
Kiri_Feather
0.0.4.1
hatenablog://entry/17680117127128278417
2008-02-21T17:10:39+09:00
2008-02-21T17:10:39+09:00 リストのチラつきをなくしました Twitterコマンドが含まれる発言が「DM宛先間違い」で投稿できない問題に対応しました 自分でも使用に耐えないぐらいリストがチラついていたので、ダブルバッファをONにしてみました。今のところ良い感じ。チラつきがほぼなくなりました! Twitterコマンドが含まれる投稿をしようとした場合に、「DM宛先間違い」というエラー(←本当は正しくない><)で投稿できない場合が結構あったので、投稿文をちょびっとだけいじって、引っかからないようにしました。 「エラーで投稿できないよ!」とか「本文が変になっちゃったよ!」とかありましたら、お知らせくださいませ。 更新履歴はこちら…
<ul>
<li>リストのチラつきをなくしました</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>コマンドが含まれる発言が「DM宛先間違い」で投稿できない問題に対応しました</li>
</ul><p><br />
自分でも使用に耐えないぐらいリストがチラついていたので、ダブルバッファをONにしてみました。今のところ良い感じ。チラつきがほぼなくなりました!<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>コマンドが含まれる投稿をしようとした場合に、「DM宛先間違い」というエラー(←本当は正しくない><)で投稿できない場合が結構あったので、投稿文をちょびっとだけいじって、引っかからないようにしました。<br />
「エラーで投稿できないよ!」とか「本文が変になっちゃったよ!」とかありましたら、お知らせくださいませ。</p><br />
<p>更新履歴はこちら→<a href="http://d.hatena.ne.jp/Kiri_Feather/20071121">http://d.hatena.ne.jp/Kiri_Feather/20071121</a><br />
ダウンロードはこちら→<a href="http://www.asahi-net.or.jp/~ne5h-ykmz/index.html">http://www.asahi-net.or.jp/~ne5h-ykmz/index.html</a></p>
Kiri_Feather
0.0.4.2
hatenablog://entry/17680117127128278350
2008-02-21T17:10:38+09:00
2008-02-21T17:10:38+09:00 はわわ。ちょいと広範にいじりすぎました。(という言い訳) バグ修正&手動での最新版取得機能追加です。 Recentのリストで、リストアイコンサイズ24,48の場合に、折り返し表示されないバグ修正 Reply,DMのリストで、右クリックメニューが表示されないバグ修正 手動での最新版取得メニューを追加
<p>はわわ。ちょいと広範にいじりすぎました。(という言い訳)<br />
バグ修正&手動での最新版取得機能追加です。</p>
<ul>
<li>Recentのリストで、リストアイコンサイズ24,48の場合に、折り返し表示されないバグ修正</li>
<li>Reply,DMのリストで、右クリックメニューが表示されないバグ修正</li>
<li>手動での最新版取得メニューを追加</li>
</ul>
Kiri_Feather
0.0.4.0
hatenablog://entry/17680117127128278488
2008-02-20T09:27:09+09:00
2008-02-20T09:27:09+09:00 バグ修正でーす。 DMの発言詳細表示がされないバグ修正 新着取得時に発言詳細部が再描画される問題を修正 POST中のreply、DM発言操作補助が効いてしまうバグ修正 更新履歴はこちら→http://d.hatena.ne.jp/Kiri_Feather/20071121 ダウンロードはこちら→http://www.asahi-net.or.jp/~ne5h-ykmz/index.html
<p>バグ修正でーす。</p>
<ul>
<li>DMの発言詳細表示がされないバグ修正</li>
<li>新着取得時に発言詳細部が再描画される問題を修正</li>
<li>POST中のreply、DM発言操作補助が効いてしまうバグ修正</li>
</ul><p><br />
更新履歴はこちら→<a href="http://d.hatena.ne.jp/Kiri_Feather/20071121">http://d.hatena.ne.jp/Kiri_Feather/20071121</a><br />
ダウンロードはこちら→<a href="http://www.asahi-net.or.jp/~ne5h-ykmz/index.html">http://www.asahi-net.or.jp/~ne5h-ykmz/index.html</a></p>
Kiri_Feather
0.0.3.8
hatenablog://entry/17680117127128278602
2008-02-19T18:26:11+09:00
2008-02-19T18:26:11+09:00 0.0.3.8。なぜかRepliesページの2ページ目が取得できなくなっていることへの対応。 まあ、1ページ目しかとっていないんですが。 Recent、Repliesの1ページ目取得時に、pageクエリを付加しないよう変更 更新履歴はこちら→http://d.hatena.ne.jp/Kiri_Feather/20071121 ダウンロードはこちら→http://www.asahi-net.or.jp/~ne5h-ykmz/index.html
<p>0.0.3.8。なぜかRepliesページの2ページ目が取得できなくなっていることへの対応。<br />
まあ、1ページ目しかとっていないんですが。</p>
<ul>
<li>Recent、Repliesの1ページ目取得時に、pageクエリを付加しないよう変更</li>
</ul><p><br />
更新履歴はこちら→<a href="http://d.hatena.ne.jp/Kiri_Feather/20071121">http://d.hatena.ne.jp/Kiri_Feather/20071121</a><br />
ダウンロードはこちら→<a href="http://www.asahi-net.or.jp/~ne5h-ykmz/index.html">http://www.asahi-net.or.jp/~ne5h-ykmz/index.html</a></p>
Kiri_Feather
0.0.3.9
hatenablog://entry/17680117127128278532
2008-02-19T18:26:10+09:00
2008-02-19T18:26:10+09:00 0.0.3.9。リスト描画の高速化、とは名ばかりで、リストの色変えと発言詳細部の書き換えを0.1秒後に行うよう変更。 ついでに、次から自動バージョンチェックが走るようになります。 リスト描画高速化 自動バージョンチェック&更新追加 更新履歴はこちら→http://d.hatena.ne.jp/Kiri_Feather/20071121 ダウンロードはこちら→http://www.asahi-net.or.jp/~ne5h-ykmz/index.html
<p>0.0.3.9。リスト描画の高速化、とは名ばかりで、リストの色変えと発言詳細部の書き換えを0.1秒後に行うよう変更。<br />
ついでに、次から自動バージョンチェックが走るようになります。</p>
<ul>
<li>リスト描画高速化</li>
<li>自動バージョンチェック&更新追加</li>
</ul><p><br />
更新履歴はこちら→<a href="http://d.hatena.ne.jp/Kiri_Feather/20071121">http://d.hatena.ne.jp/Kiri_Feather/20071121</a><br />
ダウンロードはこちら→<a href="http://www.asahi-net.or.jp/~ne5h-ykmz/index.html">http://www.asahi-net.or.jp/~ne5h-ykmz/index.html</a></p>
Kiri_Feather