diff --git a/common/src/main/java/cn/hezhaohui/common/CardEnum.java b/common/src/main/java/cn/hezhaohui/common/CardEnum.java index 533c81b..45d212d 100644 --- a/common/src/main/java/cn/hezhaohui/common/CardEnum.java +++ b/common/src/main/java/cn/hezhaohui/common/CardEnum.java @@ -2,7 +2,8 @@ package cn.hezhaohui.common; public enum CardEnum { CARD_WEATHER("AAqxas5etOJDx", "1.0.5"), - CARD_MOVIE("AAqhYDej6RK7O", "1.0.1"); + CARD_MOVIE("AAqhYDej6RK7O", "1.0.1"), + CARD_WAKATIME("AAqhg9UY0e2Ir", "1.0.1"); private final String id; private final String versionName; diff --git a/common/src/main/java/cn/hezhaohui/common/WakaTimeConstant.java b/common/src/main/java/cn/hezhaohui/common/WakaTimeConstant.java new file mode 100644 index 0000000..93cf127 --- /dev/null +++ b/common/src/main/java/cn/hezhaohui/common/WakaTimeConstant.java @@ -0,0 +1,8 @@ +package cn.hezhaohui.common; + +public class WakaTimeConstant { + + public static final String WAKATIME_API_URL_PREFIX = "https://api.wakatime.com/api/v1/"; + public static final String WAKATIME_API_URL_LAST_7_DAYS = WAKATIME_API_URL_PREFIX + "users/current/summaries?range=last_7_days"; + public static final String WAKATIME_API_SECRET_KEY_BASE64 = "d2FrYV80MzYyZjQzMC1kY2Y4LTQ2YzktYjdkYy0yMjMwMjUxOTkwNWQ="; +} diff --git a/lark/src/main/java/cn/hezhaohui/lark/client/WakaTimeClient.java b/lark/src/main/java/cn/hezhaohui/lark/client/WakaTimeClient.java new file mode 100644 index 0000000..ff23240 --- /dev/null +++ b/lark/src/main/java/cn/hezhaohui/lark/client/WakaTimeClient.java @@ -0,0 +1,6 @@ +package cn.hezhaohui.lark.client; + +public interface WakaTimeClient { + + String getLast7DaysData(); +} diff --git a/lark/src/main/java/cn/hezhaohui/lark/client/impl/WakaTimeClientImpl.java b/lark/src/main/java/cn/hezhaohui/lark/client/impl/WakaTimeClientImpl.java new file mode 100644 index 0000000..0332d23 --- /dev/null +++ b/lark/src/main/java/cn/hezhaohui/lark/client/impl/WakaTimeClientImpl.java @@ -0,0 +1,18 @@ +package cn.hezhaohui.lark.client.impl; + + +import cn.hezhaohui.common.WakaTimeConstant; +import cn.hezhaohui.lark.client.WakaTimeClient; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpUtil; +import org.springframework.stereotype.Component; + +@Component +public class WakaTimeClientImpl implements WakaTimeClient { + @Override + public String getLast7DaysData() { + HttpRequest request = HttpUtil.createGet(WakaTimeConstant.WAKATIME_API_URL_LAST_7_DAYS); + request.auth("Basic " + WakaTimeConstant.WAKATIME_API_SECRET_KEY_BASE64); + return request.execute().body(); + } +} diff --git a/lark/src/main/java/cn/hezhaohui/lark/handler/EventListener.java b/lark/src/main/java/cn/hezhaohui/lark/handler/EventListener.java index 64b7cd9..0d23457 100644 --- a/lark/src/main/java/cn/hezhaohui/lark/handler/EventListener.java +++ b/lark/src/main/java/cn/hezhaohui/lark/handler/EventListener.java @@ -3,6 +3,7 @@ package cn.hezhaohui.lark.handler; import cn.hezhaohui.common.AppConstant; import cn.hezhaohui.common.CardEnum; import cn.hezhaohui.lark.service.MovieService; +import cn.hezhaohui.lark.service.WakaTimeService; import cn.hezhaohui.pojo.entity.Weather; import cn.hezhaohui.lark.client.WeatherClient; import cn.hezhaohui.lark.util.BeanUtil; @@ -48,6 +49,10 @@ public class EventListener { MovieService movieService = BeanUtil.getBean(MovieService.class); Map data = movieService.getMovies(); LarkUtil.sendCard(CardEnum.CARD_MOVIE, data); + } else if (eventKey.equals("code")) { + WakaTimeService wakaTimeService = BeanUtil.getBean(WakaTimeService.class); + HashMap last7DaysCardData = wakaTimeService.getLast7DaysCardData(); + LarkUtil.sendCard(CardEnum.CARD_WAKATIME, last7DaysCardData); } } }) diff --git a/lark/src/main/java/cn/hezhaohui/lark/service/WakaTimeService.java b/lark/src/main/java/cn/hezhaohui/lark/service/WakaTimeService.java new file mode 100644 index 0000000..c284f92 --- /dev/null +++ b/lark/src/main/java/cn/hezhaohui/lark/service/WakaTimeService.java @@ -0,0 +1,126 @@ +package cn.hezhaohui.lark.service; + +import cn.hezhaohui.lark.client.WakaTimeClient; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class WakaTimeService { + + @Resource + private WakaTimeClient wakaTimeClient; + + public List> getLast7DaysData() { + String last7DaysData = wakaTimeClient.getLast7DaysData(); + JSONObject jsonObject = JSONUtil.parseObj(last7DaysData); + JSONArray dataArray = jsonObject.getJSONArray("data"); + // Init + List> dailyActivities = new ArrayList<>(); + // Traverse + for (int i = 0; i < dataArray.size(); i++) { + JSONObject day = dataArray.getJSONObject(i); + + // 获取日期 + String date = day.getJSONObject("range").getStr("date"); + + // 获取当天编码时间 + JSONObject grandTotal = day.getJSONObject("grand_total"); + double total_seconds = grandTotal.getDouble("total_seconds"); + int total_minutes = (int) (total_seconds / 60); + + // Map 存储 + Map activity = new HashMap<>(); + activity.put("date", date); + activity.put("total_minutes", total_minutes); + + dailyActivities.add(activity); + + } + + return dailyActivities; + } + + public HashMap getLast7DaysCardData() { + List> daysData = this.getLast7DaysData(); + int totalMinutes = 0; + for (Map dayData : daysData) { + totalMinutes += (int) dayData.get("total_minutes"); + } + + HashMap cardData = new HashMap<>(); + cardData.put("total_time", totalMinutes); + cardData.put("average_time", totalMinutes / 7); + + // 图表 + // 日期格式化器 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d"); + // 构造 values 数组 + List> valuesList = new ArrayList<>(); + for (int i = 0; i < daysData.size(); i++) { + Map entry = daysData.get(i); + String originalDate = (String) entry.get("date"); + Integer singleMinutes = (Integer) entry.get("total_minutes"); + // 将 "2025-10-26" 转换为 "10/26" + LocalDate date = LocalDate.parse(originalDate); + String formattedDate = date.format(formatter); + // 构造数据项 + Map item = new HashMap<>(); + item.put("date", formattedDate); + item.put("day", "Day" + (i + 1)); // Day1, Day2, ... + item.put("minutes", singleMinutes); + valuesList.add(item); + } + // 构造 axes 数组 + List> axesList = new ArrayList<>(); + // 构造第一个轴(y轴) + Map axisY = new HashMap<>(); + axisY.put("orient", "left"); + Map titleY = new HashMap<>(); + titleY.put("text", "编码时长(分钟)"); + axisY.put("title", titleY); + axesList.add(axisY); + // 构造第二个轴(x轴) + Map axisX = new HashMap<>(); + axisX.put("orient", "bottom"); + Map titleX = new HashMap<>(); + titleX.put("text", "日期"); + axisX.put("title", titleX); + axesList.add(axisX); + // 构造 data 对象 + Map dataMap = new HashMap<>(); + dataMap.put("values", valuesList); + // 构造 label + Map labelMap = new HashMap<>(); + labelMap.put("visible", true); + // 构造 legends + Map legendsMap = new HashMap<>(); + legendsMap.put("orient", "top"); + legendsMap.put("visible", true); + // 构造 chartConfig 对象 + Map chartConfig = new HashMap<>(); + chartConfig.put("axes", axesList); + chartConfig.put("data", dataMap); + chartConfig.put("label", labelMap); + chartConfig.put("legends", legendsMap); + chartConfig.put("seriesField", "day"); + chartConfig.put("title", new HashMap<>(Map.of("text", "每日编码时长(分钟)"))); + chartConfig.put("type", "bar"); + chartConfig.put("xField", "date"); + chartConfig.put("yField", "minutes"); + + cardData.put("chart", chartConfig); + + return cardData; + + } +} diff --git a/lark/src/test/java/cn/hezhaohui/lark/client/impl/WakaTimeClientImplTest.java b/lark/src/test/java/cn/hezhaohui/lark/client/impl/WakaTimeClientImplTest.java new file mode 100644 index 0000000..785574d --- /dev/null +++ b/lark/src/test/java/cn/hezhaohui/lark/client/impl/WakaTimeClientImplTest.java @@ -0,0 +1,20 @@ +package cn.hezhaohui.lark.client.impl; + +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class WakaTimeClientImplTest { + + @Resource + private WakaTimeClientImpl wakaTimeClient; + + @Test + void getLast7DaysData() { + String last7DaysData = wakaTimeClient.getLast7DaysData(); + System.out.println(last7DaysData); + } +} \ No newline at end of file diff --git a/lark/src/test/java/cn/hezhaohui/lark/service/WakaTimeServiceTest.java b/lark/src/test/java/cn/hezhaohui/lark/service/WakaTimeServiceTest.java new file mode 100644 index 0000000..478c9fa --- /dev/null +++ b/lark/src/test/java/cn/hezhaohui/lark/service/WakaTimeServiceTest.java @@ -0,0 +1,32 @@ +package cn.hezhaohui.lark.service; + +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class WakaTimeServiceTest { + + @Resource + private WakaTimeService wakaTimeService; + + @Test + void getLast7DaysData() { + List> last7DaysData = wakaTimeService.getLast7DaysData(); +// System.out.println(last7DaysData); + for (Map data : last7DaysData) { + System.out.println(data); + } + } + + @Test + void getLast7DaysCardData() { + Map last7DaysCardData = wakaTimeService.getLast7DaysCardData(); + System.out.println(last7DaysCardData); + } +} \ No newline at end of file