2020/03/04
デッドロックする可能性があったので一部修正しました。
2020/03/11
WordPressの記事一覧取得が10記事までしか取得できなかったので、すべての記事を取得するように修正しました。WPService.cs
#シリーズ
Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #1
Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #2
Qiitaに投稿した記事のリンクを楽にWordPressに送りたい #4
#環境
IDE:VisualStudio2019
アプリケーション:コンソールアプリ
フレームワーク:.NET Core 3.1
#Qiitaタグを連携する
前回の続きです。
前回、記事の追加/更新は実現できましたが、タグが反映できていなかったので、連携できるようチャレンジしてみます。
tagsは名称ではなく、タグのidを指定する必要があるため、Qiita側とWordPress側で名前が同じもののidを求めて設定する必要があります。
また、同じものがない場合は新規追加して発行されたidを用います。
その前に
前回、記事の作成順がばらばらだったのですが、リクエスト時のJSONのdate
にQiitaの記事作成日時を設定することでうまくいきました。
JSON作成部分
// リクエスト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ページ目の10010件が取得される
すべてのページのタグを取得したいので、再起処理を行う
※2020/03/11 GetGetArticleListも修正してます
WPService.cs
/// <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作成部分
// リクエスト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 追加メソッド
/// <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メソッド
/// <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;
}
}
#動作確認
わかりやすいようにすべて削除しておきます。
#サンプル全文
以下GitHubから取得できます。
TestProject
次回は本アプリをWebサービスに置き換えたいと思います。