Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #2

**2020/03/04**
デッドロックする可能性があったので一部修正しました。

**2020/03/11**
WordPressの記事一覧取得が10記事までしか取得できなかったので、すべての記事を取得するように修正しました。WPService.cs
リンクは[こちら](https://qiita.com/GodPhwng/items/c41facd5fef42fec7f47)

#シリーズ
[Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #1](https://qiita.com/GodPhwng/items/d987e8d5af11fb4b7411)
[Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #3](https://qiita.com/GodPhwng/items/c41facd5fef42fec7f47)
[Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #4](https://qiita.com/GodPhwng/items/875f5fbacec35f038d4a)

#環境
**IDE**：VisualStudio2019
**アプリケーション**：コンソールアプリ
**フレームワーク**：.NET Core 3.1

#アプリケーションパスワードを有効化してAPIをコールしてみたが・・・
[前回](https://qiita.com/GodPhwng/items/d987e8d5af11fb4b7411)の続きになります。

WordPressの環境を借りている方に、アプリケーションパスワードの設定を行ってもらった。
以下サイトを参考に設定してもらった。
[WordPressのRESTAPIでアプリケーションパスワードの認証がとおらないなら](https://blog.saboh.net/wp-rest-api_pass/)


更新をやってみたところ、まだエラーが起きる。401のエラーであり、権限がないとのこと。

以下で追加した名前と発行されるパスワードを「名前:パスワード」の形で設定しているのになぜエラーに・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/85af9d7a-c240-7ceb-3f94-07b74a93225c.png)

#TryAddWithoutValidationが動作していない

以下の戻り値がfalseになっており、Authorizationヘッダーがうまく付与されていなかった。

```C#
content.Headers.TryAddWithoutValidation("Authorization", $"Basic {credentials}");
```

**HttpRequestMessageを使用するらしい**
調べると以下のようにHttpRequestMessageを使用して、ヘッダーに追加するとよいらしい。

```C#
        public async Task<bool> UpdateWPArticle(string id, string json)
        {
            var request = new HttpRequestMessage(HttpMethod.Post, URL_FIRST + string.Format(UPDATE_ARTICLE, id));
            var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("名前:パスワード"));            
            request.Content = new StringContent(json, Encoding.UTF8, "application/json");
            request.Headers.Add("Authorization", $"Basic {credentials}");

            var result = await HpClient.SendAsync(request);

            if (result.StatusCode == HttpStatusCode.OK)
            {
                return true;
            }
            else
            {
                return false;
            }            
        }
```

#HttpRequestMessageを使用してもまだエラーがでる
HttpRequestMessageを使用しても依然エラーとなる。
調べてみるとどうやら

```C#
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("名前:パスワード")); 
```
の「名前:パスワード」は誤りで、「WordPressのログインユーザーID：パスワード」らしい。
しかも、パスワードは「c8cO ABCD UUb9 7DDX Rq22 1shl」のように空白区切りで発行されるが、そのまま使用するらしい。
空白は除去しないで設定することでうまくいった。
めちゃめちゃわかりにくい！！！！！

**例**

```C#
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("user01:c8cO ABCD UUb9 7DDX Rq22 1shl")); 
```

#記事の更新、追加
認証に成功したので、記事の更新／追加の処理を実装し、全体的に修正しました。

**QiitaService**

```C#
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;

namespace TestProject.QiitaToWP
{
    /// <summary>
    /// QiitaAPI呼び出しクラス
    /// </summary>
    public class QiitaService : ServiceBase
    {
        /// <summary>
        /// TOPURL
        /// </summary>
        private const string TOP_URL = "https://qiita.com";

        /// <summary>
        /// 記事一覧取得定義
        /// </summary>
        private const string GET_ARTICLELIST = "/api/v2/users/{0}/items";

        /// <summary>
        /// 記事一覧取得
        /// </summary>
        /// <param name="param">パラメータ群</param>
        /// <returns>返り値JSON配列</returns>
        public override async Task<JArray> GetArticleList(params string[] param)
        {
            var body = await HpClient.GetStringAsync(TOP_URL + string.Format(GET_ARTICLELIST, param[0]));
            return JArray.Parse(body);
        }
    }
}
```

**WPService**

```C#
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace TestProject.QiitaToWP
{
    /// <summary>
    /// WordPress API呼び出しクラス
    /// </summary>
    public class WPService : ServiceBase
    {
        /// <summary>
        /// TOPURL
        /// </summary>
        private const string TOP_URL = "http://kurosu.s1009.xrea.com";

        /// <summary>
        /// 記事取得、投稿時の定義
        /// </summary>
        private const string POSTS = "/wp-json/wp/v2/posts";

        /// <summary>
        /// 記事更新時の定義
        /// </summary>
        private const string UPDATE_POSTS = "/wp-json/wp/v2/posts/{0}";

        /// <summary>
        /// アプリケーションキー(Basic認証に使用するキー)
        /// </summary>
        private readonly string apllicationKey;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="applicationKey">アプリケーションキー(Basic認証に使用するキー)</param>
        public WPService(string applicationKey) : base()
        {
            this.apllicationKey = applicationKey;
        }

        /// <summary>
        /// 記事一覧取得
        /// </summary>
        /// <param name="param">パラメータ群</param>
        /// <returns>返り値JSON配列</returns>
        public override async Task<JArray> GetArticleList(params string[] param)
        {
            var body = await HpClient.GetStringAsync(TOP_URL + POSTS);
            return JArray.Parse(body);
        }

        /// <summary>
        /// 記事更新
        /// </summary>
        /// <param name="id">記事ID</param>
        /// <param name="json">更新情報JSON</param>
        /// <returns>処理の成否</returns>
        public async Task<bool> UpdateWPArticle(string id, object json)
        {
            var request = this.CreateHttpRequestMessage(HttpMethod.Post, TOP_URL + string.Format(UPDATE_POSTS, id));
            request.Content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json"); ;

            // リクエスト
            var result = await HpClient.SendAsync(request);

            if (result.StatusCode == HttpStatusCode.OK)
            {
                return true;
            }
            else
            {
                // エラーメッセージ
                var resultJson = JObject.Parse(await result.Content.ReadAsStringAsync());
                Console.WriteLine(resultJson["message"].ToString());

                return false;
            }
        }

        /// <summary>
        /// 記事追加
        /// </summary>
        /// <param name="json">記事情報JSON</param>
        /// <returns>処理の成否</returns>
        public async Task<bool> InsertWPArticle(object json)
        {
            var request = this.CreateHttpRequestMessage(HttpMethod.Post, TOP_URL + POSTS);
            request.Content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");

            // リクエスト
            var result = await HpClient.SendAsync(request);

            if (result.StatusCode == HttpStatusCode.Created)
            {
                return true;
            }
            else
            {
                // エラーメッセージ
                var resultJson = JObject.Parse(await result.Content.ReadAsStringAsync());
                Console.WriteLine(resultJson["message"].ToString());

                return false;
            }
        }

        /// <summary>
        /// HttpRequestMessage作成
        /// </summary>
        /// <param name="method">Httpメソッド</param>
        /// <param name="url">URL</param>
        /// <returns>HttpRequestMessage</returns>
        private HttpRequestMessage CreateHttpRequestMessage(HttpMethod method, string url)
        {
            var request = new HttpRequestMessage(method, url);

            // Basi認証ヘッダー
            var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(this.apllicationKey));
            request.Headers.Add("Authorization", $"Basic {credentials}");

            return request;
        }
    }
}
```

**Qiita2WP**

```C#
using System.Linq;
using System.Threading.Tasks;

namespace TestProject.QiitaToWP
{
    /// <summary>
    /// QiitaToWordPressクラス
    /// </summary>
    public class Qiita2WP
    {
        /// <summary>
        /// QiitaからWordPressに記事を転送
        /// </summary>
        /// <returns>Task</returns>
        public async Task Qiita2WPArticle()
        {
            // Qiita記事取得
            var qiitaService = new QiitaService();
            var qiitaList = await qiitaService.GetArticleList("GodPhwng");

            // WP記事取得
            var wpService = new WPService("ユーザID:アプリケーションパスワード");
            var wpList = await wpService.GetArticleList();

            foreach (var qiita in qiitaList)
            {
                var url = qiita["url"].ToString();
                var title = qiita["title"].ToString();

                // Qiitaの記事URLが含まれる物を取得
                var matchArticle = wpList.FirstOrDefault(w => w["content"]["rendered"].ToString().Contains(url));

                // リクエストBody作成
                var json = new
                {
                    // 公開範囲
                    status= "publish",

                    // タイトル
                    title = title,

                    // 本文
                    content = $"\n<p>{title}<a href=\"{url}\">{url}</a></p>\n"
                };
                
                if (matchArticle != null)
                {
                    // 更新
                    await wpService.UpdateWPArticle(matchArticle["id"].ToString(), json);               
                }                
                else
                {
                    // 新規追加
                    await wpService.InsertWPArticle(json);
                }
            }
        }
    }
}
```

**メインクラス**

```C#
using System;
using System.Threading.Tasks;

namespace TestProject.QiitaToWP
{
    /// <summary>
    /// メインクラス
    /// </summary>
    public class Program
    {
        /// <summary>
        /// メインエントリ
        /// </summary>
        /// <param name="args">実行時引数</param>
        /// <returns>Task</returns>
        public static async Task Main(string[] args)
        {
            try
            {
                var q2wp = new Qiita2WP();

                // Qiitaの記事をWordPressに反映
                await q2wp.Qiita2WPArticle();

                Console.WriteLine("処理終了");
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
            finally
            {
                Console.Read();
            }
        }
    }
}
```

#動作確認
**実行前**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/9deece56-ca36-434a-737a-2bf1661420a9.png)

**実行後**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/e3c479a0-5986-b2c1-2873-0bc6b36d0a3d.png)
4つほど記事が追加されました。

また、既存の記事は更新されています。

気になるのはQiitaの記事投稿順になっていないことです。
~~WordPress側で記事作成処理が非同期で動いてそうです。~~

#GitHubのソースリンク
[TestProject](https://github.com/GodPhwng/TestProject)

#次回はタグを自動設定
現状ではタグが何も設定されていないので、Qiitaから読み取ったタグを連携してみようとおもいます。
→[次回](https://qiita.com/GodPhwng/items/c41facd5fef42fec7f47)