diff --git a/gsuid_core/bg.png b/gsuid_core/bg.png new file mode 100644 index 0000000..292112e Binary files /dev/null and b/gsuid_core/bg.png differ diff --git a/gsuid_core/fg.png b/gsuid_core/fg.png new file mode 100644 index 0000000..75e255e Binary files /dev/null and b/gsuid_core/fg.png differ diff --git a/gsuid_core/global_val.py b/gsuid_core/global_val.py index 359ceb7..9e7a8a3 100644 --- a/gsuid_core/global_val.py +++ b/gsuid_core/global_val.py @@ -41,7 +41,6 @@ def get_platform_val(bot_id: str, bot_self_id: str): bot_val[bot_id] = {} if bot_self_id not in bot_val[bot_id]: bot_val[bot_id][bot_self_id] = deepcopy(platform_val) - return bot_val[bot_id][bot_self_id] @@ -57,7 +56,7 @@ def get_all_bot_dict(): async def get_value_analysis( - bot_id: str, bot_self_id: str, day: int = 7 + bot_id: str, bot_self_id: Optional[str], day: int = 7 ) -> Dict[str, PlatformVal]: '''顺序为最新的日期在前面''' result = {} @@ -71,13 +70,18 @@ async def get_value_analysis( return result -async def get_global_analysis(bot_id: str, bot_self_id: str): +async def get_global_analysis( + bot_id: str, + bot_self_id: Optional[str], +): seven_data = await get_value_analysis(bot_id, bot_self_id, 30) group_data = [] user_data = [] user_list: List[List[str]] = [] + group_list: List[List[str]] = [] + group_all_list: List[str] = [] user_all_list: List[str] = [] for day in seven_data: @@ -86,23 +90,43 @@ async def get_global_analysis(bot_id: str, bot_self_id: str): continue _user_list = list(local_val['user'].keys()) + _group_list = list(local_val['group'].keys()) user_list.append(_user_list) user_all_list.extend(_user_list) + group_list.append(_group_list) + group_all_list.extend(_group_list) group_data.append(len(local_val['group'])) user_data.append(len(local_val['user'])) # 七天内的用户 user_7_list = [user for users in user_list[:7] for user in users] + # 七天内的群组 + group_7_list = [group for groups in group_list[:7] for group in groups] # 昨日到三十日之前的用户 user_after_list = [user for users in user_list[1:] for user in users] + # 昨日到三十日之前的群组 + group_after_list = [group for groups in group_list[1:] for group in groups] # 三十天内的用户没有在这七天出现过 out_user = [] + # 三十天内的群组没有在这七天出现过 + out_group = [] # 今天的用户从来没在这个月内出现过 new_user = [] + # 今天的群组从来没在这个月内出现过 + new_group = [] + + for i in group_all_list: + if i not in group_7_list: + out_group.append(i) + + if group_list: + for i in group_list[0]: + if i not in group_after_list: + new_group.append(i) for i in user_all_list: if i not in user_7_list: @@ -130,6 +154,12 @@ async def get_global_analysis(bot_id: str, bot_self_id: str): if len(_user_all_list) != 0 else "0.00%" ), + 'NG': str(len(new_group)), + 'OG': ( + '{0:.2f}%'.format((len(out_group) / len(group_all_list)) * 100) + if len(group_all_list) != 0 + else "0.00%" + ), } return data @@ -157,9 +187,57 @@ async def save_all_global_val(day: int = 0): await save_global_val(bot_id, bot_self_id, day) +def merge_dict(dict1: PlatformVal, dict2: PlatformVal) -> PlatformVal: + result = dict1.copy() + + for key, value in dict2.items(): + if key in result: + if isinstance(value, (int, float)) and isinstance( + result[key], (int, float) + ): + result[key] += value + elif isinstance(value, dict) and isinstance(result[key], dict): + result[key] = merge_dict(result[key], value) # type: ignore + else: + result[key] = value + else: + result[key] = value + + return result + + async def get_global_val( - bot_id: str, bot_self_id: str, day: Optional[int] = None + bot_id: str, bot_self_id: Optional[str], day: Optional[int] = None ) -> PlatformVal: + if bot_self_id is None: + all_bot_self_id: Dict[str, List[str]] = {} + for bot_id in bot_val: + all_bot_self_id[bot_id] = [] + for bot_self_id in bot_val[bot_id]: + all_bot_self_id[bot_id].append(bot_self_id) + + for bot_id_path in global_val_path.iterdir(): + if bot_id_path.name not in all_bot_self_id: + all_bot_self_id[bot_id_path.name] = [] + for bot_self_id_path in bot_id_path.iterdir(): + if ( + bot_self_id_path.name + not in all_bot_self_id[bot_id_path.name] + ): + all_bot_self_id[bot_id_path.name].append( + bot_self_id_path.name + ) + + pv = deepcopy(platform_val) + for bot_id in all_bot_self_id: + for bot_self_id in all_bot_self_id[bot_id]: + pv = merge_dict( + await get_global_val(bot_id, bot_self_id, day), + pv, + ) + + return pv + if day is None or day == 0: return get_platform_val(bot_id, bot_self_id) else: diff --git a/gsuid_core/status/draw_status.py b/gsuid_core/status/draw_status.py index 098d602..fad5b4f 100644 --- a/gsuid_core/status/draw_status.py +++ b/gsuid_core/status/draw_status.py @@ -214,15 +214,18 @@ async def draw_badge( return badge -async def draw_data_analysis1(ev: Event): +async def draw_data_analysis1( + bot_id: str, + bot_self_id: Optional[str], +): local_val = await gv.get_global_val( - ev.real_bot_id, - ev.bot_self_id, + bot_id, + bot_self_id, ) yesterday = await gv.get_global_val( - ev.real_bot_id, - ev.bot_self_id, + bot_id, + bot_self_id, 1, ) @@ -272,11 +275,15 @@ async def draw_data_analysis1(ev: Event): return data_bar -async def draw_data_analysis2(ev: Event): +async def draw_data_analysis2( + bot_id: str, + bot_self_id: Optional[str], +): data = await gv.get_global_analysis( - ev.real_bot_id, - ev.bot_self_id, + bot_id, + bot_self_id, ) + badge1 = await draw_badge( 'DAU', data['DAU'], @@ -297,9 +304,20 @@ async def draw_data_analysis2(ev: Event): 0, HINT_COLOR, ) + badge5 = await draw_badge( + '群聊新增', + data['NG'], + ) + badge6 = await draw_badge( + '群聊留存', + data['OG'], + 0, + ) data_bar = Image.new('RGBA', (1400, 200)) - for index, i in enumerate([badge1, badge2, badge3, badge4]): + for index, i in enumerate( + [badge1, badge2, badge3, badge4, badge5, badge6] + ): data_bar.paste(i, (75 + index * 210, 25), i) return data_bar @@ -493,14 +511,28 @@ async def draw_curve_img(ev: Event): 30, ) + _data_2 = await gv.get_value_analysis( + ev.real_bot_id, + None, + 30, + ) + result: Dict[Union[Tuple[int, int, int], str], List[float]] = { THEME_COLOR: [], HINT_COLOR: [], + (182, 122, 210): [], + (27, 146, 210): [], } for day in _data: data = _data[day] + data2 = _data_2[day] + result[THEME_COLOR].append(data['receive']) result[HINT_COLOR].append(data['send']) + + result[(182, 122, 210)].append(data2['receive']) + result[(27, 146, 210)].append(data2['send']) + curve_img = await draw_curve(result) return curve_img @@ -541,31 +573,52 @@ async def draw_bg(w: int, h: int): async def draw_status(ev: Event): title = await draw_title() bar1 = await draw_bar('服务器基础信息', 'Base Info') - bar2 = await draw_bar('机器人数据统计', 'Data Analysis') + bar2_1 = await draw_bar('机器人数据统计(单)', 'Data Analysis') + bar2_2 = await draw_bar('机器人数据统计(多)', 'Data Analysis') bar3 = await draw_bar('日活曲线', 'Daily Activity Curve') bar4 = await draw_bar('插件额外信息', 'Extra Data') hw = draw_hw() - data_bar1 = await draw_data_analysis1(ev) - data_bar2 = await draw_data_analysis2(ev) + data_bar1_1 = await draw_data_analysis1( + ev.real_bot_id, + ev.bot_self_id, + ) + data_bar2_1 = await draw_data_analysis2( + ev.real_bot_id, + ev.bot_self_id, + ) + data_bar1_2 = await draw_data_analysis1( + ev.real_bot_id, + None, + ) + data_bar2_2 = await draw_data_analysis2( + ev.real_bot_id, + None, + ) + plugin_status_img = await draw_plugins_status() curve_img = await draw_curve_img(ev) plugins_num = len(plugins_status) plugins_h = 100 + plugins_num * 180 - img = await draw_bg(1400, 2267 + 150 + plugins_h) + img = await draw_bg(1400, 2778 + 150 + plugins_h) img.paste(title, (0, 0), title) img.paste(bar1, (0, 855), bar1) img.paste(hw, (0, 920), hw) - img.paste(bar2, (0, 1202), bar2) - img.paste(data_bar1, (0, 1289), data_bar1) - img.paste(data_bar2, (0, 1463), data_bar2) - img.paste(bar3, (0, 1686), bar3) - img.paste(curve_img, (0, 1755), curve_img) - img.paste(bar4, (0, 2267), bar4) - img.paste(plugin_status_img, (0, 2367), plugin_status_img) + img.paste(bar2_1, (0, 1202), bar2_1) + img.paste(data_bar1_1, (0, 1289), data_bar1_1) + img.paste(data_bar2_1, (0, 1463), data_bar2_1) + + img.paste(bar2_2, (0, 1686), bar2_2) + img.paste(data_bar1_2, (0, 1773), data_bar1_2) + img.paste(data_bar2_2, (0, 1974), data_bar2_2) + + img.paste(bar3, (0, 2197), bar3) + img.paste(curve_img, (0, 2266), curve_img) + img.paste(bar4, (0, 2778), bar4) + img.paste(plugin_status_img, (0, 2878), plugin_status_img) img = add_footer(img, footer=Image.open(TEXT_PATH / 'footer.png')) res = await convert_img(img)