Skip to content

Commit dad0cbf

Browse files
authored
Merge pull request #188 from lrsgzs/master
ClassIsland 联动优化
2 parents e16209d + 69884fb commit dad0cbf

10 files changed

Lines changed: 364 additions & 101 deletions

File tree

CHANGELOG/v2.3.0-beta.2/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ v2.3 - Shiroko (砂狼白子) beta 2
88

99
## 💡 功能优化
1010

11-
-
11+
- 优化 **ClassIsland 联动**,现在可以传递通知类型,并提醒用户安装插件。
1212

1313
## 🐛 修复问题
1414

app/Language/modules/notification_settings.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@
129129
"title": "ClassIsland通知服务",
130130
"content": "请确保已安装.NET 8运行时,并在ClassIsland中安装SecRandom-Ci插件",
131131
},
132+
"classisland_plugin_notification_hint": {
133+
"title": "ClassIsland通知服务",
134+
"content": "检测到未安装插件,请在ClassIsland中安装SecRandom-Ci插件",
135+
},
136+
"classisland_configured_successfully": {
137+
"title": "ClassIsland通知服务",
138+
"content": "检测到ClassIsland和SecRandom-Ci插件正常运行,欢迎使用",
139+
},
132140
},
133141
"EN_US": {
134142
"title": {
@@ -219,6 +227,14 @@
219227
"title": "ClassIsland Notification Service",
220228
"content": "Please ensure .NET 8 runtime is installed and SecRandom-Ci plugin is installed in ClassIsland",
221229
},
230+
"classisland_plugin_notification_hint": {
231+
"title": "ClassIsland Notification Service",
232+
"content": "Plugin not detected, please install SecRandom-Ci plugin in ClassIsland",
233+
},
234+
"classisland_configured_successfully": {
235+
"title": "ClassIsland Notification Service",
236+
"content": "Detected ClassIsland and SecRandom-Ci plugin running properly, welcome to use",
237+
},
222238
},
223239
"JA_JP": {
224240
"title": {
@@ -313,6 +329,14 @@
313329
"title": "ClassIsland通知サービス",
314330
"content": ".NET 8ランタイムがインストールされ、ClassIslandにSecRandom-Ciプラグインがインストールされていることを確認してください",
315331
},
332+
"classisland_plugin_notification_hint": {
333+
"title": "ClassIsland通知サービス",
334+
"content": "プラグインがインストールされていないことを検出しました、ClassIslandにSecRandom-Ciプラグインをインストールしてください",
335+
},
336+
"classisland_configured_successfully": {
337+
"title": "ClassIsland通知サービス",
338+
"content": "ClassIslandとSecRandom-Ciプラグインが正常に動作していることを検出しました、ご利用いただきありがとうございます",
339+
},
316340
},
317341
}
318342

@@ -388,6 +412,14 @@
388412
"title": "ClassIsland通知服务",
389413
"content": "请确保已安装.NET 8运行时,并在ClassIsland中安装SecRandom-Ci插件",
390414
},
415+
"classisland_plugin_notification_hint": {
416+
"title": "ClassIsland通知服务",
417+
"content": "检测到未安装插件,请在ClassIsland中安装SecRandom-Ci插件",
418+
},
419+
"classisland_configured_successfully": {
420+
"title": "ClassIsland通知服务",
421+
"content": "检测到ClassIsland和SecRandom-Ci插件正常运行,欢迎使用",
422+
},
391423
},
392424
"EN_US": {
393425
"title": {
@@ -462,6 +494,14 @@
462494
"title": "ClassIsland Notification Service",
463495
"content": "Please ensure .NET 8 runtime is installed and SecRandom-Ci plugin is installed in ClassIsland",
464496
},
497+
"classisland_plugin_notification_hint": {
498+
"title": "ClassIsland Notification Service",
499+
"content": "Plugin not detected, please install SecRandom-Ci plugin in ClassIsland",
500+
},
501+
"classisland_configured_successfully": {
502+
"title": "ClassIsland Notification Service",
503+
"content": "Detected ClassIsland and SecRandom-Ci plugin running properly, welcome to use",
504+
},
465505
},
466506
"JA_JP": {
467507
"title": {
@@ -537,6 +577,14 @@
537577
"title": "ClassIsland通知サービス",
538578
"content": ".NET 8ランタイムがインストールされ、ClassIslandにSecRandom-Ciプラグインがインストールされていることを確認してください",
539579
},
580+
"classisland_plugin_notification_hint": {
581+
"title": "ClassIsland通知サービス",
582+
"content": "プラグインがインストールされていないことを検出しました、ClassIslandにSecRandom-Ciプラグインをインストールしてください",
583+
},
584+
"classisland_configured_successfully": {
585+
"title": "ClassIsland通知サービス",
586+
"content": "ClassIslandとSecRandom-Ciプラグインが正常に動作していることを検出しました、ご利用いただきありがとうございます",
587+
},
540588
},
541589
}
542590

@@ -630,6 +678,14 @@
630678
"title": "ClassIsland通知服务",
631679
"content": "请确保已安装.NET 8运行时,并在ClassIsland中安装SecRandom-Ci插件",
632680
},
681+
"classisland_plugin_notification_hint": {
682+
"title": "ClassIsland通知服务",
683+
"content": "检测到未安装插件,请在ClassIsland中安装SecRandom-Ci插件",
684+
},
685+
"classisland_configured_successfully": {
686+
"title": "ClassIsland通知服务",
687+
"content": "检测到ClassIsland和SecRandom-Ci插件正常运行,欢迎使用",
688+
},
633689
},
634690
"EN_US": {
635691
"title": {
@@ -716,6 +772,14 @@
716772
"title": "ClassIsland Notification Service",
717773
"content": "Please ensure .NET 8 runtime is installed and SecRandom-Ci plugin is installed in ClassIsland",
718774
},
775+
"classisland_plugin_notification_hint": {
776+
"title": "ClassIsland Notification Service",
777+
"content": "Plugin not detected, please install SecRandom-Ci plugin in ClassIsland",
778+
},
779+
"classisland_configured_successfully": {
780+
"title": "ClassIsland Notification Service",
781+
"content": "Detected ClassIsland and SecRandom-Ci plugin running properly, welcome to use",
782+
},
719783
},
720784
"JA_JP": {
721785
"title": {
@@ -805,5 +869,13 @@
805869
"title": "ClassIsland通知サービス",
806870
"content": ".NET 8ランタイムがインストールされ、ClassIslandにSecRandom-Ciプラグインがインストールされていることを確認してください",
807871
},
872+
"classisland_plugin_notification_hint": {
873+
"title": "ClassIsland通知サービス",
874+
"content": "プラグインがインストールされていないことを検出しました、ClassIslandにSecRandom-Ciプラグインをインストールしてください",
875+
},
876+
"classisland_configured_successfully": {
877+
"title": "ClassIsland通知サービス",
878+
"content": "ClassIslandとSecRandom-Ciプラグインが正常に動作していることを検出しました、ご利用いただきありがとうございます",
879+
},
808880
},
809881
}

app/common/IPC_URL/csharp_ipc_handler.py

Lines changed: 103 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@
2323
clr.AddReference("ClassIsland.Shared.IPC")
2424
clr.AddReference("SecRandom4Ci.Interface")
2525

26-
from System import Action, DateTime
26+
from System import Action, DateTime, Version
2727
from ClassIsland.Shared.Enums import TimeState
2828
from ClassIsland.Shared.IPC import IpcClient, IpcRoutedNotifyIds
2929
from ClassIsland.Shared.IPC.Abstractions.Services import IPublicLessonsService
3030
from dotnetCampus.Ipc.CompilerServices.GeneratedProxies import (
3131
GeneratedIpcFactory,
3232
)
33+
from SecRandom4Ci.Interface.Enums import ResultType
34+
from SecRandom4Ci.Interface.Models import CallResult, NotificationData, Student
3335
from SecRandom4Ci.Interface.Services import ISecRandomService
34-
from SecRandom4Ci.Interface.Models import CallResult, Student
3536

3637
CSHARP_AVAILABLE = True
3738
except Exception as e:
@@ -68,7 +69,7 @@ def __init__(self):
6869
self.loop: Optional[asyncio.AbstractEventLoop] = None
6970
self.is_running = False
7071
self.is_connected = False
71-
self._disconnect_logged = False # 跟踪是否已记录断连日志
72+
self._no_plugin_logged = False
7273
self._last_on_class_left_log_time = 0 # 上次记录距离上课时间的时间
7374
self._last_known_subject_name: Optional[str] = None
7475

@@ -120,6 +121,7 @@ def send_notification(
120121
draw_count=1,
121122
settings=None,
122123
settings_group=None,
124+
is_animating=False,
123125
) -> bool:
124126
"""发送提醒"""
125127
if not self.is_running:
@@ -134,17 +136,71 @@ def send_notification(
134136
display_duration = 5
135137

136138
logger.debug(
137-
f"发送通知到 ClassIsland: 班级={class_name}, 选中学生={selected_students}, 抽取数量={draw_count}, 显示时长={display_duration}"
139+
f"发送通知到 ClassIsland: 班级={class_name}, 选中学生={selected_students}, 抽取数量={draw_count}, 显示时长={display_duration}, 设置组={settings_group}, 是否动画={is_animating}"
138140
)
139141

140142
randomService = GeneratedIpcFactory.CreateIpcProxy[ISecRandomService](
141143
self.ipc_client.Provider, self.ipc_client.PeerProxy
142144
)
143-
result = self.convert_to_call_result(
144-
class_name, selected_students, draw_count, display_duration
145-
)
146-
randomService.NotifyResult(result)
147145

146+
try:
147+
plugin_version = randomService.GetPluginVersion()
148+
except Exception as e:
149+
plugin_version = Version.Parse("0.0.0.1")
150+
151+
logger.debug(f"插件版本为 {plugin_version}")
152+
if plugin_version < Version.Parse("1.2.0.0"):
153+
logger.warning("检测到旧版插件 (小于 1.2.0.0),请尽快升级!")
154+
155+
result = CallResult()
156+
result.ClassName = class_name
157+
result.DrawCount = draw_count
158+
result.DisplayDuration = display_duration
159+
for student in selected_students:
160+
cs_student = Student()
161+
cs_student.StudentId = student[0]
162+
cs_student.StudentName = student[1]
163+
cs_student.Exists = student[2]
164+
result.SelectedStudents.Add(cs_student)
165+
randomService.NotifyResult(result)
166+
167+
return True
168+
169+
if settings_group is None:
170+
notification_type = ResultType.Unknown
171+
elif "roll_call" in settings_group:
172+
notification_type = [
173+
ResultType.PartialRollCall,
174+
ResultType.FinishedRollCall,
175+
][not is_animating]
176+
elif "quick_draw" in settings_group:
177+
notification_type = [
178+
ResultType.PartialQuickDraw,
179+
ResultType.FinishedQuickDraw,
180+
][not is_animating]
181+
elif "lottery" in settings_group:
182+
notification_type = [
183+
ResultType.PartialLottery,
184+
ResultType.FinishedLottery,
185+
][not is_animating]
186+
else:
187+
notification_type = ResultType.Unknown
188+
189+
logger.debug(f"通知类型: {notification_type}")
190+
191+
data = NotificationData()
192+
data.ResultType = notification_type
193+
data.ClassName = class_name
194+
data.DrawCount = draw_count
195+
data.DisplayDuration = display_duration
196+
for student in selected_students:
197+
cs_student = Student()
198+
cs_student.StudentId = student[0]
199+
cs_student.StudentName = student[1]
200+
cs_student.Exists = student[2]
201+
data.Items.Add(cs_student)
202+
203+
randomService.ShowNotification(data)
148204
return True
149205

150206
def is_breaking(self) -> bool:
@@ -307,22 +363,6 @@ def get_elapsed_since_previous_time_point_end_seconds(self) -> int:
307363
except Exception:
308364
return 0
309365

310-
@staticmethod
311-
def convert_to_call_result(
312-
class_name: str, selected_students, draw_count: int, display_duration=5.0
313-
) -> CallResult:
314-
result = CallResult()
315-
result.ClassName = class_name
316-
result.DrawCount = draw_count
317-
result.DisplayDuration = display_duration
318-
for student in selected_students:
319-
cs_student = Student()
320-
cs_student.StudentId = student[0]
321-
cs_student.StudentName = student[1]
322-
cs_student.Exists = student[2]
323-
result.SelectedStudents.Add(cs_student)
324-
return result
325-
326366
def _on_class_test(self):
327367
lessonSc = GeneratedIpcFactory.CreateIpcProxy[IPublicLessonsService](
328368
self.ipc_client.Provider, self.ipc_client.PeerProxy
@@ -353,22 +393,28 @@ async def client():
353393
task = self.ipc_client.Connect()
354394
await self.loop.run_in_executor(None, lambda: task.Wait())
355395
self.is_connected = True
396+
logger.debug("C# IPC 连接成功!")
356397

357398
while self.is_running:
358399
await asyncio.sleep(1)
359400

360-
if not self._check_alive():
361-
if not self._disconnect_logged:
401+
# logger.debug(f"stat: plugin({self._check_plugin_alive()}) ci({self._check_ci_alive()})")
402+
if not self.check_plugin_alive():
403+
if not self.check_ci_alive():
362404
logger.debug("C# IPC 断连!重连...")
363-
self._disconnect_logged = True
364-
self.is_connected = False
365-
366-
task = self.ipc_client.Connect()
367-
await self.loop.run_in_executor(
368-
None, lambda task=task: task.Wait()
369-
)
370-
self.is_connected = True
371-
self._disconnect_logged = False
405+
self.is_connected = False
406+
407+
task = self.ipc_client.Connect()
408+
await self.loop.run_in_executor(
409+
None, lambda task=task: task.Wait()
410+
)
411+
self.is_connected = True
412+
logger.debug("C# IPC 连接成功!")
413+
elif not self._no_plugin_logged:
414+
logger.debug("未安装 SecRandom-Ci 插件。")
415+
self._no_plugin_logged = True
416+
else:
417+
self._no_plugin_logged = False
372418

373419
self.ipc_client = None
374420
self.is_connected = False
@@ -386,8 +432,19 @@ async def client():
386432
self.loop.close()
387433
self.loop = None
388434

389-
def _check_alive(self) -> bool:
390-
"""客户端是否正常连接"""
435+
def check_ci_alive(self) -> bool:
436+
"""ClassIsland 是否正常连接"""
437+
try:
438+
lessonsService = GeneratedIpcFactory.CreateIpcProxy[
439+
IPublicLessonsService
440+
](self.ipc_client.Provider, self.ipc_client.PeerProxy)
441+
return lessonsService.IsTimerRunning
442+
except Exception as e:
443+
logger.debug(e)
444+
return False
445+
446+
def check_plugin_alive(self) -> bool:
447+
"""SecRandom-Ci 插件是否正常连接"""
391448
try:
392449
randomService = GeneratedIpcFactory.CreateIpcProxy[ISecRandomService](
393450
self.ipc_client.Provider, self.ipc_client.PeerProxy
@@ -444,6 +501,7 @@ def send_notification(
444501
draw_count=1,
445502
settings=None,
446503
settings_group=None,
504+
is_animating=False,
447505
) -> bool:
448506
"""发送提醒"""
449507
return False
@@ -484,15 +542,17 @@ def get_previous_class_info(self) -> dict:
484542
def get_elapsed_since_previous_time_point_end_seconds(self) -> int:
485543
return 0
486544

487-
@staticmethod
488-
def convert_to_call_result(
489-
class_name: str, selected_students, draw_count: int, display_duration=5.0
490-
) -> object:
491-
return object
492-
493545
def _on_class_test(self):
494546
pass
495547

496548
def _run_client(self):
497549
"""运行 C# IPC 客户端"""
498550
pass
551+
552+
def check_ci_alive(self) -> bool:
553+
"""ClassIsland 是否正常连接"""
554+
return False
555+
556+
def check_plugin_alive(self) -> bool:
557+
"""SecRandom-Ci 插件是否正常连接"""
558+
return False

app/common/notification/notification_service.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,7 @@ def _normalize_text(value):
10311031
draw_count,
10321032
settings,
10331033
settings_group,
1034+
is_animating
10341035
)
10351036
if status:
10361037
logger.info("成功发送通知到ClassIsland,结果未知")

0 commit comments

Comments
 (0)