【#はてなAPI認証】【#不完全なコード】このコードは機能しません.

2024.07.03

Logging

おはようございます.久々にAPI認証で躓いています.この頃は躓いたことがなかったのですがはてなAPI認証で躓いております.エラー内容があまりにもアバウト過ぎて何処の項目でエラーになっているのかがわからない感じです.分かった方はコメント欄にコメント頂けたらと思っています.宜しくお願い致します.

oauthSignatureを作っているところでコケているぽっいと思っているのですが、それが正しいのかどうかも定かではないです.近日中にcurlから参考にしているような方法に変えてみようと思っています.

参考にしたサイトはQiitaの質問に記載していますので良かったら覗いてみてください.

<?php
ini_set('display_errors', 1);
require '../config/config.php';

class hatena
{
    public $oauthCallback = OAUTH_CALLBACK;
    public $oauthConsumerKey = OAUTH_CONSUMER_KEY;
    public $oauthConsumeSecret = OAUTH_CONSUMER_SECRET;
    public $oauthNonce = '';
    public $oauthSignature = null;
    public $oauthSignatureMethod = "HMAC-SHA1";
    public $oauthTimestamp = '';
    public $oauthVersion = "1.0";
    public $contentType = 'application/x-www-form-urlencoded';
    public $oauthParameters = [];

    public function oauthInitiate()
    {

        $url = 'https://www.hatena.com/oauth/initiate';
        $this->oauthNonce = uniqid();
        $this->oauthTimestamp = time();

        $this->oauthParameters = [
            'oauth_consumer_key' => rawurlencode($this->oauthConsumerKey),
            'oauth_nonce' => rawurlencode($this->oauthNonce),
            'oauth_signature_method' => rawurlencode($this->oauthSignatureMethod),
            'oauth_timestamp' => rawurlencode($this->oauthTimestamp),
        ];


        $params = [
            'scope' => 'read_public,write_public,read_private,write_private'
        ];

        $this->getSignature($url, 'POST', $params);
        $this->oauthParameters['oauth_signature'] = rawurlencode($this->oauthSignature);

        $ch = curl_init($url);

        $headers = [ //'.$this->oauthParameters['realm'].'
            'Authorization: OAuth realm="",oauth_callback="' .  rawurlencode($this->oauthCallback) . '",oauth_consumer_key="' . $this->oauthParameters['oauth_consumer_key'] . '",oauth_nonce="' . $this->oauthParameters['oauth_nonce'] . '",oauth_signature="' . $this->oauthParameters['oauth_signature'] . '",oauth_signature_method="' . $this->oauthParameters['oauth_signature_method'] . '",oauth_timestamp="' . $this->oauthParameters['oauth_timestamp'] . '",oauth_version="1.0"',
            'Content-Type: ' . $this->contentType,
            'Content-Length: ' . (string)strlen($this->contentType)
        ];


        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        $response = curl_exec($ch);
        if (curl_error($ch)) {
            echo 'Curl error: ' . curl_error($ch);
        }
        parse_str($response, $response_params);
        var_dump($response_params);
        curl_close($ch);

        return $this;
    }

    public function getSignature($url, $method = 'POST', $params = [], $oauthTokenSecret = '')
    {

        foreach($params as $key=>$value){
            $params[$key] = rawurlencode($value);
        }
        $hasBase = http_build_query($this->oauthsort(array_merge($this->oauthParameters, $params)), '', '&', PHP_QUERY_RFC3986);

        $signingKey = implode('&', [rawurlencode($this->oauthConsumeSecret), rawurlencode($oauthTokenSecret)]);
        $baseString = implode('&', [
            rawurlencode($method),
            rawurlencode($url),
            $hasBase,
        ]);

        $signature = hash_hmac('sha1', $baseString, $signingKey, true);
        $signature = base64_encode($signature);
        $this->oauthSignature = $signature;

        return $this;
    }
    //OAuth式 パラメータのソート関数
    public function oauthsort($a)
    {
        $b = array_map(null, array_keys($a), $a);
        usort($b, ['hatena', 'oauthcmp']);
        $c = array();
        foreach ($b as $v) {
            $c[$v[0]] = $v[1];
        }

        return $c;
    }
    public function oauthcmp($a, $b)
    {
        return strcmp($a[0], $b[0])
            ? strcmp(rawurlencode($a[0]), rawurlencode($b[0]))
            : strcmp(rawurlencode($a[1]), rawurlencode($b[1]));
    }
}

(new hatena)->oauthInitiate();

こちらでも解決策を模索してみます.解決出来れば追記したいと思っています.

追記::解決出来ました.

明日へ続く.

著者名  @taoka_toshiaki

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

application, Authorization, Content-Length, contentType, curl, foreach, getSignature, implode, oauthConsumerKey, oauthConsumeSecret, oauthParameters, oauthSignature, oauthSignatureMethod, oauthsort, oauthTimestamp, Qitta, rawurlencode, string, strlen, uniqid,

PHP言語の素で自分もやってみた🙆

2024.06.16

Logging

おはようございます、素のPHP言語でストリーミングダウンロードしてみました.仕事でつい最近、そのような事をLaravelで行ったわけですけど、素のPHPではどんな感じであろうかと思ったのと株式会社Oさんのブログでもストリーミングダウンロードでメモリ不足解消という記事を見つけたので自分の知見で書いてみました.

<?php

class streamDownload
{
    public $flg = false;
    public $fileName = '';
    public $to_encoding = 'sjis';
    public $from_encoding = 'UTF-8';

    public function __construct($fileName,$to_encoding = 'sjis',$from_encoding = 'UTF-8')
    {
        $this->fileName = $fileName;
        return $this;
    }

    public function checkSplFileInfo()
    {
        if((new SplFileInfo($this->fileName))->getExtension() === 'csv'){
            $this->flg = true;
        }
        return $this;
    }

    public function download($data)
    {
        if(!$this->flg){
            return $this->flg;
        }

        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.$this->fileName);        
        $stream = fopen('php://output', 'w');
            foreach ($data as $row) {
                $row = mb_convert_encoding($row,$this->to_encoding,$this->from_encoding);
                fputcsv($stream, $row);
            }
        fclose($stream);
        exit;
    }
}

$data = [
    ['テスト1', '高知太郎', 'abc@example.com'],
    ['テスト2', '高知花子', 'def@example.com'],
    ['テスト3', '高知喜多郎', 'dev@example.com'],
];

(new streamDownload('test.csv'))->checkSplFileInfo()->download($data);

このコードはCSVファイルをエクセルで開くことを想定して記載しています.要のデータ処理はあのような配列で渡せば何万件もの処理でも基本落ちません.

なお要のデータ処理はご自身で考える必要があります、あくまでも雛形です.

明日へ続く.

著者名  @taoka_toshiaki

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

$flg, abc@example.com, application, attachment, construct, Content-Disposition, def@example.com, download, exit, fclose, filename, fopen, foreach, getExtension, header, Laravel, octet-stream, ストリーミングダウンロード,

Photo by RENATO CONTI on Pexels.com

TwitterとMastodonに同時配信するツールを作成

2023.07.08

Logging

おはようございます。先日、Twitter民がAPI制限で表示がされない問題が起きていた時に、TwitterとMastodonに同時配信するツールを作っていました。普通につぶやくのは前にコードを作っていましたので、それを流用して簡単に出来るなぁなどと思いながら作っていたら画像も添付した状態でつぶやきたいという欲が出てきて沼にハマりました。

Twitterの方は画像添付のつぶやきも簡単にできたものの、Mastodonで沼にハマりました。PHPにはcurlのメソッドがあります、これを使用してAPIに指示を出す感じです。ドキュメントにはヘッダーとともに必須項目を送信すればトゥート(つぶやける)できるよと記載されていたのだけど、実際はユーザーエージェントの値も送信しないと上手く動作しない仕様になっていました。

これはちょっと酷くない?と思いながら数時間悩み、その後、パラメーターの文字化けするという問題に沼にハマりここで数分悩んでいました。結局、全て自己解決したのですが調べても生成AIを頼っても答えが出ない場合は、今までの自分の知識や経験がある方が優位だなって感じました。

トイウコトデ、Qiitaでも掲載したのですがこちらでも解決策を記載します。

<?php
class Mastodon
{
    const host = "mstdn.jp";
    const endpoint1  = "/api/v1/statuses";
    const endpoint2  = "/api/v1/media";

    public function toot($text){
        $data = array('file' => new CURLFile("/var/www/html/t_m/image.png", 'image/png', "image.png"));
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "https://" . self::host . self::endpoint2);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['User-Agent: ' . $_SERVER['HTTP_USER_AGENT'], 'Content-Type: multipart/form-data', 'Authorization: Bearer ' . MSTDN_ACCESSTOKEN]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        $response =   json_decode(@curl_exec($ch));
        curl_close($ch);
        if (isset($response->id)) {
            $postdata = [
                "visibility" => "public",
                "media_ids" => [$response->id],
                "status" => strip_tags($text),
            ];
            $data = json_encode($postdata);
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, "https://" . self::host . self::endpoint1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            curl_setopt($ch, CURLOPT_HTTPHEADER, ['User-Agent: ' . $_SERVER['HTTP_USER_AGENT'], 'Content-Type: application/json', 'Authorization: Bearer ' . MSTDN_ACCESSTOKEN]);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            $response =  @curl_exec($ch);
            curl_close($ch);
        }
    }
}

著者名  @taoka_toshiaki

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

'User-Agent', API, application, array, Authorization, Bearer, Content-type, curl, false, isset, json_decode, mastodon, multipart, qiita, quot, Twitter, VERIFYHOST, トイウコトデ, トゥート, ユーザーエージェント,

Photo by Igor Haritanovich on Pexels.com

ワードプレスの自動タグ生成するプラグイン再開発。 #wp #tag

2022.12.12

Logging

おはようございます、今年もあと半分とちょっとですね、月曜日のたわわ☕。

さて、今日はワードプレスの自動タグ生成するプラグイン再開発しましたってお話です、この自動タグを生成するツールは以前、作っていたのですがYahoo!APIのバージョンアップに伴い使用出来なくなっていました。その為、プラグインを更新しV2対応をこの度、行ったって話です。もともと日本語記事のタグ自動生成するものは存在していたのですが、それがエラーで使用出来なくなり自分で開発したのが今に至っています。

プラグインをダウンロードして使いたい方は、zipファイルを解凍し解凍したフォルダをサーバーのプラグイン置き場にアップロードすることにより使用出来るようになります。尚、前手順としてYahoo!APIのアプリケーションIDの取得を行う必要があります。

プラグインをダウンロードしたくないという方のためにソースコードを一部貼っときます。

        if (isset($appid)) {
            $endpoint = "https://jlp.yahooapis.jp/KeyphraseService/V2/extract";
            $headers = [
                "Content-Type: application/json",
                "User-Agent: Yahoo AppID: ".$appid,
            ]; 
            $param = [
                "id"=> time(),
                "jsonrpc" => "2.0",
                "method" => "jlp.keyphraseservice.extract",
                "params" => [
                    "q"=>preg_replace("/https?:([a-zA-Z0-9|\/|_|\-|%|@|\*|\.|\?|&|=]){0,}/m","",$content)
                    ]
                ];

                $curl=curl_init($endpoint);
                curl_setopt($curl,CURLOPT_POST, TRUE);
                curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
                curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($param));
                curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, FALSE);
                curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, FALSE);
                curl_setopt($curl,CURLOPT_RETURNTRANSFER, TRUE);
                
                $response =  json_decode(curl_exec($curl));


            if (isset($response->result->phrases)) {
                foreach ($response->result->phrases as $keys=>$word) {
                    if ($word->text) {
                        $tags[] = $word->text;
                    }
                    if (is_array($tags)) {
                        wp_set_post_tags($post_id, implode(",", array_unique($tags)), false);
                    }
                }
            }
        }

著者名  @taoka_toshiaki

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

application, false, foreach, gt, headers, implode, isset, jlp, json_decode, json_encode, keys, PARAM, phrases, quot, quot;User-Agent, response, result, Text, true, VERIFYHOST,

goo-labのひらがな化API雛形を作りました。

2021.05.17

Logging

goo-labひらがな化API雛形を作りましたので、お裾分けです。YOUTUBEで解説している事を抜粋して記載します、まずAPIとはアプリケーションプログラミングインターフェイスの略です。APIを簡単に解説するとAというデータを送るとAのデータを処理して何らかの結果を返却してくれるサービスを言います。

APIとは?|仕組みやどんなAPIあるのかなど、図解を使って3分でわかりやすく解説します

今回のひらがな化APIは漢字の文字をひらがな(カタカナ)に変換して返却してくれるサービスです。自分が作った部分はひらがな化APIのサーバにデータを送信して返却データをキャッチする部分になります。APIというのはどんなAPIも同じようなものですので、一度、理屈を分かってしまうと簡単なものです。

因みにディファインの部分を自分のAPIに変更してお使いください、尚、コマンドラインから実行するように設計しています。

<?php
define("APIKEY","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

class Hieagana{
	public function main($str="漢字が混ざっている文章"){
		if(!$str){return false;}
		$headers = array(
			"Content-Type: application/x-www-form-urlencoded",
		);
		// app_id(必須項目)	アプリケーションID
		// request_id	リクエストID
		// 省略時は"labs.goo.ne.jp[タブ文字]リクエスト受付時刻[タブ文字]連番"となります。
		// sentence(必須項目)	解析対象テキスト
		// output_type (必須項目)	出力種別
		// hiragana(ひらがな化)、katakana(カタカナ化)のどちらかを指定してください。
		$params = [
			"app_id"=>APIKEY,
			"sentence"=>$str,
			"output_type"=>"hiragana"
		];

		$curl = curl_init("https://labs.goo.ne.jp/api/hiragana");
		curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
		curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);  
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);  
		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
		
		$output =  (object)json_decode(curl_exec($curl));
		curl_close($curl);

		var_dump($output);

	}
}

if($argv[0]){
	(new Hieagana)->main($argv[1]);
}

著者名  @taoka_toshiaki

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

$params, APIKEY, application, argv, array, decode, false, goo.ne.jp, headers, hiragana, katakana, labs, lt, object, php define, quot, VERIFYHOST, youtube, アプリケーションプログラミングインターフェイス, コマンドライン,