开发指南/快速入门/快速开发机器人/示例代码介绍
# 示例代码介绍
本教程代码完成了 [接收消息](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/events/receive) 类型的事件定义和处理逻辑，更多事件类型介绍请参考 [事件列表](https://open.larksuite.com/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list)。
本节介绍如何基于现有代码，完成不同的事件订阅处理，或者开发更多的机器人能力。

## 代码结构

以下为目录结构与部分核心代码文件：

```
|_robot_quick_start
     |_python
         |_.env		   -- 全局默认配置文件，主要存储App ID和App Secret等
         |_event.py          -- 事件服务：用于注册事件、定义事件
         |_api.py            -- API 服务：提供消息 API 调用能力
         |_decrypt.py        -- 解密服务：提供事件体解密能力
         |_server.py         -- 核心业务代码（main）
         |_utils.py          -- 工具服务：提供 dict 转 obj 的能力
         |_requirements.txt  -- 依赖配置文件
         |_README.md         -- 说明文件
````
## 代码流程

本示例作为应用服务端，需要处理请求 URL 验证和消息回调事件，具体处理流程如下图所示：

![](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/00936dc153b3cc5c246141ed626c340c_N5a5lPVGQm.png?height=1102&lazyload=true&maxWidth=750&width=1826)

## 事件订阅流程

通过事件订阅，可以满足应用及时响应Lark事件变更的需求。如果要使用事件订阅功能，需要先配置公网请求地址，并添加订阅事件。当事件发生时，Lark开放平台会以 HTTP POST 请求的方式将事件内容以 JSON 格式推送给请求地址。
更多介绍，参考[事件订阅](https://open.larksuite.com/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM)。

![image.png](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/79f1dd87f230ae668a03732ed0d740c1_puUuVy7Y2N.png?height=290&lazyload=true&maxWidth=700&width=2240)

## server.py 介绍

### 定义回调事件处理入口
**说明**：回调事件处理入口即 [Step 5](https://open.larksuite.com/document/home/develop-a-bot-in-5-minutes/coding) 中配置的公网请求网址 URL。
从事件管理器取出事件和对应的处理函数，将接收到的 http 请求转为 event 处理。

```
@app.route("/", methods=["POST"])
def callback_event_handler():
    # init callback instance and handle

event_handler, event = event_manager.get_handler_with_event(VERIFICATION_TOKEN, ENCRYPT_KEY)
    return event_handler(event)
```

### 注册事件处理函数

使用装饰器 `@event_manager.register("im.message.receive_v1")`，即可将函数注册为该类型事件的处理函数。
```
@event_manager.register("im.message.receive_v1")
def message_receive_event_handler(req_data: MessageReceiveEvent):
    sender_id = req_data.event.sender.sender_id
    message = req_data.event.message
    if message.message_type != "text":
        logging.warn("Other types of messages have not been processed yet")
        return jsonify()
        # get open_id and text_content

open_id = sender_id.open_id
    text_content = message.content
    # echo text message

message_api_client.send_text_with_open_id(open_id, text_content)
    return jsonify()
```

## event.py 介绍

### 定义具体类型的事件

```
class MessageReceiveEvent(Event):
    @staticmethod
    def event_type():
        return "im.message.receive_v1"
```

### 将定义好的事件加入事件列表（_event_list）

```
class EventManager(object):
    event_callback_map = dict()
    event_type_map = dict()
    _event_list = [MessageReceiveEvent, UrlVerificationEvent]
```

## api.py 介绍

### 发送消息

本教程实现了 [发送消息](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/create) 的能力，机器人发送任何类型的消息都可以基于 send 扩展。本教程在接收消息事件处理函数内使用了 `send_text_with_open_id`，实现了接收消息之后立刻回复消息的效果。
```
    def send_text_with_open_id(self, open_id, content):
        self.send("open_id", open_id, "text", content)
    def send(self, receive_id_type, receive_id, msg_type, content):
        # send message to user, implemented based on Lark open api capability. doc link: https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/create

self._authorize_tenant_access_token()
        url = "{}{}?receive_id_type={}".format(
            self._lark_host, MESSAGE_URI, receive_id_type
        )
        headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.tenant_access_token,
        }
        req_body = {
            "receive_id": receive_id,
            "content": content,
            "msg_type": msg_type,
        }
        resp = requests.post(url=url, headers=headers, json=req_body)
        MessageApiClient._check_error_response(resp)
```
