はじめに
ここまで来たら、mixi APIも調べてみようと思いましたが、意外と大変でした。何度も心がくじけそうになりました。
手順
1.ディベロッパー登録
まず大変だったのがクレジットカードの登録。クレジットカードの登録をしないと先に進めません。バーチャルカードは使用できませんでした。さらに、一日一回しか登録できないので、失敗すると次の日まで待たないといけないため、心がくじけそうになります。
2.アプリケーションの登録
アプリケーションを登録する際には、リダイレクトURLも記入してください。特にリダイレクト用のURLを用意しなくても、例えば「http://www.mztm.jp/redirect
」のようなURLで大丈夫です。
consumer keyとconsumer secretを環境変数にでも入れておきましょう。
MIXI_CONSUMER_KEY=aaaaaaaa
MIXI_CONSUMER_SECRET=bbbbbbbbbb
3.server stateの取得
ここからは時間との勝負です。
ここからは時間との勝負です。まずはServer Stateを取得しましょう。Server Stateとは...あー、このコードの有効時間は30分です。のんきに調べていたらコードが無効になってしまいますので急ぎましょう。
private getServerState = async (): Promise<any> => {
const param = new URLSearchParams({
grant_type: "server_state",
client_id: process.env.MIXI_CONSUMER_KEY,
});
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
try {
const response = await axios.post("https://secure.mixi-platform.com/2/token", param, {headers})
console.log(response.data.server_state)
} catch (e) {
console.log("error")
}
}
ここで出力されるのがServer Stateです。仮にccccccc
と出力されたとしましょう。
4.OAuth Codeの取得
以下のようにURLを生成して、ブラウザに入力します。
const param = "client_id=" + process.env.MIXI_CONSUMER_KEY +
"&response_type=code" +
"&scope=w_voice" +
"&display=pc" +
"&server_state=ccccccc"
const url = "https://mixi.jp/connect_authorize.pl?" + param;
console.log(url)
許可をすると、上のリダイレクトURLにページ遷移します。
そのURLのアドレスからcode
の変数を取得します。
例:http://www.mztm.jp/redirect?code=ddddddddd
このdddddddddがOAuth Codeです。
OAuth Codeとは・・・
あー!OAuth Codeの有効時間は3分です。
ささ、急ぎましょう。
5.Tokenの取得
Server StateとOAuth Codeを使って、Tokenを取得します。
public getToken = async (): Promise<any> => {
const server_state:string = "ccccccc";
const code:string = "ddddddddd";
const param = new URLSearchParams({
grant_type: "authorization_code",
client_id: process.env.MIXI_CONSUMER_KEY,
client_secret: process.env.MIXI_CONSUMER_SECRET,
code: code,
server_state: server_state
});
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
try {
const response = await axios.post("https://secure.mixi-platform.com/2/token", param, {headers})
console.log(response.data);
} catch (e) {
console.log("error")
}
}
以上を実行すると、出力されるはずです。
refresh_token: 'eeeeeeee',
expires_in: 900,
access_token: 'ffffffffffff',
token_type: 'Bearer',
scope: 'w_voice'
このaccess_tokenは900秒です。
ただ、今回は900秒を超えてしまっても、refresh_tokenを使って再度access_tokenを取得することができます。
refresh_tokenを環境変数に入れておきます。
MIXI_REFRESH_TOKEN=eeeeeeee
6.投稿
下準備はおわりました。
このrefresh tokenを使って投稿ごとにtokenを取得して、メッセージを投稿しましょう。
とりあえず画像付きの関数と画像なしの関数を用意しています。
それぞれ、まずはrefresh tokenを使い、access tokenを取得して、POSTにくっつけて送ります。
private refreshToken = async () => {
const date = {
grant_type: "refresh_token",
client_id: process.env.MIXI_CONSUMER_KEY,
client_secret: process.env.MIXI_CONSUMER_SECRET,
refresh_token: process.env.MIXI_REFRESH_TOKEN
}
const param = new URLSearchParams(date);
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
try {
const response = await axios.post("https://secure.mixi-platform.com/2/token", param, {headers})
return {
data: {
success: true,
access_token: response.data.access_token
}
}
} catch (e) {
console.log("error " + e)
return {
data: {
success: false,
}
}
}
}
/**
* メッセージをMixi APIを使用して送信します
*
* @param {string} message - 送信するメッセージ
* @returns {Promise<any>} - 成功ステータスを含むオブジェクトを返すPromise
* @throws {Error} - 送信プロセス中に失敗した場合、エラーを投げます
*/
public send = async (message: string):Promise<any> => {
const response: any = await this.refreshToken();
if (response.data.success) {
const param = new URLSearchParams({
status: message,
oauth_token: response.data.access_token
});
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
try {
await axios.post("https://api.mixi-platform.com/2/voice/statuses/update", param, {headers})
return {
data:{
success: true
}
}
} catch (e) {
console.log("error send!")
return {
data:{
success: false,
error:{
message:e
}
}
}
}
}
}
/**
* 画像をメッセージと一緒にMixiプラットフォームに送信します
*
* @param {string} message - 画像と一緒に送信するメッセージ
* @param {string} imagePath - 画像ファイルへのパス
* @returns {Promise<any>} - 成功ステータスとオプションのエラーメッセージを含むオブジェクトを返すPromise
* @throws {Error} - 画像の読み取りまたは送信中にエラーが発生した場合、エラーを投げます
*/
public sendEmbedImage = async (message: string, imagePath: string): Promise<any> => {
const response: any = await this.refreshToken();
if (response.data.success) {
let photoData: Buffer;
let contentType: string;
if (imagePath.endsWith('.jpg') || imagePath.endsWith('.jpeg')) {
contentType = 'image/jpeg';
} else if (imagePath.endsWith('.png')) {
contentType = 'image/png';
} else {
console.log("Unsupported image format");
return;
}
try {
const filePath = path.join(__dirname, imagePath);
photoData = await fs.readFile(filePath);
const headers = {
'Content-Type': contentType
};
const url: string = `https://api.mixi-platform.com/2/voice/statuses/update?status=${encodeURIComponent(message)}&oauth_token=${response.data.access_token}`;
await axios.post(url, photoData, {headers});
return {
data:{
success:true
}
}
} catch (e) {
console.log("error " + e);
return {
data:{
success: false,
error:{
message:e
}
}
}
}
}
}
まとめ
あー、疲れました。
もう少しきれいな方法があるかもしれませんが、とりあえず送信ができました。
mixiのドキュメントによると、mixi側が勝手にリフレッシュトークンを使えないことがあるかもしれないとのことです。OAuthコードを再度取得して処理を行う必要があるかもしれません。
完全自動化は難しいかもしれませんね。
しかし、3ヶ月ほど動かしてみたところ、とりあえず動いています。ここまで動けば大丈夫かな。
参考
mixi api 認証認可手順(新方式)
https://developer.mixi.co.jp/connect/mixi_graph_api/api_auth/
Voice API
https://developer.mixi.co.jp/connect/mixi_graph_api/mixi_io_spec_top/voice-api/