You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1049 lines
35 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'dart:convert';
import 'package:bytedesk_kefu/bytedesk_kefu.dart';
import 'package:bytedesk_kefu/model/message.dart';
import 'package:bytedesk_kefu/model/thread.dart';
import 'package:bytedesk_kefu/model/user.dart';
// TODO: 条件引入web格式类似import 'src/configure_imp.dart' if (dart.library.html) 'src/configure_web.dart' as conf;
// ignore: uri_does_not_exist
import 'package:bytedesk_kefu/mqtt/lib/mqtt_browser_client.dart';
import 'package:bytedesk_kefu/mqtt/lib/mqtt_client.dart';
import 'package:bytedesk_kefu/mqtt/lib/mqtt_server_client.dart';
import 'package:bytedesk_kefu/util/bytedesk_constants.dart';
import 'package:bytedesk_kefu/model/messageProvider.dart';
import 'package:bytedesk_kefu/util/bytedesk_events.dart';
import 'package:bytedesk_kefu/util/bytedesk_extraparam.dart';
import 'package:bytedesk_kefu/util/bytedesk_utils.dart';
import 'package:bytedesk_kefu/util/bytedesk_uuid.dart';
import 'package:sp_util/sp_util.dart';
// FIXME: proto文件重新生成兼容null-safty报错
// ignore: import_of_legacy_library_into_null_safe
import 'package:bytedesk_kefu/protobuf/message.pb.dart' as protomsg;
// ignore: import_of_legacy_library_into_null_safe
import 'package:bytedesk_kefu/protobuf/thread.pb.dart' as protothread;
// ignore: import_of_legacy_library_into_null_safe
import 'package:bytedesk_kefu/protobuf/user.pb.dart' as protouser;
import 'package:flutter/services.dart';
// import 'package:fluttertoast/fluttertoast.dart';
// import 'package:vibration/vibration.dart';
class BytedeskMqtt {
//
var mqttClient;
String? clientId;
int keepAlivePeriod = 20;
// final key = Key.fromUtf8('16BytesLengthKey');
// final iv = IV.fromUtf8('A-16-Byte-String');
MessageProvider messageProvider = new MessageProvider();
List<String> midList = [];
// bool _isConnected = false;
String? currentUid;
String? client;
// 单例模式
static final BytedeskMqtt _singleton = BytedeskMqtt._internal();
factory BytedeskMqtt() {
return _singleton;
}
BytedeskMqtt._internal();
void connect() async {
// eventbus发送广播连接中...
bytedeskEventBus
.fire(ConnectionEventBus(BytedeskConstants.USER_STATUS_CONNECTING));
//
currentUid = SpUtil.getString(BytedeskConstants.uid);
client = BytedeskUtils.getClient();
clientId = "$currentUid/$client";
//注意必须要先判断web否则在web运行会报错
// Unsupported operation: Platform._operatingSystem
if (BytedeskUtils.isWeb) {
if (BytedeskConstants.isDebug) {
mqttClient = MqttBrowserClient.withPort(
'ws://127.0.0.1/websocket', clientId!, 3885);
} else {
mqttClient = MqttBrowserClient.withPort(
BytedeskConstants.webSocketWssUrl, clientId!, 443);
}
} else {
if (BytedeskConstants.isWebSocketWss) {
mqttClient =
MqttServerClient(BytedeskConstants.webSocketWssUrl, clientId!);
mqttClient.useWebSocket = true;
mqttClient.port = 443;
/// You can also supply your own websocket protocol list or disable this feature using the websocketProtocols
/// setter, read the API docs for further details here, the vast majority of brokers will support the client default
/// list so in most cases you can ignore this. Mosquito needs the single default setting.
// mqttClient.websocketProtocols = MqttClientConstants.protocolsSingleDefault;
} else {
mqttClient = MqttServerClient(BytedeskConstants.mqttHost, clientId!);
mqttClient.port = BytedeskConstants.mqttPort;
mqttClient.secure = BytedeskConstants.isSecure;
}
}
// 启用3.1.1版本协议否则clientId限制最大长度为23
mqttClient.setProtocolV311();
/// Set logging on if needed, defaults to off
// mqttClient.logging(on: BytedeskConstants.isDebug);
mqttClient.logging(on: false); // BytedeskConstants.isDebug
/// If you intend to use a keep alive value in your connect message that is not the default(60s)
/// you must set it here
mqttClient.keepAlivePeriod = keepAlivePeriod;
mqttClient.autoReconnect = true; // FIXME:
// mqttClient.onAutoReconnect = _onAutoReconnect; // FIXME:
mqttClient.onDisconnected = _onDisconnected;
mqttClient.onConnected = _onConnected;
mqttClient.onSubscribed = _onSubscribed;
mqttClient.onUnsubscribed = _onUnSubscribed;
mqttClient.onSubscribeFail = _onSubscribeFailed;
/// Set a ping received callback if needed, called whenever a ping response(pong) is received from the broker.
mqttClient.pongCallback = _onPong;
/// Create a connection message to use or use the default one. The default one sets the
/// client identifier, any supplied username/password, the default keepalive interval(60s)
/// and clean session, an example of a specific one below.
final MqttConnectMessage connMessage = MqttConnectMessage()
.withClientIdentifier(clientId!)
.authenticateAs('username', 'password'); // TODO: 服务器暂时不需要auth随便填写
// .keepAliveFor(keepAlivePeriod); // Must agree with the keep alive set above or not set
// 取消客户端设置,直接在服务器端统一内容格式推送
// .withWillTopic('protobuf/lastWill/mqtt') // If you set this you must set a will message
// .withWillMessage('My Will message')
// .startClean() // Non persistent session for testing
// .withWillQos(MqttQos.atLeastOnce);
BytedeskUtils.printLog('mqttClient connecting....');
mqttClient.connectionMessage = connMessage;
/// Connect the client, any errors here are communicated by raising of the appropriate exception. Note
/// in some circumstances the broker will just disconnect us, see the spec about this, we however eill
/// never send malformed messages.
try {
await mqttClient.connect();
} on Exception catch (e) {
BytedeskUtils.printLog('mqttClient exception - $e');
mqttClient.disconnect();
}
/// Check we are connected
if (mqttClient.connectionStatus.state == MqttConnectionState.connected) {
BytedeskUtils.printLog('mqttClient connected');
} else {
/// Use status here rather than state if you also want the broker return code.
BytedeskUtils.printLog(
'ERROR mqttClient connection failed - disconnecting, status is ${mqttClient.connectionStatus}');
mqttClient.disconnect();
// exit(-1);
}
/// The client has a change notifier object(see the Observable class) which we then listen to to get
/// notifications of published updates to each subscribed topic.
// mqttClient.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
// final MqttPublishMessage recMess = c[0].payload;
// final String pt =
// MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
// // BytedeskUtils.printLog('Change notification:: topic is <${c[0].topic}>, payload is <-- $pt -->');
// });
/// 收到的消息
// if (mqttClient != null && mqttClient.published != null) {
//
mqttClient.published!.listen((MqttPublishMessage messageBinary) {
// BytedeskUtils.printLog('Published notification:: topic is ${messageBinary.variableHeader.topicName}, with Qos ${messageBinary.header.qos}');
//
protomsg.Message messageProto =
protomsg.Message.fromBuffer(messageBinary.payload.message);
// FIXME: 自己发送的消息显示两条此处根据mid去个重
var mid = messageProto.mid;
if (midList.contains(mid)) {
return;
}
midList.add(mid);
//
var uid = messageProto.user.uid;
var username = messageProto.user.username;
var nickname = messageProto.user.nickname;
var avatar = messageProto.user.avatar;
//
var content = '';
var type = messageProto.type;
var timestamp = messageProto.timestamp;
var client = messageProto.client;
//
BytedeskUtils.printLog('bytedesk_mqtt.dart receive type:' +
type +
' client:' +
client +
' mid:' +
mid);
// 非会话消息,如:会议通知等, 另行处理
if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_NOTICE) {
// TODO: 待处理
return;
}
//
User user = new User(
uid: uid, username: username, nickname: nickname, avatar: avatar);
//
Thread thread = new Thread(
tid: messageProto.thread.tid,
type: messageProto.thread.type,
// uid: '',
nickname: messageProto.thread.nickname,
avatar: messageProto.thread.avatar,
content: messageProto.thread.content,
timestamp: messageProto.thread.timestamp,
unreadCount: messageProto.thread.unreadCount,
topic: messageProto.thread.topic,
client: client);
Message message = new Message(
mid: mid,
content: content,
imageUrl: content,
nickname: nickname,
avatar: avatar,
type: type,
timestamp: timestamp,
status: 'stored',
isSend: uid == currentUid ? 1 : 0,
currentUid: currentUid,
thread: thread,
user: user,
client: client);
// 是否发送消息回执
// var autoReply = false;
var sendReceipt = false;
// var webRTCVideoInvite = false;
// var webRTCAudioInvite = false;
switch (type) {
case BytedeskConstants.MESSAGE_TYPE_TEXT:
{
//
// autoReply = true;
sendReceipt = true;
// TODO: 判断是否加密,暂时不需要
message.content = messageProto.text.content;
BytedeskUtils.printLog('receive text:' + message.content!);
break;
}
case BytedeskConstants.MESSAGE_TYPE_IMAGE:
{
//
// autoReply = true;
sendReceipt = true;
message.imageUrl = messageProto.image.imageUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_VOICE:
{
//
// autoReply = true;
sendReceipt = true;
message.voiceUrl = messageProto.voice.voiceUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_FILE:
{
//
// autoReply = true;
sendReceipt = true;
message.fileUrl = messageProto.file.fileUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_VIDEO:
case BytedeskConstants.MESSAGE_TYPE_SHORT_VIDEO:
{
//
// autoReply = true;
sendReceipt = true;
message.videoUrl = messageProto.video.videoOrShortUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_THREAD:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_THREAD_REENTRY:
case BytedeskConstants.MESSAGE_TYPE_COMMODITY:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_CONNECT:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_DISCONNECT:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_QUEUE:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_QUEUE_ACCEPT:
{
// 替换 'joinQueueThread'
message.content = '接入队列会话'; // TODO: 国际化
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_AGENT_CLOSE:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_VISITOR_CLOSE:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_AUTO_CLOSE:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TICKET:
{
// TODO: 工单消息
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_FEEDBACK:
{
// TODO: 意见反馈
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_CHANNEL:
{
// TODO: 渠道消息
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_PREVIEW:
{
// 对方正在输入
String uid = messageProto.user.uid;
String previewContent = messageProto.preview.content;
if (uid != currentUid) {
bytedeskEventBus
.fire(ReceiveMessagePreviewEventBus(previewContent));
}
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECEIPT:
{
// 消息回执
var midR = messageProto.receipt.mid;
var statusR = messageProto.receipt.status;
messageProvider.update(midR, statusR);
// 通知界面更新聊天记录状态
bytedeskEventBus.fire(ReceiveMessageReceiptEventBus(midR, statusR));
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECALL:
{
// 消息撤回
String mid = messageProto.recall.mid;
bytedeskEventBus.fire(DeleteMessageEventBus(mid));
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_RATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RATE_RESULT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE_VIDEO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE_AUDIO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CANCEL:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_OFFER_VIDEO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_OFFER_AUDIO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_ANSWER:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CANDIDATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_READY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_BUSY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CLOSE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_CREATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_UPDATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_ANNOUNCEMENT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY_APPROVE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY_DENY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_KICK:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_MUTE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_WITHDRAW:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_DISMISS:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_LOCATION:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_LINK:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_EVENT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_CUSTOM:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_RED_PACKET:
{
//
return;
}
default:
BytedeskUtils.printLog('other message type:' + type);
}
// 客服端使用
// if (autoReply) {
// //
// }
//
if (sendReceipt && message.isSend == 0) {
// 发送送达回执
sendReceiptReceivedMessage(mid, thread);
}
//
// final encrypter = Encrypter(AES(key, mode: AESMode.cbc));
// final decrypted = encrypter.decrypt64(messageProto.text.content, iv: iv);
// BytedeskUtils.printLog('content: ' + decrypted);
//
// 忽略连接信息
if (message.content == 'visitorConnect' ||
message.content == 'visitorDisconnect') {
return;
}
// 插入本地数据库
// if (messageProvider != null) {
messageProvider.insert(message);
// }
// 通知界面显示聊天记录
bytedeskEventBus.fire(ReceiveMessageEventBus(message));
// 接收消息播放提示音放到SDK外实现迁移到demo中
if (BytedeskKefu.getPlayAudioOnReceiveMessage()! && message.isSend == 0) {
// BytedeskUtils.printLog('play audio');
SystemSound.play(SystemSoundType.click);
}
// 振动放到SDK外实现迁移到demo中
if (BytedeskKefu.getVibrateOnReceiveMessage()! && message.isSend == 0) {
// BytedeskUtils.printLog('should vibrate');
vibrate();
}
});
//
// } else {
// BytedeskUtils.printLog('mqttClient.published is null');
// }
}
// FIXME: ld: library not found for -lvibration
void vibrate() async {
// if (await Vibration.hasVibrator()) {
// Vibration.vibrate();
// }
}
void subscribe(String topic) {
// BytedeskUtils.printLog('Subscribing to the hello topic');
mqttClient.subscribe(topic, MqttQos.exactlyOnce);
}
void unsubscribe(String topic) {
mqttClient.unsubscribe(topic);
}
void sendTextMessage(String content, Thread currentThread) {
publish(content, BytedeskConstants.MESSAGE_TYPE_TEXT, currentThread, null);
}
void sendImageMessage(String content, Thread currentThread) {
publish(content, BytedeskConstants.MESSAGE_TYPE_IMAGE, currentThread, null);
}
void sendFileMessage(String content, Thread currentThread) {
publish(content, BytedeskConstants.MESSAGE_TYPE_FILE, currentThread, null);
}
void sendVoiceMessage(String content, Thread currentThread) {
publish(content, BytedeskConstants.MESSAGE_TYPE_VOICE, currentThread, null);
}
void sendVideoMessage(String content, Thread currentThread) {
publish(content, BytedeskConstants.MESSAGE_TYPE_VIDEO, currentThread, null);
}
// 商品消息
void sendCommodityMessage(String content, Thread currentThread) {
publish(
content, BytedeskConstants.MESSAGE_TYPE_COMMODITY, currentThread, null);
}
// 消息预知
void sendPreviewMessage(String previewContent, Thread currentThread) {
publish(previewContent, BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_PREVIEW,
currentThread, null);
}
// 消息撤回
void sendRecallMessage(String mid, Thread currentThread) {
ExtraParam extraParam = new ExtraParam();
extraParam.recallMid = mid;
publish(mid, BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECALL,
currentThread, extraParam);
}
// 送达回执
void sendReceiptReceivedMessage(String mid, Thread currentThread) {
sendReceiptMessage(
mid, BytedeskConstants.MESSAGE_STATUS_RECEIVED, currentThread);
}
// 已读回执
void sendReceiptReadMessage(String mid, Thread currentThread) {
sendReceiptMessage(
mid, BytedeskConstants.MESSAGE_STATUS_READ, currentThread);
}
void sendReceiptMessage(String mid, String status, Thread currentThread) {
ExtraParam extraParam = new ExtraParam();
extraParam.receiptMid = mid;
extraParam.receiptStatus = status;
publish('content', BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECEIPT,
currentThread, extraParam);
}
void publish(String content, String type, Thread currentThread,
ExtraParam? extraParam) {
// if (currentThread == null) {
// BytedeskUtils.printLog('连接客服失败,请退出页面重新进入。注意: 请在App启动的时候调用init接口');
// Fluttertoast.showToast(msg: '连接客服失败,请退出页面重新进入');
// return;
// }
// https://pub.dev/packages/encrypt#aes
// final encrypter = Encrypter(AES(key, mode: AESMode.cbc));
// final encrypted = encrypter.encrypt(content, iv: iv);
// BytedeskUtils.printLog(encrypted.base64);
// final decrypted = encrypter.decrypt(encrypted, iv: iv);
// BytedeskUtils.printLog(decrypted);
// thread
protothread.Thread thread = new protothread.Thread();
thread.tid = currentThread.tid!;
thread.type = currentThread.type!;
thread.topic = currentThread.topic!;
thread.nickname = currentThread.nickname!;
thread.avatar = currentThread.avatar!;
thread.client = currentThread.client!;
thread.timestamp = BytedeskUtils.formatedDateNow(); // 没有必要填写,服务器端会填充
thread.unreadCount = 0;
var extra = {'top': false, 'undisturb': false};
thread.extra = jsonEncode(extra);
// user
protouser.User user = new protouser.User();
user.uid = SpUtil.getString(BytedeskConstants.uid)!;
user.username = SpUtil.getString(BytedeskConstants.username)!;
user.nickname = SpUtil.getString(BytedeskConstants.nickname)!;
user.avatar = SpUtil.getString(BytedeskConstants.avatar)!;
// msg
protomsg.Message messageProto = new protomsg.Message();
messageProto.mid = BytedeskUuid.uuid();
messageProto.type = type;
messageProto.timestamp = BytedeskUtils.formatedDateNow();
messageProto.client = BytedeskUtils.getClient(); //BytedeskConstants.client;
messageProto.version = '1';
messageProto.encrypted = false;
// 用来在发送之前显示到界面
Message message = new Message();
message.mid = messageProto.mid;
message.type = messageProto.type;
message.timestamp = messageProto.timestamp;
message.client = messageProto.client;
message.nickname = user.nickname;
message.avatar = user.avatar;
message.topic = thread.topic;
message.status = BytedeskConstants.MESSAGE_STATUS_SENDING;
message.isSend = 1;
message.currentUid = currentUid;
message.answersJson = '';
message.thread = currentThread;
message.user =
User(uid: user.uid, avatar: user.avatar, nickname: user.nickname);
// 判断是否应该插入本地并显示
bool shouldInsertLocal = false;
// 发送protobuf
if (type == BytedeskConstants.MESSAGE_TYPE_TEXT) {
protomsg.Text text = new protomsg.Text();
text.content = content;
messageProto.text = text;
//
thread.content = content;
//
shouldInsertLocal = true;
message.content = content;
} else if (type == BytedeskConstants.MESSAGE_TYPE_IMAGE) {
protomsg.Image image = new protomsg.Image();
image.imageUrl = content;
messageProto.image = image;
//
thread.content = '[图片]';
//
shouldInsertLocal = true;
message.imageUrl = content;
} else if (type == BytedeskConstants.MESSAGE_TYPE_VOICE) {
protomsg.Voice voice = new protomsg.Voice();
voice.voiceUrl = content;
// voice.length
// voice.format
messageProto.voice = voice;
//
thread.content = '[语音]';
//
shouldInsertLocal = true;
message.voiceUrl = content;
} else if (type == BytedeskConstants.MESSAGE_TYPE_FILE) {
protomsg.File file = new protomsg.File();
file.fileUrl = content;
messageProto.file = file;
//
thread.content = '[文件]';
//
shouldInsertLocal = true;
message.fileUrl = content;
} else if (type == BytedeskConstants.MESSAGE_TYPE_VIDEO ||
type == BytedeskConstants.MESSAGE_TYPE_SHORT_VIDEO) {
protomsg.Video video = new protomsg.Video();
video.videoOrShortUrl = content;
messageProto.video = video;
//
thread.content = '[视频]';
//
shouldInsertLocal = true;
message.videoUrl = content;
} else if (type == BytedeskConstants.MESSAGE_TYPE_COMMODITY) {
protomsg.Text text = new protomsg.Text();
text.content = content;
messageProto.text = text;
//
thread.content = '[商品]';
//
shouldInsertLocal = true;
message.content = content;
} else if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_PREVIEW) {
protomsg.Preview preview = new protomsg.Preview();
preview.content = content;
messageProto.preview = preview;
} else if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECEIPT) {
// 发送消息回执
protomsg.Receipt receipt = new protomsg.Receipt();
receipt.mid = extraParam!.receiptMid!;
receipt.status = extraParam.receiptStatus!;
//
messageProto.receipt = receipt;
} else if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECALL) {
//
protomsg.Recall recall = new protomsg.Recall();
recall.mid = extraParam!.recallMid!;
//
messageProto.recall = recall;
} else if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER_ACCEPT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER_REJECT) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_ACCEPT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_REJECT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_RATE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RATE_RESULT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE_VIDEO) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE_AUDIO) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CANCEL) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_OFFER_VIDEO) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_OFFER_AUDIO) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_ANSWER) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CANDIDATE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_ACCEPT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_REJECT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_READY) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_BUSY) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CLOSE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_CREATE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_UPDATE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_ANNOUNCEMENT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE_ACCEPT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE_REJECT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY_APPROVE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY_DENY) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_KICK) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_MUTE) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER_ACCEPT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER_REJECT) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_WITHDRAW) {
//
return;
} else if (type ==
BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_DISMISS) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_LOCATION) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_LINK) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_EVENT) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_CUSTOM) {
//
return;
} else if (type == BytedeskConstants.MESSAGE_TYPE_RED_PACKET) {
//
return;
} else {
// 其他类型消息
BytedeskUtils.printLog('other type:' + type);
}
//
messageProto.user = user;
messageProto.thread = thread;
// 先通知界面本地显示聊天记录,然后再发送
if (shouldInsertLocal) {
// 插入本地数据库
// if (messageProvider != null) {
messageProvider.insert(message);
// }
bytedeskEventBus.fire(ReceiveMessageEventBus(message));
midList.add(message.mid!);
}
//
final MqttClientPayloadBuilder builder = MqttClientPayloadBuilder();
// 注意:此函数为自行添加,原先库中没有
builder.addProtobuf(messageProto.writeToBuffer());
mqttClient.publishMessage(
currentThread.topic, MqttQos.exactlyOnce, builder.payload);
// 播放发送消息提示音放到SDK外实现迁移到demo中
if (BytedeskKefu.getPlayAudioOnSendMessage()!) {
//
}
}
// 断开长连接
void disconnect() {
if (mqttClient != null) {
mqttClient.disconnect();
}
}
/// The subscribed callback
void _onSubscribed(String? topic) {
// BytedeskUtils.printLog('Subscription confirmed for topic $topic');
}
/// The unsubscribed callback
void _onUnSubscribed(String? topic) {
// BytedeskUtils.printLog('UnSubscription confirmed for topic $topic');
}
/// The subscribed callback
void _onSubscribeFailed(String? topic) {
// BytedeskUtils.printLog('Subscribe Failed confirmed for topic $topic');
}
/// The unsolicited disconnect callback
void _onDisconnected() {
// _isConnected = false;
// BytedeskUtils.printLog('OnDisconnected client callback - Client disconnection');
// eventbus发广播通知长连接断开
bytedeskEventBus
.fire(ConnectionEventBus(BytedeskConstants.USER_STATUS_DISCONNECTED));
// if (mqttClient.connectionStatus.returnCode == MqttConnectReturnCode.solicited) {
// BytedeskUtils.printLog('OnDisconnected callback is solicited, this is correct');
// }
// 延时10s执行重连
Future.delayed(Duration(seconds: 10), () {
// BytedeskUtils.printLog('start reconnecting');
// reconnect();
});
}
/// The unsolicited disconnect callback
// void _onAutoReconnect() {
// // BytedeskUtils.printLog('EXAMPLE::onAutoReconnect client callback - Client auto reconnection sequence will start');
// // connect();
// }
/// The successful connect callback
void _onConnected() {
// _isConnected = true;
// BytedeskUtils.printLog('OnConnected client callback - Client connection was sucessful');
// TODO: eventbus发广播通知长连接建立
bytedeskEventBus
.fire(ConnectionEventBus(BytedeskConstants.USER_STATUS_CONNECTED));
}
/// Pong callback
void _onPong() {
// BytedeskUtils.printLog('Ping response client callback invoked');
}
bool isConnected() {
// return _isConnected;
return mqttClient.connectionStatus.state == MqttConnectionState.connected;
}
}