public async Task <DiaryGrpcResponse> GetDiaryDatesAsync(DiaryGrpcRequest request, CallContext context = default)
    {
        var response = new DiaryGrpcResponse();

        try
        {
            response.DiaryDates = await _diaryFileService.GetDiaryDatesAsync(request.Year, request.Month);
        }
        catch (Exception ex)
        {
            response.IsOk    = false;
            response.Message = ex.Message;
            _logger.LogError(ex, $"Get diaries count failed: {JsonUtil.Serialize(request)}");
        }

        return(response);
    }
    public async Task <ApiResponse <ChartResponse> > GetChartForCountPerMonth()
    {
        var response = new ApiResponse <ChartResponse>();

        try
        {
            var request = new DiaryGrpcRequest {
                Year = DateTime.Now.Year
            };
            var diaryResponse = await _diaryGrpcService.GetDiaryDatesAsync(request);

            if (diaryResponse.IsOk)
            {
                var chart = new ChartResponse
                {
                    Title = "当月的日记数",
                    Type  = "line"
                };

                diaryResponse.DiaryDates ??= new List <DateTime>();
                foreach (var item in diaryResponse.DiaryDates.GroupBy(x => x.Month).OrderBy(x => x.Key))
                {
                    chart.Data.Add(item.Count());
                    chart.Labels.Add($"{item.Key}月");
                }

                response.Content = chart;
            }
            else
            {
                response.IsOk    = false;
                response.Message = diaryResponse.Message;
            }
        }
        catch (Exception ex)
        {
            response.IsOk    = false;
            response.Message = ex.Message;
            _logger.LogError(ex, "Get chart for count per month failed.");
        }

        return(response);
    }
    public async Task <ApiResponse <ChartResponse> > GetChartForWordsPerYear()
    {
        var response = new ApiResponse <ChartResponse>();

        try
        {
            var request = new DiaryGrpcRequest {
                ExtractRuntime = true
            };
            var diaryResponse = await _diaryGrpcService.GetDiariesAsync(request);

            if (diaryResponse.IsOk)
            {
                var chart = new ChartResponse
                {
                    Title = "当年的日记字数",
                    Type  = "line"
                };

                diaryResponse.DiaryRuntimeList ??= new List <DiaryRuntime>();
                foreach (var item in diaryResponse.DiaryRuntimeList.GroupBy(x => x.Raw.Date.Year).OrderBy(x => x.Key))
                {
                    chart.Data.Add(item.Sum(x => x.Raw.MarkdownContent.Length));
                    chart.Labels.Add($"{item.Key}年");
                }

                response.Content = chart;
            }
            else
            {
                response.IsOk    = false;
                response.Message = diaryResponse.Message;
            }
        }
        catch (Exception ex)
        {
            response.IsOk    = false;
            response.Message = ex.Message;
            _logger.LogError(ex, "Get chart for words per year failed.");
        }

        return(response);
    }
    public async Task <DiaryGrpcResponse> UpdateDiaryAsync(DiaryGrpcRequest request, CallContext context = default)
    {
        var response = new DiaryGrpcResponse();

        try
        {
            await _diaryFileService.UpdateDiaryAsync(request.Diary);

            response.Diary = request.Diary;
        }
        catch (Exception ex)
        {
            response.IsOk    = false;
            response.Message = ex.Message;
            _logger.LogError(ex, $"Update diary failed: {JsonUtil.Serialize(request)}");
        }

        return(response);
    }
    public async Task <IActionResult> Detail([FromRoute] int year, [FromRoute] int month, [FromRoute] int day)
    {
        var date    = new DateTime(year, month, day);
        var request = new DiaryGrpcRequest {
            Date = date, ExtractRuntime = true, ExtractNext = true, ExtractPrev = true
        };
        var response = await _diaryGrpcService.GetDiaryAsync(request);

        if (response.IsOk)
        {
            if (response.NotFound)
            {
                return(Redirect($"{_options.AdminRemoteEndpoint}/diary/add?date={date.ToDate()}"));
            }

            return(View(response.DiaryRuntime));
        }

        return(NotFound());
    }