2010/05/22

ソースを整理して通常版とOpenWrt版を統合

ーーーーーーーーーー
この記事は古いです
ここを開いて一番上に出てきた記事に最新版が貼ってあります、たぶん
ーーーーーーーーーー

だいぶソースを整理した
wgetとcurlの切り替え対応
OpenWrtではiconvが無いので投稿のみ
一時ファイルはrep.sedだけになりました
一度目の起動時にPIN等の取得を試みます

タイムライン表示

$ shtter.sh


投稿

$ shtter.sh update "foobar"


Fedora(12 x86_64)とOpenWrt(KAMIKAZE 8.09.2)で動作を確認しています
Fedoraで使用する場合はwgetをインストールしてください
OpenWrtで使用する場合はopenssl-utilとcurlをインストールして
HTTP_GETとHTTP_POSTをcurlに切り替えてください


使ってるコマンド (全部あるか確認してください)

dd md5sum cut date echo sed grep sort uniq hexdump rm printf iconv openssl read wget/curl


shtter.sh (last update 2010/05/22)
This script lisence is GPL.

#!/bin/sh

CKEY="U3DhP7CpPx0bNCzdAFShg"
CSECRET="eAQ13OTo7BhroXQc5dA5oOqEuXhAf7yABVKpkbR7so"
AKEY=""
ASECRET=""

HTTP_GET="wget -q -O -"
HTTP_POST="wget -q -O - --post-data"
#HTTP_GET="curl -s"
#HTTP_POST="curl -s --data"

TMPDIR="/tmp"

PREFIX=""
SUFFIX=" http://bit.ly/dsKezn #shtter"

GenerateNonce()
{
dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | cut -c1-32
}

GetTimeStamp()
{
date +%s
}

Encode()
{
echo "$@" | sed 's/./\0\n/g' | grep '[^-._~0-9a-zA-Z]' | sort | uniq | while read l
do
if [ "$l" == "" ]; then l=" "; fi

HEX="`echo -n \"$l\" | hexdump -e '16/1 "%02X" "\n"'`"

if [ "$l" == "/" ]; then l="\/"; fi
echo "s/$l/$HEX"
done | sed 's/ *$//; s/\([0-9A-Z]\{2\}\)/%\1/g; s/$/\/g/' >"$TMPDIR/rep.sed"

echo "$@" | sed -f "$TMPDIR/rep.sed"

rm "$TMPDIR/rep.sed"
}

Decode()
{
HEX="`echo -e "$@" | sed 's/&#[0-9]\+;/\n\0\n/g' | sed '/^&#[0-9]\+;$/!d; s/[&#;]//g' | sort | uniq`"
HEX="`echo -e \"$HEX\" | while read l; do echo -n \"$l\" | hexdump -e '8/1 "%02x00"'; printf '%04x\n' "$l"; done`"
HEX="`echo -e \"$HEX\" | sed 's/ 00//g; s/^/73002f0026002300/; s/\(..\)\(..\)$/3b002f00\2\12f0067000a00/'`"
HEX="`echo $HEX | sed 's/ //g; s/../\\\x\0/g'`"
printf "$HEX" | iconv -f UTF-16 -t UTF-8 >"$TMPDIR/rep.sed"

echo -e "$@" | sed -f "$TMPDIR/rep.sed"

rm "$TMPDIR/rep.sed"
}

GenerateHash()
{
EURL="`Encode $2`"
EPARAM="`Encode $3`"
QUERY="$1&$EURL&$EPARAM"

HASH="`echo -n \"$QUERY\" | openssl sha1 -hmac \"$CSECRET&$ASECRET\" -binary | openssl base64`"
Encode "$HASH"
}

GetRequestToken()
{
URL="http://twitter.com/oauth/request_token"
PARAM="oauth_consumer_key=$CKEY&oauth_nonce=`GenerateNonce`&oauth_signature_method=HMAC-SHA1&oauth_timestamp=`GetTimeStamp`&oauth_token=&oauth_version=1.0"
HASH="`GenerateHash \"GET\" \"$URL\" \"$PARAM\"`"

RTOKEN="`$HTTP_GET \"$URL?$PARAM&oauth_signature=$HASH\"`"
if [ "$RTOKEN" == "" ]; then
echo "can not get request token" >&2
exit 1
fi

RKEY="`echo \"$RTOKEN\" | sed 's/.*oauth_token=\([^&]*\).*/\1/'`"
RSECRET="`echo \"$RTOKEN\" | sed 's/.*oauth_token_secret=\([^&]*\).*/\1/'`"

echo "open this url in your browsser and input pin" >&2
echo "http://twitter.com/oauth/authorize?oauth_token=$RKEY" >&2
echo -n "pin > " >&2
read PIN

echo "$RKEY $RSECRET $PIN"
}

GetAccessToken()
{
RKEY="$1"
RSECRET="$2"
PIN="$3"

URL="http://twitter.com/oauth/access_token"
PARAM="oauth_consumer_key=$CKEY&oauth_nonce=`GenerateNonce`&oauth_signature_method=HMAC-SHA1&oauth_timestamp=`GetTimeStamp`&oauth_token=$RKEY&oauth_verifier=$PIN&oauth_version=1.0"
HASH="`GenerateHash \"GET\" \"$URL\" \"$PARAM\"`"

ATOKEN="`$HTTP_GET \"$URL?$PARAM&oauth_signature=$HASH\"`"
if [ "$ATOKEN" == "" ]; then
echo "can not get access token" >&2
exit 1
fi

AKEY="`echo $ATOKEN | sed 's/.*oauth_token=\([^&]*\).*/\1/'`"
ASECRET="`echo $ATOKEN | sed 's/.*oauth_token_secret=\([^&]*\).*/\1/'`"

sed -i "1,/^AKEY/ s/^\(AKEY=\).*/\1\"$AKEY\"/" "$0"
sed -i "1,/^ASECRET/ s/^\(ASECRET=\).*/\1\"$ASECRET\"/" "$0"
}

GetTimeLine()
{
URL="http://api.twitter.com/1/statuses/home_timeline.xml"
PARAM="oauth_consumer_key=$CKEY&oauth_nonce=`GenerateNonce`&oauth_signature_method=HMAC-SHA1&oauth_timestamp=`GetTimeStamp`&oauth_token=$AKEY&oauth_version=1.0&status="
HASH="`GenerateHash \"GET\" \"$URL\" \"$PARAM\"`"

XML="`$HTTP_GET \"$URL?$PARAM&oauth_signature=$HASH\"`"
if [ "$XML" == "" ]
then
echo "can not get TimeLine" >&2
exit 1
fi

XML="`echo $XML | sed 's/<text>/\n\0/g; s/<\/screen_name>/\0\n/g' | sed -n '/^<text>.*<\/screen_name>$/!d; s/<text>\([^<]*\).*<screen_name>\([^<]*\).*/\2: \1/; p'`"
Decode "$XML"
}

UpdateTimeLine()
{
TWEET="`Encode \"$PREFIX$@$SUFFIX\"`"
if [ "$TWEET" == "" ]
then
echo "can not decode tweet" >&2
exit 1
fi

URL="http://api.twitter.com/1/statuses/update.xml"
PARAM="oauth_consumer_key=$CKEY&oauth_nonce=`GenerateNonce`&oauth_signature_method=HMAC-SHA1&oauth_timestamp=`GetTimeStamp`&oauth_token=$AKEY&oauth_version=1.0&status=$TWEET"
HASH="`GenerateHash \"POST\" \"$URL\" \"$PARAM\"`"

XML="`$HTTP_POST \"$PARAM&oauth_signature=$HASH\" \"$URL\"`"
if [ "$XML" == "" ]
then
echo "can not post tweet" >&2
exit 1
fi
}

if [ "$AKEY" == "" -o "$ASECRET" == "" ]
then
RTOKEN="`GetRequestToken`"
GetAccessToken $RTOKEN
else
ARG="$1"
shift 1

case "$ARG" in
init)
sed -i "1,/^AKEY/ s/^\(AKEY=\).*/\1/" "$0"
sed -i "1,/^ASECRET/ s/^\(ASECRET=\).*/\1/" "$0"
;;
update)
UpdateTimeLine "$@"
;;
*)
GetTimeLine
;;
esac
fi

16 件のコメント:

  1. Hi!
    I think this is really cool-I'm trying to use it on my wireless router. It's working..somewhat, not completely (I guess it might be related to http vs https).
    If possible, it would be cool if you could manually translate this post into English.
    Cheers
    Dan

    返信削除
  2. Hi Dan.
    I was thought that nobody is using it.
    Thank you for using this app.
    About https had been simply forgotten... :P
    When I can take time, research information about https and update this script.
    I hope that can get across my English.
    Bye.

    返信削除
  3. I can't get it to work. I'm very frustrate. I get a "sh: closing paren expected" and I don't know where those parenthesis are. =/

    返信削除
  4. Hi Massayoshi.
    Sorry, please try bash or ash.

    返信削除
  5. このコメントは投稿者によって削除されました。

    返信削除
  6. Should I escape double quote char in the line 70 etc.?

    返信削除
  7. oops. please ignore the previous comment.

    返信削除
  8. Hi, This works very well for getting timelines, and seems to do the oauth properly for that, but I can't get it to post an update at all. I just get "Could not authenticate with OAuth." back, in a 401. I can't for the life of me work out what's different between the get and the post...

    返信削除
  9. Mmm I cannot find a way to install iconv from the latest openwrt sources.

    Any suggestion?

    返信削除
  10. Hi Enrique.
    Thank you for your comment.
    But I'm not sure.
    I'm not using for getting timeline this script on openwrt.
    I think you can build from source.
    http://downloads.openwrt.org/sources/libiconv-1.11.1.tar.gz
    Download this file and extract it.
    Move in to extracted directory.
    and execute ./configure && make
    Maybe you can get binary src/iconv_no_i18n.

    返信削除
  11. 素晴らしいスクリプト、ありがとうございます。とても重宝しております。
    シェルだけで Twitter クライアントってできるのですね。

    返信削除
  12. 以前から shtter を活用させていただいておりました。ありがとうございます。

    Twitter API 1.0 が完全停止され使えなくなったのですが、
    試したところ、Twitter API 1.1 対応として、下記のパッチでプログラムを修正し、認証しなおせば、投稿できるようになりました。
    (ただし、取得したタイムラインのパースは行っていないです。)

    API 1.1 対応のお役に立てば幸いです。

    70,74c70,75
    < URL="http://twitter.com/oauth/request_token"
    < PARAM="oauth_consumer_key=$CKEY&oauth_nonce=`GenerateNonce`&oauth_signature_method=HMAC-SHA1&oauth_timestamp=`GetTimeStamp`&oauth_token=&oauth_version=1.0"
    < HASH="`GenerateHash \"GET\" \"$URL\" \"$PARAM\"`"
    <
    < RTOKEN="`$HTTP_GET \"$URL?$PARAM&oauth_signature=$HASH\"`"
    ---
    > URL="https://api.twitter.com/oauth/request_token"
    > NONCE="`GenerateNonce`"
    > TIMESTAMP="`GetTimeStamp`"
    > PARAM="oauth_callback=&oauth_consumer_key=$CKEY&oauth_nonce=$NONCE&oauth_signature_method=HMAC-SHA1&oauth_timestamp=$TIMESTAMP&oauth_version=1.0"
    > HASH="`GenerateHash \"POST\" \"$URL\" \"$PARAM\"`"
    > RTOKEN="`wget -q -O - --post-data=\"\" --header=\"Authorization: OAuth oauth_nonce=\"$NONCE\", oauth_callback=\"\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"$TIMESTAMP\", oauth_consumer_key=\"$CKEY\", oauth_signature=\"$HASH\", oauth_version=\"1.0\"\" $URL`"
    116c117
    < URL="http://api.twitter.com/1/statuses/home_timeline.xml"
    ---
    > URL="https://api.twitter.com/1.1/statuses/home_timeline.json"
    140c143
    < URL="http://api.twitter.com/1/statuses/update.xml"
    ---
    > URL="http://api.twitter.com/1.1/statuses/update.json"

    返信削除
  13. うめさん

    ありがとうございます
    ソースをGithubに移動してパッチを当てたブランチを作成しました
    https://github.com/lostman-github/shtter/tree/v1.1-patched

    返信削除
  14. Did you know you can create short urls with AdFly and make money for every click on your short links.

    返信削除