@@ -469,3 +469,264 @@ public class MyComponent {
469469有关事件的更多内容参考
470470<a href =" onebot11-event.md " /> 。
471471</warning >
472+
473+
474+ ## 外部事件
475+
476+ ` OneBotBot ` 提供了 ` push(String) ` 来允许直接从外部推送一个原始的事件字符串。
477+
478+ <tabs group =" code " >
479+ <tab title =" Kotlin " group-key =" Kotlin " >
480+
481+ ``` Kotlin
482+ val json = """
483+ {
484+ "time": 1515204254,
485+ "self_id": 10001000,
486+ "post_type": "message",
487+ "message_type": "private",
488+ "sub_type": "friend",
489+ "message_id": 12,
490+ "user_id": 12345678,
491+ "message": "你好~",
492+ "raw_message": "你好~",
493+ "font": 456,
494+ "sender": {
495+ "nickname": "小不点",
496+ "sex": "male",
497+ "age": 18
498+ }
499+ }
500+ """
501+
502+ bot.push(json).collect()
503+ ```
504+
505+ </tab >
506+ <tab title =" Java " group-key =" Java " >
507+
508+ ``` Java
509+ var json = " " "
510+ {
511+ " time" : 1515204254,
512+ " self_id" : 10001000,
513+ " post_type" : " message" ,
514+ " message_type" : " private " ,
515+ " sub_type" : " friend" ,
516+ " message_id" : 12,
517+ " user_id" : 12345678,
518+ " message" : " 你好~" ,
519+ " raw_message" : " 你好~" ,
520+ " font" : 456,
521+ " sender" : {
522+ " nickname" : " 小不点" ,
523+ " sex" : " male" ,
524+ " age" : 18
525+ }
526+ }
527+ " " "
528+
529+ // 推送并在异步中处理
530+ bot. pushAndLaunch(json);
531+ ```
532+
533+ 由于 ` bot.push ` 返回的结果是 ` Flow ` , 因此 Java 中想要直接使用它会比较困难。
534+ 你可以先通过 ` Collectables.valueOf(flow) ` 将其转化为 ` Collectable ` (与关系对象相关API的结果类型一样),
535+ 然后再做进一步操作。
536+
537+
538+ ``` java
539+ var collectable = Collectables . valueOf(flow);
540+ // 使用 collectAsync 异步遍历
541+ // 或者 Collectables 中提供的各种辅助API
542+ // 或者 transform 转化为其他的类型,比如响应式的 Flux
543+ ```
544+
545+ </tab >
546+ </tabs >
547+
548+ > 示例JSON来自
549+ > https://github.com/botuniverse/onebot-11/blob/master/communication/http-post.md 。
550+
551+ 这可以让你能够使用** 反向事件推送** 来接收事件,比如通过接收来自 HTTP 的事件推送请求。
552+
553+ 简单示例:
554+
555+ <tabs >
556+ <tab title =" Ktor " >
557+
558+ ``` kotlin
559+ suspend fun main () {
560+ val application = launchSimpleApplication {
561+ useOneBot11()
562+ }
563+ // 注册事件省略...
564+
565+ // 注册bot并启动
566+ val bot = application.oneBot11Bots {
567+ register {
568+ // 内容省略
569+ }.apply { start() }
570+ }
571+
572+ // 启动一个Ktor Server
573+ embeddedServer(Netty , port = 5959 , module = { serverModule(bot) })
574+ .start(wait = true )
575+ }
576+
577+ fun io.ktor.server.application.Application.serverModule (bot : OneBotBot ) {
578+ routing {
579+ post(" /event" ) {
580+ // 收到事件,推送并在异步中处理
581+ // 你也可以选择直接 push(body).collect(),
582+ // 直到事件被完全处理后在返回
583+ val body = call.receiveText()
584+ bot.pushAndLaunch(body)
585+
586+ // 响应一个默认的空JSON结果
587+ call.response.header(HttpHeaders .ContentType , " application/json" )
588+ call.respond(" {}" )
589+ }
590+ }
591+ }
592+ ```
593+
594+ </tab >
595+ <tab title =" Spring Boot Web " >
596+
597+ ``` java
598+ @RestController
599+ public class MyController {
600+ private final Application application;
601+
602+ // 一个简单的返回值类型,假设始终返回空JSON {}
603+ public record Result () {
604+ }
605+
606+ private static final Result OK = new Result ();
607+
608+ public MyController (Application application ) {
609+ this . application = application;
610+ }
611+
612+ /**
613+ * 通过 /xxx/event 接收事件,
614+ * xxx 为你bot配置的 uniqueBotId
615+ */
616+ @PostMapping (" /{botId}/event" )
617+ public Result onEvent (@PathVariable String botId , @RequestBody String body ) {
618+ for (var botManager : application. getBotManagers()) {
619+ if (botManager instanceof OneBotBotManager obManager) {
620+ // 找到这个bot
621+ var bot = obManager. find(Identifies . of(botId));
622+ // 如果有就推送这个事件并退出寻找
623+ if (bot != null ) {
624+ // 推送事件并在异步中处理
625+ // 你也可以参考上面有关 Flux 和 Collectable 的说明
626+ // 来阻塞地等待事件处理完成后再返回
627+ bot. pushAndLaunch(body);
628+ break ;
629+ }
630+ }
631+ }
632+
633+ return OK ;
634+ }
635+ }
636+ ```
637+
638+ </tab >
639+ <tab title =" Spring Boot WebFlux " >
640+
641+ <tabs >
642+ <tab title =" 异步处理 " >
643+
644+ 如果选择直接异步处理,那么其实跟 Spring Boot Web 的情况下没什么太大区别。
645+
646+ ``` java
647+ @RestController
648+ public class MyController {
649+ private final Application application;
650+
651+ public record Result () {
652+ }
653+
654+ private static final Result OK = new Result ();
655+
656+ public MyController (Application application ) {
657+ this . application = application;
658+ }
659+
660+ /**
661+ * 通过 /xxx/event 接收事件,
662+ * xxx 为你bot配置的 uniqueBotId
663+ */
664+ @PostMapping (" /{botId}/event" )
665+ public Mono<Result > onEvent (@PathVariable String botId , @RequestBody String body ) {
666+ for (var botManager : application. getBotManagers()) {
667+ if (botManager instanceof OneBotBotManager obManager) {
668+ // 找到这个bot
669+ var bot = obManager. find(Identifies . of(botId));
670+ // 如果有就推送这个事件并退出寻找
671+ if (bot != null ) {
672+ bot. pushAndLaunch(body);
673+ break ;
674+ }
675+ }
676+ }
677+
678+ return Mono . just(OK );
679+ }
680+ }
681+ ```
682+
683+ </tab >
684+ <tab title =" 顺序响应式处理 " >
685+
686+ ``` java
687+ @RestController
688+ public class MyController {
689+ private final Application application;
690+
691+ public record Result () {
692+ }
693+
694+ private static final Result OK = new Result ();
695+
696+ public MyController (Application application ) {
697+ this . application = application;
698+ }
699+
700+ /**
701+ * 通过 /xxx/event 接收事件,
702+ * xxx 为你bot配置的 uniqueBotId
703+ */
704+ @PostMapping (" /{botId}/event" )
705+ public Mono<Result > onEvent (@PathVariable String botId , @RequestBody String body ) {
706+ for (var botManager : application. getBotManagers()) {
707+ if (botManager instanceof OneBotBotManager obManager) {
708+ // 找到这个bot
709+ var bot = obManager. find(Identifies . of(botId));
710+ // 如果有就推送这个事件并退出寻找
711+ if (bot != null ) {
712+ final var flow = bot. push(body);
713+ // 将 flow 转为 reactor 的 Flux
714+ // 需要添加依赖 [[[kotlinx-coroutines-reactor|https://github.com/Kotlin/kotlinx.coroutines/tree/master/reactive]]]
715+ return ReactorFlowKt
716+ .asFlux(flow)
717+ .then(Mono . just(OK ));
718+ }
719+ }
720+ }
721+
722+ // 没找到,直接返回
723+ return Mono . just(OK );
724+ }
725+ }
726+ ```
727+
728+ </tab >
729+ </tabs >
730+
731+ </tab >
732+ </tabs >
0 commit comments