C++ Rest SDKでtwitter③

e-tipsmemo.hatenablog.com
続き。

認証が完了したら、
oauth_tokenはaccess token
oauth_token_secretはaccess token secret
を得ている。

ツイートを行う。


signatureを作るパラメータにはツイートと、画像をアップロードしてmedia_idがあるならばあるならばmedia_idsを入れる。
画像がないときは、meida_idsのパラメータ自体がなくてもよいし、その値が、空白(media_ids="")でもよい。


ツイートとmedia_idsはbodyに入れるので、parameterから消しておく。


bodyにはツイートとmedia_idsを入れる。
media_idは9桁の数字なので、四枚ツイートとするとき以下のようになる。
status=ツイート内容&media_ids=[9桁の数字],[9桁の数字],[9桁の数字],[9桁の数字]

あとは、httprequestするだけ。

ツイートidとかがjsonで帰ってくる。

ツイートidはメンションつたり、ツイート削除するときに必要となる。

プログラミング言語C++ 第4版

プログラミング言語C++ 第4版

投稿記事が100を超えた

記念すべき100記事目は
http://e-tipsmemo.hatenablog.com/entry/2018/07/08/000000e-tipsmemo.hatenablog.com

であった。
3日に1記事書くことを目標にやっているので、100記事増えるのに、だいたい1年ぐらいかかる。

記事のカテゴリは適当につけているけれどもどうしても
ソフトウェアは試行が楽なので記事の数が多くなってしまいがち。

でもハードウェアの記事も書けば結構見られているきがするし、
逆にネットにそういう記事が少ないからこそ書くというのは
ビュー数を増やす戦略になりえるかもしれない。

10000ビュー超えた記事からあまり時間が経ってはいないけれども、
はてな管理画面で見られている記事ランクを以下に示す。
(2018/07/05時点、この時点での訪問数ははてな管理画面によると、12757)

e-tipsmemo.hatenablog.com
訪問数の10%が見ているらしい。
しかしココ最近になってこの記事が急上昇しているきがする(気のせいかも)ので、
クローラー的ななにかが頻繁にきているとも思えないし、
EZ-USB FX2を使うひとはまだまだいるということだなぁと思う。

e-tipsmemo.hatenablog.com
9%の人が見たらしい。
上のEZ-USBの記事と順位が入れ替わることもある。

AMDRyzen CPUは2017年から2019、2020年にかけて最も話題のCPUのひとつなので
とくにZen2のRyzen5 2600Xの記事を発売すぐにかけるのはビュー数上昇に一役買っていると思う。
しかし内容が中途半端なので、そろそろPlexチューナーで環境を設定する記事が必要な気がしている。

e-tipsmemo.hatenablog.com
ココらへんからのビュー数順位は、あまり前と変わらない。
最近WSLもUbuntu18にアップデートしたが何の問題もなしに使えている。
機能的にはまだたりない部分があると思う。
個人的には、GPU supportや
nmapなどのコマンド、さらにext4のマウントとかが使えるようになれば言葉では言い表せないほど便利だと思う。

C++ Rest SDKでtwitter②

e-tipsmemo.hatenablog.com
の続き。

requestTokenが成功すると

oauth_token=xxxxxx&oauth_token_secret=yyyyy&hoge=zzzzz

みたいな文字列が返ってくる。
Request TokenとRequest Token Secretとなんとかid(つかわない)

https://api.twitter.com/oauth/authorize?oauth_token={oauth_token}
にアクセスするとPIN codeを貰えるので、それを次のAccess Tokenを得るときに使う。

requestTokenを得るときと同じ様にパラメータを作っていく。
signatureを作るときにSecret Keyを必要とするが、ここは先程得た、””Request Token Secret(oauth_token_secret)””を使う。


あとは同じ様に ヘッダーに入れてhttprequestを投げるだけ。


成功すれば、URI_queryのような形をしたものが返ってきて、失敗したらAuthentication Failedみたいな文字列を含んだJsonが返ってくる。
例外処理とかめんどくさくなったので、基本成功したと仮定して、
oauth_tokenはaccess token
oauth_token_secretはaccess token secret
ついでにuser idとscreen nameをパースする。

それらのパースに失敗したら認証失敗したことにしている。

ここで得られた、access tokenと、access token secretを保存しておけば次からはこれをつかってツイートなどできるので
毎回の認証操作は不要になる。
なのでこれらは厳密に保管されなければならない。

Twitter API ポケットリファレンス (POCKET REFERENCE)

Twitter API ポケットリファレンス (POCKET REFERENCE)

C++ Rest SDKでtwitter①

TwitterつかうアプリケーションでC++ Rest SDKを利用した。
C++ Rest SDKはexperimentalだがoauth1 oauth2の実装もしてあったが使い方がよくわからなかったので
httprequestを直接つかった。

Twitter認証のステップをメモしておく。

最初にrequestTokenを得る。

CONSUMER_KEYはTwitterのアプリを登録したときにもらうやつで。
ATS(ACCESS_TOKEN_SECRET)は最後にもらうやつなので、この時点では空文字
これらのパラメータはkeyでソートされている必要がある。

署名

C++ REST SDKuri_builderはfalseを引き数に取らないと、appendしたときに勝手に要素をuri_encodeしてくれてしまうので
何回もやると%が%25になる関係で %252525..とかになってTwitterからAuthentication Errorが帰ってきたりする。

署名にはHMAC-SHA1が必要なので以前書いたこのライブラリを利用している。
e-tipsmemo.hatenablog.com

このライブラリはstd::stringしか受け付けないので、windowsUnicodeを設定して開発しているならば変換する必要あがあった。
e-tipsmemo.hatenablog.com


パラメータを利用してAuth文字列を得る。


Authenticationの文字列は "=" と ","でつなげるらしくこれはライブラリにはなかったので素朴に書いた


ライブラリのhttpclientを利用して、POSTで投げる。

responseの文字列は成功すればurl_queryの形で帰ってきて失敗すると、jsonで返ってくるという様なので
取りあえず url_queryだとしてパースして
パースに失敗したらREQUEST_TOKENの値がおそらく空なのでそれで判定するという雑な感じでとりあえず実装した。

Visual Studio 2017 boost xml serialization

Nuget パッケージマネージャーでboostと検索して
プロジェクトのプラットフォームツールセットのバージョンにあったBoostをインストールする

f:id:katakanan:20180630112732p:plain
今回はv140を入れた。

準備

シリアライズしたいクラスに追加する。

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>

class hoge
{
public:
	int a;
	std::string b;

private:
	friend class boost::serialization::access;
	template <class Archive>
	void serialize(Archive& archive, unsigned int version) 
	{
		archive& boost::serialization::make_nvp("a", a);
		archive& boost::serialization::make_nvp("b", b);
	}
};

メンバに自作の別のクラスがある場合は、そのクラスにも似たようにserialize関数を実装すると
再帰的にシリアライズされてくれる。

STLのクラスには自分で実装できないので
~~~.hppをincludeするとできる(例: boost/serialization/string.hpp )

利用

#include <boost/archive/xml_oarchive.hpp>//書き出し
#include <boost/archive/xml_iarchive.hpp>//読み込み

書き出し

hoge h;
//hに値をセットする
std::ofstream ofs(TEXT("test.xml"), std::ios::trunc);
{
	boost::archive::xml_oarchive oarchive(ofs);
	oarchive << boost::serialization::make_nvp("Root", h);
} //ファイルを閉じる前にスコープを区切る
ofs.close();

スコープを切らないと、多分oarchiveのデストラクタが呼ばれなくて(?)、xmlタグが正しく閉じられない。
間違った形のxmlをiarchiveで読もうとすると、
input stream errorでプログラムが止まる。

読み込み

std::ifstream ifs(TEXT("test.xml"));
if (ifs.fail())
{
	return false;
}
hoge h;
{
	boost::archive::xml_iarchive iarchive(ifs);
	iarchive >> boost::serialization::make_nvp("Root", h);
}
//hが読めているはず

Visual Studio 2017 C++ Rest SDK static library build

Visual Studio 2017でcpprestsdkの静的リンクライブラリを作成したときにでてきたエラーの解決方法(2018/06/19)

Cannot fimd Build/Release.Tests.settings

github.com
からリポジトリをクローンするのだが、

WSLからgitコマンドを利用したところ、一部のファイルがうまく引っ張ってこれなくて、
Visual Studioでプロジェクトファイルが開けなかった。

解決策

zipでダウンロードした。
f:id:katakanan:20180619234850p:plain

Can't find v140 in Visual Studio 2017

Nugetからcpprestsdkを利用するときも書いたが、
build set が v140でないとコンパイルが通らない。

CL.exe not found

普通はvcvarsall.batがいつの時点でかで実行されてパスが通っているはずなのだが、
通っていない。

解決策

(install dir) : ~~ \2017\Community\VC\Tools\MSVC\14.14.26428\bin\Hostx86\x86
環境変数のPathに追加する。

Can not open include file: 'vcruntime.h': No such file or directory

cpprestsdk.sinはVisual Studio 2015を想定しているから見つからないのだろうか。。。

解決策

cpprestsdk.static をクリックしてプロパティから
VC++ディレクトリの
インクルードディレクトリに
D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\include
などを
追加する。

これでビルド通った。

C++のコンパクトなハッシュライブラリ

HMAC-SHA1を計算したかった。
win32にはcrypt32とかあるけどよくわからなかったので

github.com

便利

#include "../sha1.h"
#include "../hmac.h"

#include <string>
#include <vector>
#include <iostream>

int main()
{
    std::string input= "what do ya want for nothing?";
    std::string key = "Jefe";
    std::string hash = hmac<SHA1>(&input[0], input.size(), &key[0], key.size());
    std::cout << hash << std::endl;
    return 0;
}

f:id:katakanan:20180616111719p:plain

Test Cases for HMAC-MD5 and HMAC-SHA-1

ただし出力が16進数のstringなので、一旦char arrayなどにして解釈し直さないと、間違えることがある。

バイト列でほしいなら

std::string hash = hmac<SHA1>(&input[0], input.size(), &key[0], key.size());
std::vector<unsigned char> v(hash.length() / 2, 0);

for (size_t i = 0; i < hash.length() / 2; i++)
{
	std::string b = hash.substr(i * 2, 2);
	v[i] = std::stoi(b, NULL, 16);
}

こんな感じにする必要がある。