private async Task <IEnumerable <long> > UploadMediaAsync(KintoneWebhookRequest kintoneRequest, Tokens tokens) { try { var list = new List <long>(); foreach (var attachment in kintoneRequest.Record.添付ファイル.Value) { var content = $"Name={attachment.Name},FileKey={attachment.FileKey},Size={attachment.Size},ContentType={attachment.ContentType}"; _logger.LogInformation(content); var url = $"{_kintoneSettings.Value.ServiceUrl}k/v1/file.json?fileKey={attachment.FileKey}"; using var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Add("X-Cybozu-API-Token", _kintoneSettings.Value.ApiToken); var response = await client.SendAsync(request); var stream = await response.Content.ReadAsStreamAsync(); var mediaUploadResult = await tokens.Media.UploadAsync(stream); list.Add(mediaUploadResult.MediaId); } return(list); } catch (Exception ex) { _logger.LogError($"{ex.Message}"); _logger.LogError($"{ex.StackTrace}"); throw; } }
public async Task <IActionResult> Post([FromBody] KintoneWebhookRequest kintoneRequest) { var requestContent = $"Url={kintoneRequest.Url},App.Id={kintoneRequest.App.Id}" + $",承認ステータス={kintoneRequest.Record.承認ステータス.Value}" + $",Type={kintoneRequest.Type},Twitter投稿済={string.Join(",", kintoneRequest.Record.Twitter投稿済.Value)}" + $",Twitter投稿メッセージ={kintoneRequest.Record.Twitter投稿メッセージ.Value}" + $",投稿内容={kintoneRequest.Record.投稿内容.Value}"; _logger.LogInformation(requestContent); //Webhookで来たJsonのチェック。指定したサービス・アプリ・イベント以外はUnAuthorizedで返す if (!kintoneRequest.Url.StartsWith(_kintoneSettings.Value.ServiceUrl)) { return(Unauthorized()); } if (kintoneRequest.App.Id != _kintoneSettings.Value.AppId) { return(Unauthorized()); } if (kintoneRequest.Type != "UPDATE_RECORD") { return(Unauthorized()); } //承認以外は何もしない if (kintoneRequest.Record.承認ステータス.Value != "承認") { return(Ok()); } //投稿済は何もしない if (kintoneRequest.Record.Twitter投稿済.Value.Contains("投稿済")) { return(Ok()); } //Twitter投稿メッセージが何か入っていたら、何もしない(エラー後の更新でループすることの回避) if (!string.IsNullOrEmpty(kintoneRequest.Record.Twitter投稿メッセージ.Value)) { return(Ok()); } //Twitterの認証情報セット var apiKey = _twitterSettings.Value.ApiKey; var apiSecret = _twitterSettings.Value.ApiSecret; var accessToken = _twitterSettings.Value.AccessToken; var accessTokenSecret = _twitterSettings.Value.AccessTokenSecret; var tokens = CoreTweet.Tokens.Create(apiKey, apiSecret, accessToken, accessTokenSecret); //Twitterへ投稿 try { //メディアを先にアップロード var mediaIdList = await UploadMediaAsync(kintoneRequest, tokens); //メディア付きでTweet var mediaIds = mediaIdList.Any() ? mediaIdList.ToArray() : null; var tweetResponse = tokens.Statuses.Update(status: $"{kintoneRequest.Record.投稿内容.Value}", media_ids: mediaIds); _logger.LogInformation($"Twitter投稿OK。Id:{tweetResponse.Id},CreatedAt:{tweetResponse.CreatedAt}"); } catch (TwitterException ex) { var error = ex.Errors.First(); var errorMessage = $"{error.Code}:{error.Message}"; _logger.LogWarning(errorMessage); //エラーをKintoneに反映 var tweetErrorJson = JsonSerializer.Serialize(new NotifyErrorRequestBody(kintoneRequest.App.Id, kintoneRequest.Record.レコード番号.Value, errorMessage)); await NotifyAsync(tweetErrorJson); //キャッチできるエラーなので、200で返す return(Ok()); } catch (Exception ex) { var errorMessage = ex.Message; //stacktraceはサーバにはstacktraceも出す _logger.LogError($"{errorMessage}\r\n{ex.StackTrace}"); //エラーをKintoneに反映 var jsonError = JsonSerializer.Serialize(new NotifyErrorRequestBody(kintoneRequest.App.Id, kintoneRequest.Record.レコード番号.Value, errorMessage)); await NotifyAsync(jsonError); //想定していないエラーなので、500で返す return(new StatusCodeResult(StatusCodes.Status500InternalServerError)); } //投稿結果をKintoneに反映 var json = JsonSerializer.Serialize(new NotifySuccessRequestBody(kintoneRequest.App.Id, kintoneRequest.Record.レコード番号.Value)); if (await NotifyAsync(json)) { return(Ok()); } return(new StatusCodeResult(StatusCodes.Status500InternalServerError)); }