261 lines
8.5 KiB
Python
261 lines
8.5 KiB
Python
# -*- coding: utf-8 -*-
|
||
|
||
import logging
|
||
from odoo import api, models, _
|
||
|
||
|
||
from odoo.addons.wecom_api.api.wecom_abstract_api import ApiException # type: ignore
|
||
|
||
from datetime import datetime, timedelta
|
||
import pytz
|
||
import json
|
||
|
||
_logger = logging.getLogger(__name__)
|
||
|
||
|
||
class WeComMessageApi(models.AbstractModel):
|
||
_name = "wecom.message.api"
|
||
_description = "WeCom Message API"
|
||
|
||
def get_message_api(self, company):
|
||
""""""
|
||
wxapi = self.env["wecom.service_api"].InitServiceApi(
|
||
company, "message_secret", "message"
|
||
)
|
||
return wxapi
|
||
|
||
def send_by_api(self, message, api):
|
||
params = self.env["ir.config_parameter"].sudo()
|
||
debug = params.get_param("wecom.debug_enabled")
|
||
|
||
try:
|
||
del message["company"] # 删除message中的 company
|
||
|
||
response = api.httpCall(
|
||
self.env["wecom.service_api_list"].get_server_api_call("MESSAGE_SEND"),
|
||
message,
|
||
)
|
||
return response
|
||
|
||
except ApiException as ex:
|
||
if debug:
|
||
_logger.warning(_("Error sending message: %s") % (ex))
|
||
|
||
def build_message(
|
||
self,
|
||
msgtype,
|
||
toall=None,
|
||
touser=None,
|
||
toparty=None,
|
||
totag=None,
|
||
subject=None,
|
||
media_id=None,
|
||
description=None,
|
||
author_id=None,
|
||
body_html=None,
|
||
body_json=None,
|
||
body_markdown=None,
|
||
safe=None,
|
||
enable_id_trans=None,
|
||
enable_duplicate_check=None,
|
||
duplicate_check_interval=None,
|
||
company=None,
|
||
):
|
||
"""
|
||
构建消息
|
||
:msgtype: 消息类型,根据消息类型来构建消息内容
|
||
:toall: 发送给全体人员
|
||
:touser: 指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个)。
|
||
特殊情况:指定为”@all”,则向该企业应用的全部成员发送
|
||
:toparty: 指定接收消息的部门,部门ID列表,多个接收者用‘|’分隔,最多支持100个。
|
||
当touser为”@all”时忽略本参数
|
||
:totag: 指定接收消息的标签,标签ID列表,多个接收者用‘|’分隔,最多支持100个。
|
||
当touser为”@all”时忽略本参数
|
||
:subject: 标题 ,不同消息类型,长度限制不一样
|
||
:media_id: media_id, 可以通过素材管理接口获得
|
||
:body_html: 图文消息的内容,支持html标签,不超过666 K个字节,仅用于图文消息(mpnews)
|
||
:body_json: 非图文消息的内容,不同消息类型,长度限制不一样
|
||
:safe: 表示是否是保密消息,0表示可对外分享,1表示不能分享且内容显示水印,默认为0
|
||
:enable_id_trans: 表示是否开启id转译,0表示否,1表示是,默认0。仅第三方应用需要用到,企业自建应用可以忽略。
|
||
:enable_duplicate_check: Indicates whether to enable duplicate message checking. 0 indicates no, 1 indicates yes. The default is 0
|
||
:duplicate_check_interval: Indicates whether the message check is repeated. The default is 1800s and the maximum is no more than 4 hours
|
||
|
||
"""
|
||
if not company:
|
||
company = self.env.company
|
||
|
||
messages_content = self.get_messages_content(
|
||
msgtype,
|
||
description,
|
||
author_id,
|
||
body_html,
|
||
body_json,
|
||
body_markdown,
|
||
subject,
|
||
media_id,
|
||
)
|
||
messages_options = self.get_messages_options(
|
||
msgtype,
|
||
safe,
|
||
enable_id_trans,
|
||
enable_duplicate_check,
|
||
duplicate_check_interval,
|
||
)
|
||
|
||
messages = {
|
||
"touser": "@all" if toall else touser,
|
||
"toparty": "" if toall else toparty,
|
||
"totag": "" if toall else totag,
|
||
"msgtype": msgtype,
|
||
"agentid": company.message_agentid,
|
||
"company": company,
|
||
}
|
||
messages.update(messages_content)
|
||
messages.update(messages_options)
|
||
return messages
|
||
|
||
@api.model
|
||
def send_message(self, message):
|
||
"""
|
||
发送一条企业微信消息 到多个人员
|
||
"""
|
||
return self.send_by_api(message)
|
||
|
||
@api.model
|
||
def _send_message_batch(self, messages):
|
||
"""
|
||
批量模式发送企业微信消息
|
||
"""
|
||
params = {
|
||
"messages": messages,
|
||
}
|
||
return self._wecom_message_send_api(params)
|
||
|
||
def get_messages_content(
|
||
self,
|
||
msgtype,
|
||
description=None,
|
||
author_id=None,
|
||
body_html=None,
|
||
body_json=None,
|
||
body_markdown=None,
|
||
subject=None,
|
||
media_id=None,
|
||
):
|
||
# material_info = (
|
||
# self.env["wecom.material"].sudo().browse(int(media_id)).read(["name"])
|
||
# )
|
||
|
||
messages_content = {}
|
||
if msgtype == "text":
|
||
# 文本消息
|
||
messages_content = {
|
||
"text": body_json,
|
||
}
|
||
elif msgtype == "mpnews":
|
||
# 图文消息(mpnews)
|
||
material = (
|
||
self.sudo()
|
||
.env["wecom.material"]
|
||
.search(
|
||
[
|
||
("id", "=", media_id),
|
||
],
|
||
limit=1,
|
||
)
|
||
)
|
||
# material_media_id = self.check_material_file_expiration(material)
|
||
messages_content = {
|
||
"mpnews": {
|
||
"articles": [
|
||
{
|
||
"title": subject,
|
||
"thumb_media_id": material._check_material_file_expiration(),
|
||
"author": author_id.display_name,
|
||
"content": body_html,
|
||
"digest": description,
|
||
}
|
||
]
|
||
},
|
||
}
|
||
elif msgtype == "markdown":
|
||
# markdown消息
|
||
messages_content = {
|
||
"markdown": {
|
||
"content": body_markdown,
|
||
}
|
||
}
|
||
|
||
elif msgtype == "template_card":
|
||
# 模板卡片消息
|
||
messages_content = {
|
||
"template_card": json.loads(body_json, strict=False),
|
||
}
|
||
return messages_content
|
||
|
||
def get_messages_options(
|
||
self,
|
||
msgtype,
|
||
safe=None,
|
||
enable_id_trans=None,
|
||
enable_duplicate_check=None,
|
||
duplicate_check_interval=None,
|
||
):
|
||
"""[summary]
|
||
获取企业微信消息的选项
|
||
Args:
|
||
msgtype ([type]): [description]
|
||
safe ([type], optional): [description]. Defaults to None.
|
||
enable_id_trans ([type], optional): [description]. Defaults to None.
|
||
enable_duplicate_check ([type], optional): [description]. Defaults to None.
|
||
duplicate_check_interval ([type], optional): [description]. Defaults to None.
|
||
|
||
Returns:
|
||
[type]: [description]
|
||
"""
|
||
messages_options = {
|
||
"safe": int(safe),
|
||
"enable_id_trans": int(enable_id_trans),
|
||
"enable_duplicate_check": int(enable_duplicate_check),
|
||
"duplicate_check_interval": duplicate_check_interval,
|
||
}
|
||
|
||
if msgtype == "markdown":
|
||
# markdown消息
|
||
del messages_options["safe"]
|
||
del messages_options["enable_id_trans"]
|
||
if msgtype == "template_card":
|
||
# 模板卡片消息
|
||
del messages_options["safe"]
|
||
|
||
return messages_options
|
||
|
||
# def check_material_file_expiration(self, material):
|
||
# """[summary]
|
||
# 检查素材文件是否过期
|
||
# Args:
|
||
# material ([type]): [description]
|
||
|
||
# Returns:
|
||
# [type]: [description]
|
||
# """
|
||
# media_id = ""
|
||
# if material.created_at:
|
||
# # 有创建日期
|
||
# created_time = material.created_at
|
||
# MAX_FAIL_TIME = 3
|
||
|
||
# # 检查是否超过3天
|
||
# overdue = self.env["wecom.tools"].cheeck_days_overdue(
|
||
# created_time, MAX_FAIL_TIME
|
||
# )
|
||
# if overdue:
|
||
# # 临时素材超期,重新上传
|
||
# material.upload_media()
|
||
# media_id = material.media_id
|
||
# else:
|
||
# # 无创建日期,执行第一次上传临时素材
|
||
# material.upload_media()
|
||
# media_id = material.media_id
|
||
# return media_id
|