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

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

**2020/03/11**
WordPressの記事一覧取得が10記事までしか取得できなかったので、すべての記事を取得するように修正しました。WPService.cs

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

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

#Qiitaタグを連携する
[前回](https://qiita.com/GodPhwng/items/8de81c46a3a01f53d4b5)の続きです。

前回、記事の追加／更新は実現できましたが、タグが反映できていなかったので、連携できるようチャレンジしてみます。
tagsは名称ではなく、タグのidを指定する必要があるため、Qiita側とWordPress側で名前が同じもののidを求めて設定する必要があります。
また、同じものがない場合は新規追加して発行されたidを用います。

**その前に**
前回、記事の作成順がばらばらだったのですが、リクエスト時のJSONの```date```にQiitaの記事作成日時を設定することでうまくいきました。

JSON作成部分

```C#
                // リクエストBody作成
                var json = new
                {
                    // 作成日時
                    date = DateTime.Parse(qiita["created_at"].ToString()).ToString("s"),

                    // 公開範囲
                    status = "publish",

                    // タイトル
                    title = title,

                    // 本文
                    content = $"\n<p>{title}<a href=\"{url}\">{url}</a></p>\n",
                };
```

#設計
①WordPressタグ一覧取得
↓
②Qiita記事をループしながら、対象のタグが①に存在する場合は、そのidを用いて記事を更新／追加する
↓
③対象のタグが①に存在しない場合は、WordPressのタグ追加リクエストを行い、①に追加したタグの情報を追加する

#WordPressタグ一覧取得
API説明
https://ja.wp-api.org/reference/tags/

ネット上で情報を探すと、どうやら全ていっぺんにタグを取得することは不可能とのこと。(PHP側ではやりようがあるとのこと)
上記リンクにあるように　{何}ページ目の{何件}取得するかを指定する必要がある模様
特に指定しなかった場合は、1ページ目の~~100~~10件が取得される

すべてのページのタグを取得したいので、再起処理を行う

**※2020/03/11 GetGetArticleListも修正してます**

WPService.cs

```C#
        /// <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 TAGS = "/wp-json/wp/v2/tags";

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

        /// <summary>
        /// タグ一覧取得
        /// </summary>
        /// <param name="page">ページIndex</param>
        /// <returns>返り値JSON配列</returns>
        public async Task<JArray> GetTagList()
        {
            return await this.GetList(TAGS);
        }

        /// <summary>
        /// 指定された要素すべてを取得
        /// </summary>
        /// <param name="url">要素のURL</param>
        /// <param name="page">ページIndex</param>
        /// <returns>返り値JSON配列</returns>
        private async Task<JArray> GetList(string url, int page = 1)
        {
            // 1ページ単位、100件取得
            var responce = await HpClient.GetAsync($"{TOP_URL}{url}?page={page}&per_page=100");

            // 100件区切りした場合のトータルのページ
            // 例えば201件ある場合、3ページとなる
            var toalPage = responce.Headers.GetValues("X-WP-TotalPages").First();

            var body = await responce.Content.ReadAsStringAsync();
            var tagArray = JArray.Parse(body);

            if (Convert.ToInt32(toalPage) > page)
            {
                // 再起処理 すべてのページの要素を収集
                tagArray.Merge(await this.GetList(url, ++page));
            }

            return tagArray;
        }
```

#JSONにtagsを追加

**JSON作成部分**

```C#
	// リクエストBody作成
	var json = new
	{
	    // 作成日時
	    date = DateTime.Parse(qiita["created_at"].ToString()).ToString("s"),

	    // 公開範囲
	    status = "publish",

	    // タイトル
	    title = title,

	    // 本文
	    content = $"\n<p>{title}<a href=\"{url}\">{url}</a></p>\n",

	    // タグ(インサート処理は非同期で実行し、すべての処理が終わるのを待つ)
	    tags = await Task.WhenAll(qiita["tags"].Select(async q => await this.GetAndAddTagListAsync(wpService, q, tagList)))
	};
```

**タグ取得 OR 追加メソッド**

```C#
        /// <summary>
        /// Qiitaタグと同一のWordPressタグIDを取得
        /// WordPress側に存在しない場合は、新規追加を行う
        /// </summary>
        /// <param name="wpService">WPService</param>
        /// <param name="tag">Qiitaタグ</param>
        /// <param name="wpTagList">WordPressタグ一覧</param>
        /// <returns>Qiitaタグと同一のWordPressタグID</returns>
        private async Task<int> GetAndAddTagListAsync(WPService wpService, JToken tag, JArray wpTagList)
        {
            var findTag = wpTagList.FirstOrDefault(wpt => wpt["name"].ToString() == tag["name"].ToString());
            if (findTag == null)
            {
                // Tag追加リクエスト
                var id = await wpService.InsertTag(new { name = tag["name"].ToString() });

                // リストに追加
                wpTagList.Add(JToken.FromObject(new { id = id ?? -1, name = tag["name"].ToString() }));

                return id ?? -1;
            }
            else
            {
                return findTag["id"].Value<int>();
            }
        }
```
**WPService.InsertTagメソッド**

```C#
        /// <summary>
        /// タグ追加
        /// </summary>
        /// <param name="json">タグ情報JSON</param>
        /// <returns>作成したタグのID</returns>
        public async Task<int?> InsertTag(object json)
        {
            var request = this.CreateHttpRequestMessage(HttpMethod.Post, TOP_URL + TAGS);
            request.Content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");

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

            // レスポンスbody
            var resultJson = JObject.Parse(await result.Content.ReadAsStringAsync());

            if (result.StatusCode == HttpStatusCode.Created)
            {
                // 追加したタグのIDを返却
                return resultJson["id"].Value<int>();
            }
            else
            {
                // エラーメッセージ
                Console.WriteLine(resultJson["message"].ToString());

                return null;
            }
        }
```

#動作確認
わかりやすいようにすべて削除しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/49c3b2ac-a3a5-0153-9f8f-fa2d432c2749.png)

タグも空にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/743ca115-714e-22c1-1ec6-ba37ba2dd795.png)

**実行後**
記事一覧
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/bbc77e53-f405-77db-2e70-40504e427eb4.png)

タグ一覧
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/baa163c3-5732-c321-a8b0-53b8ae5789ae.png)

#サンプル全文
以下GitHubから取得できます。
[TestProject](https://github.com/GodPhwng/TestProject)

次回は本アプリをWebサービスに置き換えたいと思います。