シリーズ
Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #1
環境
IDE:VisualStudio2019
アプリケーション:コンソールアプリ
フレームワーク:.NET Core 3.1
アプリケーションパスワードを有効化してAPIをコールしてみたが・・・
前回の続きになります。
WordPressの環境を借りている方に、アプリケーションパスワードの設定を行ってもらった。
以下サイトを参考に設定してもらった。
WordPressのRESTAPIでアプリケーションパスワードの認証がとおらないなら
更新をやってみたところ、まだエラーが起きる。401のエラーであり、権限がないとのこと。
以下で追加した名前と発行されるパスワードを「名前:パスワード」の形で設定しているのになぜエラーに・・・
TryAddWithoutValidationが動作していない
以下の戻り値がfalseになっており、Authorizationヘッダーがうまく付与されていなかった。
content.Headers.TryAddWithoutValidation("Authorization",$"Basic {credentials}");
HttpRequestMessageを使用するらしい
調べると以下のようにHttpRequestMessageを使用して、ヘッダーに追加するとよいらしい。
publicasyncTask<bool>UpdateWPArticle(stringid,stringjson){varrequest=newHttpRequestMessage(HttpMethod.Post,URL_FIRST+string.Format(UPDATE_ARTICLE,id));varcredentials=Convert.ToBase64String(Encoding.UTF8.GetBytes("名前:パスワード"));request.Content=newStringContent(json,Encoding.UTF8,"application/json");request.Headers.Add("Authorization",$"Basic {credentials}");varresult=awaitHpClient.SendAsync(request);if(result.StatusCode==HttpStatusCode.OK){returntrue;}else{returnfalse;}}
HttpRequestMessageを使用してもまだエラーがでる
HttpRequestMessageを使用しても依然エラーとなる。
調べてみるとどうやら
varcredentials=Convert.ToBase64String(Encoding.UTF8.GetBytes("名前:パスワード"));
の「名前:パスワード」は誤りで、「WordPressのログインユーザーID:パスワード」らしい。
しかも、パスワードは「c8cO ABCD UUb9 7DDX Rq22 1shl」のように空白区切りで発行されるが、そのまま使用するらしい。
空白は除去しないで設定することでうまくいった。
めちゃめちゃわかりにくい!!!!!
例
varcredentials=Convert.ToBase64String(Encoding.UTF8.GetBytes("user01:c8cO ABCD UUb9 7DDX Rq22 1shl"));
記事の更新、追加
認証に成功したので、記事の更新/追加の処理を実装し、全体的に修正しました。
QiitaService
usingNewtonsoft.Json.Linq;usingSystem.Threading.Tasks;namespaceTestProject.QiitaToWP{/// <summary>/// QiitaAPI呼び出しクラス/// </summary>publicclassQiitaService:ServiceBase{/// <summary>/// TOPURL/// </summary>privateconststringTOP_URL="https://qiita.com";/// <summary>/// 記事一覧取得定義/// </summary>privateconststringGET_ARTICLELIST="/api/v2/users/{0}/items";/// <summary>/// 記事一覧取得/// </summary>/// <param name="param">パラメータ群</param>/// <returns>返り値JSON配列</returns>publicoverrideasyncTask<JArray>GetArticleList(paramsstring[]param){varbody=awaitHpClient.GetStringAsync(TOP_URL+string.Format(GET_ARTICLELIST,param[0]));returnJArray.Parse(body);}}}
WPService
usingNewtonsoft.Json;usingNewtonsoft.Json.Linq;usingSystem;usingSystem.Net;usingSystem.Net.Http;usingSystem.Text;usingSystem.Threading.Tasks;namespaceTestProject.QiitaToWP{/// <summary>/// WordPress API呼び出しクラス/// </summary>publicclassWPService:ServiceBase{/// <summary>/// TOPURL/// </summary>privateconststringTOP_URL="http://kurosu.s1009.xrea.com";/// <summary>/// 記事取得、投稿時の定義/// </summary>privateconststringPOSTS="/wp-json/wp/v2/posts";/// <summary>/// 記事更新時の定義/// </summary>privateconststringUPDATE_POSTS="/wp-json/wp/v2/posts/{0}";/// <summary>/// アプリケーションキー(Basic認証に使用するキー)/// </summary>privatereadonlystringapllicationKey;/// <summary>/// コンストラクタ/// </summary>/// <param name="applicationKey">アプリケーションキー(Basic認証に使用するキー)</param>publicWPService(stringapplicationKey):base(){this.apllicationKey=applicationKey;}/// <summary>/// 記事一覧取得/// </summary>/// <param name="param">パラメータ群</param>/// <returns>返り値JSON配列</returns>publicoverrideasyncTask<JArray>GetArticleList(paramsstring[]param){varbody=awaitHpClient.GetStringAsync(TOP_URL+POSTS);returnJArray.Parse(body);}/// <summary>/// 記事更新/// </summary>/// <param name="id">記事ID</param>/// <param name="json">更新情報JSON</param>/// <returns>処理の成否</returns>publicasyncTask<bool>UpdateWPArticle(stringid,objectjson){varrequest=this.CreateHttpRequestMessage(HttpMethod.Post,TOP_URL+string.Format(UPDATE_POSTS,id));request.Content=newStringContent(JsonConvert.SerializeObject(json),Encoding.UTF8,"application/json");;// リクエストvarresult=awaitHpClient.SendAsync(request);if(result.StatusCode==HttpStatusCode.OK){returntrue;}else{// エラーメッセージvarresultJson=JObject.Parse(result.Content.ReadAsStringAsync().Result);Console.WriteLine(resultJson["message"].ToString());returnfalse;}}/// <summary>/// 記事追加/// </summary>/// <param name="json">記事情報JSON</param>/// <returns>処理の成否</returns>publicasyncTask<bool>InsertWPArticle(objectjson){varrequest=this.CreateHttpRequestMessage(HttpMethod.Post,TOP_URL+POSTS);request.Content=newStringContent(JsonConvert.SerializeObject(json),Encoding.UTF8,"application/json");// リクエストvarresult=awaitHpClient.SendAsync(request);if(result.StatusCode==HttpStatusCode.Created){returntrue;}else{// エラーメッセージvarresultJson=JObject.Parse(result.Content.ReadAsStringAsync().Result);Console.WriteLine(resultJson["message"].ToString());returnfalse;}}/// <summary>/// HttpRequestMessage作成/// </summary>/// <param name="method">Httpメソッド</param>/// <param name="url">URL</param>/// <returns>HttpRequestMessage</returns>privateHttpRequestMessageCreateHttpRequestMessage(HttpMethodmethod,stringurl){varrequest=newHttpRequestMessage(method,url);// Basi認証ヘッダーvarcredentials=Convert.ToBase64String(Encoding.UTF8.GetBytes(this.apllicationKey));request.Headers.Add("Authorization",$"Basic {credentials}");returnrequest;}}}
Qiita2WP
usingSystem.Linq;usingSystem.Threading.Tasks;namespaceTestProject.QiitaToWP{/// <summary>/// QiitaToWordPressクラス/// </summary>publicclassQiita2WP{/// <summary>/// QiitaからWordPressに記事を転送/// </summary>/// <returns>Task</returns>publicasyncTaskQiita2WPArticle(){// Qiita記事取得varqiitaService=newQiitaService();varqiitaList=awaitqiitaService.GetArticleList("GodPhwng");// WP記事取得varwpService=newWPService("ユーザID:アプリケーションパスワード");varwpList=awaitwpService.GetArticleList();foreach(varqiitainqiitaList){varurl=qiita["url"].ToString();vartitle=qiita["title"].ToString();// Qiitaの記事URLが含まれる物を取得varmatchArticle=wpList.FirstOrDefault(w=>w["content"]["rendered"].ToString().Contains(url));// リクエストBody作成varjson=new{// 公開範囲status="publish",// タイトルtitle=title,// 本文content=$"\n<p>{title}<a href=\"{url}\">{url}</a></p>\n"};if(matchArticle!=null){// 更新awaitwpService.UpdateWPArticle(matchArticle["id"].ToString(),json);}else{// 新規追加awaitwpService.InsertWPArticle(json);}}}}}
メインクラス
usingSystem;usingSystem.Threading.Tasks;namespaceTestProject.QiitaToWP{/// <summary>/// メインクラス/// </summary>publicclassProgram{/// <summary>/// メインエントリ/// </summary>/// <param name="args">実行時引数</param>/// <returns>Task</returns>publicstaticasyncTaskMain(string[]args){try{varq2wp=newQiita2WP();// Qiitaの記事をWordPressに反映awaitq2wp.Qiita2WPArticle();Console.WriteLine("処理終了");}catch(Exceptionerr){Console.WriteLine(err.Message);}finally{Console.Read();}}}}
動作確認
また、既存の記事は更新されています。
気になるのはQiitaの記事投稿順になっていないことです。
WordPress側で記事作成処理が非同期で動いてそうです。
GitHubのソースリンク
次回はタグを自動設定
現状ではタグが何も設定されていないので、Qiitaから読み取ったタグを連携してみようとおもいます。