@@ -40,6 +40,8 @@ enum Command {
4040 Comment ( String ) ,
4141 #[ command( description = "搜索" ) ]
4242 Find ( String ) ,
43+ #[ command( description = "删除评价" ) ]
44+ Del ( String ) ,
4345}
4446
4547#[ tokio:: main]
@@ -52,7 +54,7 @@ async fn main() {
5254 bot. set_my_commands ( Command :: bot_commands ( ) ) // 向 telegram 注册命令
5355 . await
5456 . expect ( "Failed to set bot commands to telegram" ) ;
55-
57+
5658 log:: info!( "Bot commands have been set" ) ;
5759
5860 Dispatcher :: builder ( bot, schema ( ) )
@@ -78,6 +80,7 @@ fn schema() -> UpdateHandler<Box<dyn std::error::Error + Send + Sync + 'static>>
7880 . branch ( case ! [ Command :: DownloadDb ] . endpoint ( download_db_command) )
7981 . branch ( case ! [ Command :: Find ( arg) ] . endpoint ( find_command) )
8082 . branch ( case ! [ Command :: Comment ( arg) ] . endpoint ( comment_command) )
83+ . branch ( case ! [ Command :: Del ( arg) ] . endpoint ( delete_comment_command) )
8184 . branch ( dptree:: endpoint ( invalid_command) ) ;
8285
8386 // 文本消息
@@ -90,7 +93,8 @@ fn schema() -> UpdateHandler<Box<dyn std::error::Error + Send + Sync + 'static>>
9093 . branch ( case ! [ State :: Department { school_cate, university } ] . endpoint ( choose_supervisor) )
9194 . branch ( case ! [ State :: Supervisor { school_cate, university, department } ] . endpoint ( read_or_comment) )
9295 . branch ( case ! [ State :: Comment { object_id, comment_type } ] . endpoint ( add_comment) )
93- . branch ( case ! [ State :: Publish { object_id, comment, comment_type } ] . endpoint ( publish_comment) ) ;
96+ . branch ( case ! [ State :: Publish { object_id, comment, comment_type } ] . endpoint ( publish_comment) )
97+ . branch ( case ! [ State :: DeleteConfirm { comment_id } ] . endpoint ( confirm_delete_comment) ) ;
9498
9599 // 消息
96100 let message_handler = Update :: filter_message ( )
@@ -197,6 +201,90 @@ async fn find_command(bot: Bot, dialogue: MyDialogue, arg: String, msg: Message)
197201 Ok ( ( ) )
198202}
199203
204+ /// 删除评价命令
205+ async fn delete_comment_command (
206+ bot : Bot ,
207+ dialogue : MyDialogue ,
208+ arg : String ,
209+ msg : Message ,
210+ ) -> HandlerResult {
211+ let parts: Vec < & str > = arg. split_whitespace ( ) . collect ( ) ;
212+
213+ if parts. len ( ) != 2 {
214+ bot. send_message (
215+ msg. chat . id ,
216+ "使用方法:\n /del <评价 ID> <发布人 OTP>\n 示例:/del ab12cd34 xxxxxxxx" ,
217+ )
218+ . reply_to_message_id ( msg. id )
219+ . await ?;
220+ return Ok ( ( ) ) ;
221+ }
222+
223+ let comment_id = parts[ 0 ] . to_string ( ) ;
224+ let otp = parts[ 1 ] . to_string ( ) ;
225+
226+ let comment = match SAFC_DB . find_comment_by_id ( & comment_id) ? {
227+ Some ( c) => c,
228+ None => {
229+ bot. send_message (
230+ msg. chat . id ,
231+ format ! ( "未找到评价 `{}`。请检查评价 ID。" , comment_id) ,
232+ )
233+ . reply_to_message_id ( msg. id )
234+ . await ?;
235+ return Ok ( ( ) ) ;
236+ }
237+ } ;
238+
239+ let author_sign = match comment. author_sign . as_ref ( ) {
240+ Some ( sign) => sign,
241+ None => {
242+ bot. send_message (
243+ msg. chat . id ,
244+ "该评价未设置 OTP,暂不支持自行删除。" ,
245+ )
246+ . reply_to_message_id ( msg. id )
247+ . await ?;
248+ return Ok ( ( ) ) ;
249+ }
250+ } ;
251+
252+ let expected_sign = hash_author_sign ( & comment_id, & otp) ;
253+ if author_sign != & expected_sign {
254+ bot. send_message (
255+ msg. chat . id ,
256+ "签名验证失败。请确认评价 ID 与 OTP 是否正确。" ,
257+ )
258+ . reply_to_message_id ( msg. id )
259+ . await ?;
260+ return Ok ( ( ) ) ;
261+ }
262+
263+ let object_info = match SAFC_DB . find_objteacher_with_id ( comment. object . as_str ( ) ) ? {
264+ Some ( obj) => obj. display_path ( ) ,
265+ None => format ! ( "客体 ID {}" , comment. object) ,
266+ } ;
267+
268+ let comment_body = escape ( comment. description . as_str ( ) ) ;
269+ let comment_type_label = comment. comment_type . to_string ( ) ;
270+ let confirm_message = format ! (
271+ "评价 ID `{}`\n 对象:{}\n 日期:{}\n 类型:{}\n \n ```text\n {}\n ```\n \n 签名验证成功。\n 请回复「确认删除」以继续,或发送 /cancel 终止此操作。" ,
272+ escape( comment_id. as_str( ) ) ,
273+ escape( object_info. as_str( ) ) ,
274+ escape( comment. date. as_str( ) ) ,
275+ escape( comment_type_label. as_str( ) ) ,
276+ comment_body
277+ ) ;
278+
279+ bot. send_message ( msg. chat . id , confirm_message)
280+ . reply_to_message_id ( msg. id )
281+ . parse_mode ( MarkdownV2 )
282+ . await ?;
283+
284+ dialogue. update ( State :: DeleteConfirm { comment_id } ) . await ?;
285+ Ok ( ( ) )
286+ }
287+
200288/// 直接评价命令处理函数
201289async fn comment_command (
202290 bot : Bot ,
@@ -993,6 +1081,55 @@ async fn publish_comment(
9931081 Ok ( ( ) )
9941082}
9951083
1084+ /// 删除评价确认处理
1085+ async fn confirm_delete_comment (
1086+ bot : Bot ,
1087+ dialogue : MyDialogue ,
1088+ comment_id : String ,
1089+ msg : Message ,
1090+ ) -> HandlerResult {
1091+ let text = match msg. text ( ) {
1092+ Some ( t) => t. trim ( ) ,
1093+ None => {
1094+ bot. send_message (
1095+ msg. chat . id ,
1096+ "未识别的输入。请回复「确认删除」,或使用 /cancel 取消操作。" ,
1097+ )
1098+ . await ?;
1099+ return Ok ( ( ) ) ;
1100+ }
1101+ } ;
1102+
1103+ if text != "确认删除" {
1104+ bot. send_message (
1105+ msg. chat . id ,
1106+ "如需删除,请回复「确认删除」。若不再需要删除,可使用 /cancel 结束操作。" ,
1107+ )
1108+ . await ?;
1109+ return Ok ( ( ) ) ;
1110+ }
1111+
1112+ match SAFC_DB . delete_comment ( & comment_id) ? {
1113+ true => {
1114+ bot. send_message (
1115+ msg. chat . id ,
1116+ format ! ( "评价 `{}` 已删除。感谢您的更新!" , comment_id) ,
1117+ )
1118+ . await ?;
1119+ }
1120+ false => {
1121+ bot. send_message (
1122+ msg. chat . id ,
1123+ "评价不存在或已被删除。" ,
1124+ )
1125+ . await ?;
1126+ }
1127+ }
1128+
1129+ dialogue. update ( State :: Start ) . await ?;
1130+ Ok ( ( ) )
1131+ }
1132+
9961133/// 一维向量转换为 n 列纵向键盘
9971134fn convert_to_n_columns_keyboard ( data : Vec < String > , n : usize ) -> Vec < Vec < KeyboardButton > > {
9981135 data. chunks ( n)
0 commit comments