Module: FeishuApi

Defined in:
lib/feishu-api.rb,
lib/feishu-api/api.rb,
lib/feishu-api/config.rb,
lib/feishu-api/engine.rb,
lib/feishu-api/version.rb

Defined Under Namespace

Classes: Config, Engine

Constant Summary collapse

API_HOST =
'https://open.feishu.cn/open-apis'
API_TENANT_ACCESS_TOKEN =
'/auth/v3/tenant_access_token/internal'
API_APP_ACCESS_TOKEN =
'/auth/v3/app_access_token/internal'
API_SEND_MESSAGES =
'/im/v1/messages'
API_CUSTOM_BOT_SEND =
'/bot/v2/hook'
API_UPLOAD_IMAGE =
'/im/v1/images'
API_UPLOAD_FILES =
'/im/v1/files'
API_CHATS =
'/im/v1/chats'
API_RESERVES =
'/vc/v1/reserves'
API_MEETINGS =
'/vc/v1/meetings'
VERSION =
'0.3.0'

Class Method Summary collapse

Class Method Details

.add_group_managers(chat_id, manager_ids) ⇒ Object

指定群管理员



318
319
320
321
# File 'lib/feishu-api/api.rb', line 318

def add_group_managers(chat_id, manager_ids)
  post_with_token("#{API_CHATS}/#{chat_id}/managers/add_managers",
                  { manager_ids: }.to_json, { 'Content-Type' => 'application/json' })
end

.add_group_member(chat_id, id_list) ⇒ Object

将用户或机器人拉入群聊



295
296
297
298
# File 'lib/feishu-api/api.rb', line 295

def add_group_member(chat_id, id_list)
  post_with_token("#{API_CHATS}/#{chat_id}/members",
                  { id_list: }.to_json, { 'Content-Type' => 'application/json', 'Accept' => 'application/json' })
end

.add_message_reactions(message_id, emoji_type) ⇒ Object

添加消息表情回复



215
216
217
218
219
220
221
222
# File 'lib/feishu-api/api.rb', line 215

def add_message_reactions(message_id, emoji_type)
  post_with_token("#{API_SEND_MESSAGES}/#{message_id}/reactions",
                  {
                    reaction_type: {
                      emoji_type: emoji_type.to_s
                    }
                  }.to_json, { 'Content-Type' => 'application/json' })
end

.api(interface) ⇒ Object



17
18
19
# File 'lib/feishu-api/api.rb', line 17

def api(interface)
  "#{API_HOST}#{interface}"
end

.app_access_tokenObject



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/feishu-api/api.rb', line 114

def app_access_token
  Rails.cache.fetch('app_access_token', expires_in: 2.hours) do
    res = post(API_APP_ACCESS_TOKEN, {
                 app_id: Config.app_id,
                 app_secret: Config.app_secret
               })
    return nil if res.code != 200

    body = JSON.parse(res.body)
    token = (body['code']).zero? ? body['app_access_token'] : nil
    token
  end
end

.bot_chat_listObject

获取用户或者机器人所在群列表



235
236
237
# File 'lib/feishu-api/api.rb', line 235

def bot_chat_list
  get_with_token(API_CHATS.to_s)
end

.check_reader(message_id) ⇒ Object

查询消息已读信息



183
184
185
# File 'lib/feishu-api/api.rb', line 183

def check_reader(message_id)
  get_with_token("#{API_SEND_MESSAGES}/#{message_id}/read_users?user_id_type=open_id")
end

.configure(&block) ⇒ Object



14
15
16
# File 'lib/feishu-api.rb', line 14

def configure(&block)
  Config.configure(&block)
end

.create_group(name) ⇒ Object

创建群



274
275
276
277
# File 'lib/feishu-api/api.rb', line 274

def create_group(name)
  post_with_token(API_CHATS.to_s,
                  { name: name.to_s })
end

.custom_robot_send(data, hook_id, secret = '') ⇒ Object

自定义机器人接口 发送消息



358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/feishu-api/api.rb', line 358

def custom_robot_send(data, hook_id, secret = '')
  if secret != ''
    timestamp = Time.now.to_i.to_s
    string_to_sign = "#{timestamp}\n#{secret}"
    hmac_code = OpenSSL::HMAC.digest('sha256', string_to_sign, "")
    sign = Base64.encode64(hmac_code).strip
    data = {timestamp: , sign: }.merge(data)
  end
  res = post("#{API_CUSTOM_BOT_SEND}/#{hook_id}", data)
  return nil if res.code != 200

  JSON.parse(res.body)
end

.custom_robot_send_card(title = '标题', theme = 'blue', elements = [], hook_id = '', secret = '') ⇒ Object

自定义机器人接口 发送卡片消息



491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/feishu-api/api.rb', line 491

def custom_robot_send_card(title = '标题', theme = 'blue', elements = [], hook_id = '', secret = '')
  custom_robot_send({
                      msg_type: 'interactive',
                      card: {
                        config: {
                          wide_screen_mode: true
                        },
                        header: {
                          title: {
                            tag: 'plain_text',
                            content: title
                          },
                          template: theme
                        },
                        elements: 
                      }
                    }, hook_id, secret)
end

.custom_robot_send_text(text, hook_id) ⇒ Object

自定义机器人接口 发送文本消息



469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/feishu-api/api.rb', line 469

def custom_robot_send_text(text, hook_id)
  custom_robot_send({
                      msg_type: 'post',
                      content: {
                        post: {
                          'zh-CN': {
                            title: '',
                            content: [
                              [
                                {
                                  tag: 'text',
                                  text: 
                                }
                              ]
                            ]
                          }
                        }
                      }
                    }, hook_id)
end

.delete_group_managers(chat_id, manager_ids) ⇒ Object

删除群管理员



324
325
326
327
# File 'lib/feishu-api/api.rb', line 324

def delete_group_managers(chat_id, manager_ids)
  post_with_token("#{API_CHATS}/#{chat_id}/managers/delete_managers",
                  { manager_ids: }.to_json, { 'Content-Type' => 'application/json' })
end

.delete_group_member(chat_id, id_list) ⇒ Object

将用户或机器人移出群聊



301
302
303
304
# File 'lib/feishu-api/api.rb', line 301

def delete_group_member(chat_id, id_list)
  delete_with_token("#{API_CHATS}/#{chat_id}/members",
                    { id_list: }.to_json, { 'Content-Type' => 'application/json', 'Accept' => 'application/json' })
end

.delete_group_top_notice(chat_id) ⇒ Object

撤销群置顶



269
270
271
# File 'lib/feishu-api/api.rb', line 269

def delete_group_top_notice(chat_id)
  delete_with_token("#{API_CHATS}/#{chat_id}/top_notice/delete_top_notice")
end

.delete_message_reactions(message_id) ⇒ Object

删除消息表情回复



230
231
232
# File 'lib/feishu-api/api.rb', line 230

def delete_message_reactions(message_id)
  delete_with_token("#{API_SEND_MESSAGES}/#{message_id}/reactions")
end

.delete_reserve(token, reserve_id) ⇒ Object

删除预约



442
443
444
# File 'lib/feishu-api/api.rb', line 442

def delete_reserve(token, reserve_id)
  delete_with_user_token("#{API_RESERVES}/#{reserve_id}", token)
end

.delete_with_token(url, data = {}, headers = {}, timeout = 30) ⇒ Object



71
72
73
74
75
76
# File 'lib/feishu-api/api.rb', line 71

def delete_with_token(url, data = {}, headers = {}, timeout = 30)
  HTTParty.delete(api(url),
                  body: data,
                  headers: { Authorization: "Bearer #{tenant_access_token}" }.merge(headers),
                  timeout: )
end

.delete_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30) ⇒ Object



78
79
80
81
82
83
# File 'lib/feishu-api/api.rb', line 78

def delete_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30)
  HTTParty.delete(api(url),
                  body: data,
                  headers: { Authorization: "Bearer #{user_access_token}" }.merge(headers),
                  timeout: )
end

.dissolve_group(chat_id) ⇒ Object

解散群



290
291
292
# File 'lib/feishu-api/api.rb', line 290

def dissolve_group(chat_id)
  delete_with_token("#{API_CHATS}/#{chat_id}")
end

.download_file(file_key) ⇒ Object

下载文件



167
168
169
170
# File 'lib/feishu-api/api.rb', line 167

def download_file(file_key)
  HTTParty.get("#{API_HOST}#{API_UPLOAD_FILES}/#{file_key}",
               headers: { Authorization: "Bearer #{tenant_access_token}" })
end

.download_image(image_key) ⇒ Object

下载图片



155
156
157
# File 'lib/feishu-api/api.rb', line 155

def download_image(image_key)
  get_with_token("#{API_UPLOAD_IMAGE}/#{image_key}")
end

.get_active_meeting(token, reserve_id) ⇒ Object

获取活跃会议



452
453
454
# File 'lib/feishu-api/api.rb', line 452

def get_active_meeting(token, reserve_id)
  get_with_user_token("#{API_RESERVES}/#{reserve_id}/get_active_meeting", token)
end

.get_chat_messages(container_id) ⇒ Object

获取会话(历史)消息



199
200
201
# File 'lib/feishu-api/api.rb', line 199

def get_chat_messages(container_id)
  get_with_token("#{API_SEND_MESSAGES}?container_id_type=chat&container_id=#{container_id}")
end

.get_group_announcement(chat_id) ⇒ Object

获取群公告信息



335
336
337
# File 'lib/feishu-api/api.rb', line 335

def get_group_announcement(chat_id)
  get_with_token("#{API_CHATS}/#{chat_id}/announcement")
end

.get_group_info(chat_id) ⇒ Object

获取群信息



280
281
282
# File 'lib/feishu-api/api.rb', line 280

def get_group_info(chat_id)
  get_with_token("#{API_CHATS}/#{chat_id}")
end

.get_group_members(chat_id) ⇒ Object

获取群成员列表



330
331
332
# File 'lib/feishu-api/api.rb', line 330

def get_group_members(chat_id)
  get_with_token("#{API_CHATS}/#{chat_id}/members")
end

.get_list_by_no(meeting_number, start_time, end_time) ⇒ Object

获取与会议号相关联的会议列表



462
463
464
465
466
# File 'lib/feishu-api/api.rb', line 462

def get_list_by_no(meeting_number, start_time, end_time)
  end_time_unix = Time.strptime(end_time, '%Y-%m-%d %H:%M:%S').to_i
  start_time_unix = Time.strptime(start_time, '%Y-%m-%d %H:%M:%S').to_i
  get_with_token("#{API_MEETINGS}/list_by_no?end_time=#{end_time_unix}&start_time=#{start_time_unix}&meeting_no=#{meeting_number}")
end

.get_meeting_info(meeting_id) ⇒ Object

获取会议详情



457
458
459
# File 'lib/feishu-api/api.rb', line 457

def get_meeting_info(meeting_id)
  get_with_token("#{API_MEETINGS}/#{meeting_id}")
end

.get_member_permission(chat_id) ⇒ Object

灵缇高级管家 chat_id:oc_31e9100a2673814ecba937f0772b8ebc 获取群成员发言权限



246
247
248
# File 'lib/feishu-api/api.rb', line 246

def get_member_permission(chat_id)
  get_with_token("#{API_CHATS}/#{chat_id}/moderation")
end

.get_message_content(message_id) ⇒ Object

获取指定消息的内容



204
205
206
# File 'lib/feishu-api/api.rb', line 204

def get_message_content(message_id)
  get_with_token("#{API_SEND_MESSAGES}/#{message_id}")
end

.get_message_reactions(message_id) ⇒ Object

获取消息表情回复



225
226
227
# File 'lib/feishu-api/api.rb', line 225

def get_message_reactions(message_id)
  get_with_token("#{API_SEND_MESSAGES}/#{message_id}/reactions")
end

.get_reserve_info(token, reserve_id) ⇒ Object

获取预约



447
448
449
# File 'lib/feishu-api/api.rb', line 447

def get_reserve_info(token, reserve_id)
  get_with_user_token("#{API_RESERVES}/#{reserve_id}", token)
end

.get_with_token(url, data = {}, headers = {}, timeout = 30) ⇒ Object



43
44
45
46
47
48
# File 'lib/feishu-api/api.rb', line 43

def get_with_token(url, data = {}, headers = {}, timeout = 30)
  HTTParty.get(api(url),
               body: data,
               headers: { Authorization: "Bearer #{tenant_access_token}" }.merge(headers),
               timeout: )
end

.get_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30) ⇒ Object



50
51
52
53
54
55
# File 'lib/feishu-api/api.rb', line 50

def get_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30)
  HTTParty.get(api(url),
               body: data,
               headers: { Authorization: "Bearer #{user_access_token}" }.merge(headers),
               timeout: )
end

.join_group(chat_id) ⇒ Object

用户或机器人主动加入群聊需要打开群设置:公开



308
309
310
# File 'lib/feishu-api/api.rb', line 308

def join_group(chat_id)
  patch_with_token("#{API_CHATS}/#{chat_id}/members/me_join")
end

.member_is_in_chat(chat_id) ⇒ Object

判断用户或机器人是否在群里



313
314
315
# File 'lib/feishu-api/api.rb', line 313

def member_is_in_chat(chat_id)
  get_with_token("#{API_CHATS}/#{chat_id}/members/is_in_chat")
end

.patch_with_token(url, data = {}, headers = {}, timeout = 30) ⇒ Object



85
86
87
88
89
90
# File 'lib/feishu-api/api.rb', line 85

def patch_with_token(url, data = {}, headers = {}, timeout = 30)
  HTTParty.patch(api(url),
                 body: data,
                 headers: { Authorization: "Bearer #{tenant_access_token}" }.merge(headers),
                 timeout: )
end

.patch_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30) ⇒ Object



92
93
94
95
96
97
# File 'lib/feishu-api/api.rb', line 92

def patch_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30)
  HTTParty.patch(api(url),
                 body: data,
                 headers: { Authorization: "Bearer #{user_access_token}" }.merge(headers),
                 timeout: )
end

.post(url, data, headers = {}, timeout = 30) ⇒ Object



21
22
23
24
25
26
27
# File 'lib/feishu-api/api.rb', line 21

def post(url, data, headers = {}, timeout = 30)
  HTTParty.post(api(url),
                body: data.to_json,
                headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }.merge(headers),
                timeout: ,
                verify: false)
end

.post_with_token(url, data, headers = {}, timeout = 30) ⇒ Object



29
30
31
32
33
34
# File 'lib/feishu-api/api.rb', line 29

def post_with_token(url, data, headers = {}, timeout = 30)
  HTTParty.post(api(url),
                body: data,
                headers: { Authorization: "Bearer #{tenant_access_token}" }.merge(headers),
                timeout: )
end

.post_with_user_token(url, user_access_token, data, headers = {}, timeout = 30) ⇒ Object



36
37
38
39
40
41
# File 'lib/feishu-api/api.rb', line 36

def post_with_user_token(url, user_access_token, data, headers = {}, timeout = 30)
  HTTParty.post(api(url),
                body: data,
                headers: { Authorization: "Bearer #{user_access_token}" }.merge(headers),
                timeout: )
end

.put_with_token(url, data = {}, headers = {}, timeout = 30) ⇒ Object



57
58
59
60
61
62
# File 'lib/feishu-api/api.rb', line 57

def put_with_token(url, data = {}, headers = {}, timeout = 30)
  HTTParty.put(api(url),
               body: data,
               headers: { Authorization: "Bearer #{tenant_access_token}" }.merge(headers),
               timeout: )
end

.put_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30) ⇒ Object



64
65
66
67
68
69
# File 'lib/feishu-api/api.rb', line 64

def put_with_user_token(url, user_access_token, data = {}, headers = {}, timeout = 30)
  HTTParty.put(api(url),
               body: data,
               headers: { Authorization: "Bearer #{user_access_token}" }.merge(headers),
               timeout: )
end

.reply_message(message_id) ⇒ Object

回复消息



193
194
195
196
# File 'lib/feishu-api/api.rb', line 193

def reply_message(message_id)
  post_with_token("#{API_SEND_MESSAGES}/#{message_id}/reply",
                  { content: '{"text":" test content"}', msg_type: 'text' })
end

.reserve_meeting(token, end_time, check_list, topic) ⇒ Object

预约会议



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/feishu-api/api.rb', line 373

def reserve_meeting(token, end_time, check_list, topic)
  post_with_user_token("#{API_RESERVES}/apply", token, {
    end_time: Time.strptime(end_time, '%Y-%m-%d %H:%M:%S').to_i,
    meeting_settings: {
      topic: topic,
      action_permissions: [
        {
          permission: 1,
          permission_checkers: [
            {
              check_field: 1,
              check_mode: 1,
              check_list: 
            }
          ]
        }
      ],
      meeting_initial_type: 1,
      call_setting: {
        callee: {
          id: check_list[0],
          user_type: 1,
          pstn_sip_info: {
            nickname: 'dodo',
            main_address: '+86-02187654321'
          }
        }
      },
      auto_record: true
    }
  }.to_json, { 'Content-Type' => 'application/json' })
end

.search_chat_list(query) ⇒ Object

搜索对用户或机器人可见的群列表



240
241
242
# File 'lib/feishu-api/api.rb', line 240

def search_chat_list(query)
  get_with_token("#{API_CHATS}/search?query=#{query}")
end

.send_file_by_group(receive_id, file_key) ⇒ Object

发文件消息到指定群聊



173
174
175
# File 'lib/feishu-api/api.rb', line 173

def send_file_by_group(receive_id, file_key)
  send_message_by_group(receive_id, 'file', JSON.generate({ file_key: }))
end

.send_image_by_group(receive_id, image_key) ⇒ Object

发图片消息到指定群聊



188
189
190
# File 'lib/feishu-api/api.rb', line 188

def send_image_by_group(receive_id, image_key)
  send_message_by_group(receive_id, 'image', JSON.generate({ image_key: }))
end

.send_message(receive_type, receive_id, msg_type, content) ⇒ Object

发送消息



129
130
131
132
133
134
135
136
# File 'lib/feishu-api/api.rb', line 129

def send_message(receive_type, receive_id, msg_type, content)
  res = post_with_token("#{API_SEND_MESSAGES}?receive_id_type=#{receive_type}",
                        { receive_id: , msg_type: , content: })
  # p res
  return nil if res.code != 200

  JSON.parse(res.body)
end

.send_message_by_email(receive_id, msg_type, content) ⇒ Object

通过邮箱识别用户, 发消息到指定用户



353
354
355
# File 'lib/feishu-api/api.rb', line 353

def send_message_by_email(receive_id, msg_type, content)
  send_message('email', receive_id, msg_type, content)
end

.send_message_by_group(receive_id, msg_type, content) ⇒ Object

发消息到指定群聊



139
140
141
# File 'lib/feishu-api/api.rb', line 139

def send_message_by_group(receive_id, msg_type, content)
  send_message('chat_id', receive_id, msg_type, content)
end

.send_text_by_group(receive_id, text) ⇒ Object

发文本消息到指定群聊



144
145
146
# File 'lib/feishu-api/api.rb', line 144

def send_text_by_group(receive_id, text)
  send_message_by_group(receive_id, 'text', JSON.generate({ text: }))
end

.send_urgent_app_message(message_id, user_id) ⇒ Object

发送应用内加急消息 (需要相关权限)



209
210
211
212
# File 'lib/feishu-api/api.rb', line 209

def send_urgent_app_message(message_id, user_id)
  patch_with_token("#{API_SEND_MESSAGES}/#{message_id}/urgent_app?user_id_type=user_id",
                   { user_id_list: [user_id] })
end

.tenant_access_tokenObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/feishu-api/api.rb', line 99

def tenant_access_token
  Rails.cache.fetch('tenant_access_token', expires_in: 2.hours) do
    res = post(API_TENANT_ACCESS_TOKEN, {
                 app_id: Config.app_id,
                 app_secret: Config.app_secret
               })

    return nil if res.code != 200

    body = JSON.parse(res.body)
    token = (body['code']).zero? ? body['tenant_access_token'] : nil
    token
  end
end

.update_group_announcement(chat_id) ⇒ Object

更新群公告信息rubocop:disable all



341
342
343
344
345
346
347
348
349
# File 'lib/feishu-api/api.rb', line 341

def update_group_announcement(chat_id)
  patch_with_token("#{API_CHATS}/#{chat_id}/announcement",
    {
      "revision": "0",
      "requests": [
        "{\"requestType\":\"UpdateTitleRequestType\",\"updateTitleRequest\":{\"payload\":\"{\\\"elements\\\":[{\\\"type\\\":\\\"textRun\\\",\\\"textRun\\\":{\\\"text\\\":\\\"Updated Document Title\\\",\\\"style\\\":{}}}],\\\"style\\\":{}}\"}}"
      ]
    }.to_json, { 'Content-Type' => 'application/json'})
end

.update_group_info(chat_id, description) ⇒ Object

更新群信息



285
286
287
# File 'lib/feishu-api/api.rb', line 285

def update_group_info(chat_id, description)
  put_with_token("#{API_CHATS}/#{chat_id}", { description: description.to_s })
end

.update_group_top_notice(chat_id, message_id) ⇒ Object

更新群置顶



256
257
258
259
260
261
262
263
264
265
266
# File 'lib/feishu-api/api.rb', line 256

def update_group_top_notice(chat_id, message_id)
  post_with_token("#{API_CHATS}/#{chat_id}/top_notice/put_top_notice",
                  {
                    chat_top_notice: [
                      {
                        action_type: '1',
                        message_id: message_id.to_s
                      }
                    ]
                  }.to_json, { 'Content-Type' => 'application/json', 'Accept' => 'application/json' })
end

.update_member_permission(chat_id) ⇒ Object

更新群成员发言权限



251
252
253
# File 'lib/feishu-api/api.rb', line 251

def update_member_permission(chat_id)
  put_with_token("#{API_CHATS}/#{chat_id}/moderation")
end

.update_reserve(token, reserve_id, topic, check_list, end_time) ⇒ Object

更新预约



407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/feishu-api/api.rb', line 407

def update_reserve(token, reserve_id, topic, check_list, end_time)
  put_with_user_token("#{API_RESERVES}/#{reserve_id}", token,
                      {
                        end_time: Time.strptime(end_time, '%Y-%m-%d %H:%M:%S').to_i,
                        meeting_settings: {
                          topic: topic,
                          action_permissions: [
                            {
                              permission: 1,
                              permission_checkers: [
                                {
                                  check_field: 1,
                                  check_mode: 1,
                                  check_list: 
                                }
                              ]
                            }
                          ],
                          meeting_initial_type: 1,
                          call_setting: {
                            callee: {
                              id: check_list[0],
                              user_type: 1,
                              pstn_sip_info: {
                                nickname: 'dodo',
                                main_address: '+86-02187654321'
                              }
                            }
                          },
                          auto_record: true
                        }
                      }.to_json, { 'Content-Type' => 'application/json' })
end

.upload_file(path, file_type) ⇒ Object

上传文件



160
161
162
163
164
# File 'lib/feishu-api/api.rb', line 160

def upload_file(path, file_type)
  post_with_token(API_UPLOAD_FILES.to_s,
                  { file_type: file_type, file_name: File.basename(path), file: File.new(path) },
                  { 'Content-Type' => 'multipart/formdata' })
end

.upload_image(path) ⇒ Object

上传图片



149
150
151
152
# File 'lib/feishu-api/api.rb', line 149

def upload_image(path)
  post_with_token(API_UPLOAD_IMAGE.to_s, { image_type: 'message', image: File.new(path) },
                  { 'Content-Type' => 'multipart/formdata', 'Accept' => 'application/json' })
end

.withdraw_message(message_id) ⇒ Object

撤回消息



178
179
180
# File 'lib/feishu-api/api.rb', line 178

def withdraw_message(message_id)
  delete_with_token("#{API_SEND_MESSAGES}/#{message_id}")
end