update plugins/freeswitch: add 3 mod 1 del 3 files

This commit is contained in:
jack ning
2025-06-08 22:06:57 +08:00
parent 7875e732f1
commit 88c2b7a07a
34 changed files with 841 additions and 295 deletions

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-08 12:45:23
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 12:46:04
* @LastEditTime: 2025-06-08 21:34:36
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -13,8 +13,6 @@
*/
package com.bytedesk.freeswitch.callcenter;
import java.time.LocalDateTime;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@@ -23,8 +21,6 @@ import com.bytedesk.freeswitch.callcenter.event.CallAnsweredEvent;
import com.bytedesk.freeswitch.callcenter.event.CallHangupEvent;
import com.bytedesk.freeswitch.callcenter.event.CallStartEvent;
import com.bytedesk.freeswitch.callcenter.event.DtmfEvent;
import com.bytedesk.freeswitch.user.FreeSwitchUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -40,7 +36,7 @@ public class CallEventListener {
private final CallService callService;
// private final FreeSwitchCdrService cdrService; // 暂时未使用,保留以备后续扩展
private final FreeSwitchUserService userService;
// private final FreeSwitchNumberService userService;
/**
* 监听通话开始事件
@@ -119,10 +115,10 @@ public class CallEventListener {
*/
private void updateUserActivity(String username) {
try {
if (userService.findByUsername(username).isPresent()) {
userService.updateLastRegistration(username, LocalDateTime.now());
log.debug("已更新用户活动时间: {}", username);
}
// if (userService.findByUsername(username).isPresent()) {
// userService.updateLastRegistration(username, LocalDateTime.now());
// log.debug("已更新用户活动时间: {}", username);
// }
} catch (Exception e) {
log.error("更新用户活动时间失败: {} - {}", username, e.getMessage(), e);
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-05-24 10:31:49
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:03:38
* @LastEditTime: 2025-06-08 21:34:27
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -24,11 +24,8 @@ import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import com.bytedesk.freeswitch.cdr.FreeSwitchCdrEntity;
import com.bytedesk.freeswitch.user.FreeSwitchUserEntity;
import com.bytedesk.freeswitch.cdr.FreeSwitchCdrService;
import com.bytedesk.freeswitch.config.FreeSwitchService;
import com.bytedesk.freeswitch.user.FreeSwitchUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -46,7 +43,7 @@ public class CallService {
private final FreeSwitchService freeSwitchService;
private final SimpMessagingTemplate messagingTemplate;
private final FreeSwitchCdrService cdrService;
private final FreeSwitchUserService userService;
// private final FreeSwitchNumberService userService;
// 存储活动呼叫信息
private final Map<String, CallInfo> activeCallMap = new ConcurrentHashMap<>();
@@ -469,11 +466,11 @@ public class CallService {
*/
private void updateUserLastRegistration(String username) {
try {
Optional<FreeSwitchUserEntity> userOptional = userService.findByUsername(username);
if (userOptional.isPresent()) {
userService.updateLastRegistration(username, LocalDateTime.now());
log.debug("已更新用户最后注册时间: {}", username);
}
// Optional<FreeSwitchNumberEntity> userOptional = userService.findByUsername(username);
// if (userOptional.isPresent()) {
// userService.updateLastRegistration(username, LocalDateTime.now());
// log.debug("已更新用户最后注册时间: {}", username);
// }
} catch (Exception e) {
log.error("更新用户最后注册时间失败: {} - {}", username, e.getMessage(), e);
}

View File

@@ -14,8 +14,15 @@
package com.bytedesk.freeswitch.cdr;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;
import com.bytedesk.core.utils.ApplicationContextHolder;
import com.bytedesk.freeswitch.cdr.event.FreeSwitchCdrCreateEvent;
import com.bytedesk.freeswitch.cdr.event.FreeSwitchCdrUpdateEvent;
import com.bytedesk.freeswitch.config.FreeSwitchEventPublisher;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostUpdate;
import lombok.extern.slf4j.Slf4j;
/**
@@ -30,5 +37,20 @@ public class FreeSwitchCdrEntityListener {
log.info("FreeSwitch CDR记录创建: uuid={}, caller={}, destination={}, duration={}",
entity.getUid(), entity.getCallerIdNumber(),
entity.getDestinationNumber(), entity.getDuration());
FreeSwitchCdrEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchCdrCreateEvent(cloneEntity));
}
@PostUpdate
public void onPostUpdate(FreeSwitchCdrEntity entity) {
log.info("FreeSwitch CDR记录更新: uuid={}, caller={}, destination={}, duration={}",
entity.getUid(), entity.getCallerIdNumber(),
entity.getDestinationNumber(), entity.getDuration());
FreeSwitchCdrEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchCdrUpdateEvent(cloneEntity));
}
}

View File

@@ -0,0 +1,52 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:39:10
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.cdr;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.bytedesk.freeswitch.cdr.event.FreeSwitchCdrCreateEvent;
import com.bytedesk.freeswitch.cdr.event.FreeSwitchCdrUpdateEvent;
import lombok.extern.slf4j.Slf4j;
/**
* FreeSwitch事件监听器
*/
@Slf4j
@Component
public class FreeSwitchCdrEventListener {
@EventListener
public void onFreeSwitchCdrCreateEvent(FreeSwitchCdrCreateEvent event) {
FreeSwitchCdrEntity cdr = event.getCdr();
log.info("收到FreeSwitch CDR创建事件: uuid={}, caller={}, destination={}",
cdr.getUid(), cdr.getCallerIdNumber(), cdr.getDestinationNumber());
// 这里可以添加额外的处理逻辑,比如:
// 1. 通知系统管理员有新的通话记录
// 2. 更新相关统计信息
// 3. 触发其他业务流程
}
@EventListener
public void onFreeSwitchCdrUpdateEvent(FreeSwitchCdrUpdateEvent event) {
FreeSwitchCdrEntity cdr = event.getCdr();
log.info("收到FreeSwitch CDR更新事件: uuid={}, duration={}",
cdr.getUid(), cdr.getDuration());
// 这里可以添加额外的处理逻辑
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:50:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.cdr.event;
import com.bytedesk.freeswitch.cdr.FreeSwitchCdrEntity;
import lombok.Getter;
@Getter
public class FreeSwitchCdrCreateEvent {
private final FreeSwitchCdrEntity cdr;
public FreeSwitchCdrCreateEvent(FreeSwitchCdrEntity cdr) {
this.cdr = cdr;
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:50:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.cdr.event;
import com.bytedesk.freeswitch.cdr.FreeSwitchCdrEntity;
import lombok.Getter;
@Getter
public class FreeSwitchCdrUpdateEvent {
private final FreeSwitchCdrEntity cdr;
public FreeSwitchCdrUpdateEvent(FreeSwitchCdrEntity cdr) {
this.cdr = cdr;
}
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 19:50:34
* @LastEditTime: 2025-06-08 21:19:21
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,6 +14,7 @@
package com.bytedesk.freeswitch.conference;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.TypeConsts;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -67,38 +68,35 @@ public class FreeSwitchConferenceEntity extends BaseEntity {
* 是否启用
*/
@Builder.Default
@Column(nullable = false)
@Column(name = "is_enabled")
private Boolean enabled = true;
/**
* 是否录音
*/
@Builder.Default
@Column(nullable = false)
@Column(name = "is_record_enabled")
private Boolean recordEnabled = false;
/**
* 录音文件路径
*/
@Column(length = 500)
private String recordPath;
/**
* 创建者
*/
@Column(length = 100)
private String creator;
/**
* 会议室配置参数JSON格式
*/
@Column(columnDefinition = "TEXT")
@Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT)
private String configJson;
/**
* 备注
*/
@Column(length = 500)
private String remarks;
/**

View File

@@ -14,6 +14,12 @@
package com.bytedesk.freeswitch.conference;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;
import com.bytedesk.core.utils.ApplicationContextHolder;
import com.bytedesk.freeswitch.config.FreeSwitchEventPublisher;
import com.bytedesk.freeswitch.conference.event.FreeSwitchConferenceCreateEvent;
import com.bytedesk.freeswitch.conference.event.FreeSwitchConferenceUpdateEvent;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostUpdate;
@@ -30,11 +36,19 @@ public class FreeSwitchConferenceEntityListener {
public void postPersist(FreeSwitchConferenceEntity entity) {
log.info("FreeSwitch会议室创建: name={}, maxMembers={}",
entity.getConferenceName(), entity.getMaxMembers());
FreeSwitchConferenceEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchConferenceCreateEvent(cloneEntity));
}
@PostUpdate
public void postUpdate(FreeSwitchConferenceEntity entity) {
log.info("FreeSwitch会议室更新: name={}, enabled={}",
entity.getConferenceName(), entity.getEnabled());
FreeSwitchConferenceEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchConferenceUpdateEvent(cloneEntity));
}
}

View File

@@ -0,0 +1,52 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:38:55
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.conference;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.bytedesk.freeswitch.conference.event.FreeSwitchConferenceCreateEvent;
import com.bytedesk.freeswitch.conference.event.FreeSwitchConferenceUpdateEvent;
import lombok.extern.slf4j.Slf4j;
/**
* FreeSwitch事件监听器
*/
@Slf4j
@Component
public class FreeSwitchConferenceEventListener {
@EventListener
public void onFreeSwitchConferenceCreateEvent(FreeSwitchConferenceCreateEvent event) {
FreeSwitchConferenceEntity conference = event.getConference();
log.info("收到FreeSwitch会议室创建事件: name={}, maxMembers={}",
conference.getConferenceName(), conference.getMaxMembers());
// 这里可以添加额外的处理逻辑,比如:
// 1. 通知相关用户新的会议室已创建
// 2. 预分配会议资源
}
@EventListener
public void onFreeSwitchConferenceUpdateEvent(FreeSwitchConferenceUpdateEvent event) {
FreeSwitchConferenceEntity conference = event.getConference();
log.info("收到FreeSwitch会议室更新事件: name={}, enabled={}",
conference.getConferenceName(), conference.getEnabled());
// 这里可以添加额外的处理逻辑
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 22:00:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.conference.event;
import com.bytedesk.freeswitch.conference.FreeSwitchConferenceEntity;
import lombok.Getter;
@Getter
public class FreeSwitchConferenceCreateEvent {
private final FreeSwitchConferenceEntity conference;
public FreeSwitchConferenceCreateEvent(FreeSwitchConferenceEntity conference) {
this.conference = conference;
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 22:00:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.conference.event;
import com.bytedesk.freeswitch.conference.FreeSwitchConferenceEntity;
import lombok.Getter;
@Getter
public class FreeSwitchConferenceUpdateEvent {
private final FreeSwitchConferenceEntity conference;
public FreeSwitchConferenceUpdateEvent(FreeSwitchConferenceEntity conference) {
this.conference = conference;
}
}

View File

@@ -1,7 +1,6 @@
package com.bytedesk.freeswitch.config;
import java.time.LocalDateTime;
import java.util.Optional;
import org.freeswitch.esl.client.IEslEventListener;
import org.freeswitch.esl.client.transport.event.EslEvent;
@@ -14,9 +13,8 @@ import com.bytedesk.freeswitch.callcenter.event.CallHangupEvent;
import com.bytedesk.freeswitch.callcenter.event.CallStartEvent;
import com.bytedesk.freeswitch.callcenter.event.DtmfEvent;
import com.bytedesk.freeswitch.cdr.FreeSwitchCdrEntity;
import com.bytedesk.freeswitch.user.FreeSwitchUserEntity;
import com.bytedesk.freeswitch.cdr.FreeSwitchCdrService;
import com.bytedesk.freeswitch.user.FreeSwitchUserService;
// import com.bytedesk.freeswitch.number.FreeSwitchNumberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -32,7 +30,7 @@ public class FreeSwitchEventListener implements IEslEventListener {
private final ApplicationEventPublisher eventPublisher;
private final FreeSwitchCdrService cdrService;
private final FreeSwitchUserService userService;
// private final FreeSwitchNumberService userService;
/**
* 处理FreeSwitch事件
@@ -184,13 +182,13 @@ public class FreeSwitchEventListener implements IEslEventListener {
*/
private void updateUserOnlineStatus(String username, boolean online) {
try {
Optional<FreeSwitchUserEntity> userOptional = userService.findByUsername(username);
if (userOptional.isPresent()) {
if (online) {
userService.updateLastRegistration(username, LocalDateTime.now());
}
log.debug("已更新用户在线状态: {} -> {}", username, online);
}
// Optional<FreeSwitchNumberEntity> userOptional = userService.findByUsername(username);
// if (userOptional.isPresent()) {
// if (online) {
// userService.updateLastRegistration(username, LocalDateTime.now());
// }
// log.debug("已更新用户在线状态: {} -> {}", username, online);
// }
} catch (Exception e) {
log.error("更新用户在线状态失败: {} - {}", username, e.getMessage(), e);
}

View File

@@ -0,0 +1,76 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:55:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.config;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import com.bytedesk.freeswitch.cdr.event.FreeSwitchCdrCreateEvent;
import com.bytedesk.freeswitch.cdr.event.FreeSwitchCdrUpdateEvent;
import com.bytedesk.freeswitch.conference.event.FreeSwitchConferenceCreateEvent;
import com.bytedesk.freeswitch.conference.event.FreeSwitchConferenceUpdateEvent;
import com.bytedesk.freeswitch.gateway.event.FreeSwitchGatewayCreateEvent;
import com.bytedesk.freeswitch.gateway.event.FreeSwitchGatewayUpdateEvent;
import com.bytedesk.freeswitch.number.event.FreeSwitchNumberCreateEvent;
import com.bytedesk.freeswitch.number.event.FreeSwitchNumberUpdateEvent;
import lombok.AllArgsConstructor;
/**
* FreeSwitch事件发布器
*/
@Async
@Component
@AllArgsConstructor
public class FreeSwitchEventPublisher {
private final ApplicationEventPublisher applicationEventPublisher;
// CDR事件
public void publishEvent(FreeSwitchCdrCreateEvent event) {
applicationEventPublisher.publishEvent(event);
}
public void publishEvent(FreeSwitchCdrUpdateEvent event) {
applicationEventPublisher.publishEvent(event);
}
// Conference事件
public void publishEvent(FreeSwitchConferenceCreateEvent event) {
applicationEventPublisher.publishEvent(event);
}
public void publishEvent(FreeSwitchConferenceUpdateEvent event) {
applicationEventPublisher.publishEvent(event);
}
// Gateway事件
public void publishEvent(FreeSwitchGatewayCreateEvent event) {
applicationEventPublisher.publishEvent(event);
}
public void publishEvent(FreeSwitchGatewayUpdateEvent event) {
applicationEventPublisher.publishEvent(event);
}
// User事件
public void publishEvent(FreeSwitchNumberCreateEvent event) {
applicationEventPublisher.publishEvent(event);
}
public void publishEvent(FreeSwitchNumberUpdateEvent event) {
applicationEventPublisher.publishEvent(event);
}
}

View File

@@ -45,71 +45,63 @@ public class FreeSwitchGatewayEntity extends BaseEntity {
/**
* 网关名称
*/
@Column(nullable = false, unique = true, length = 100)
@Column(unique = true)
private String gatewayName;
/**
* 网关描述
*/
@Column(length = 255)
private String description;
/**
* SIP服务器地址
*/
@Column(nullable = false, length = 255)
private String proxy;
/**
* 用户名
*/
@Column(nullable = false, length = 100)
private String username;
/**
* 密码
*/
@Column(nullable = false, length = 255)
private String password;
/**
* 从号码
*/
@Column(length = 100)
private String fromUser;
/**
* 从域名
*/
@Column(length = 100)
private String fromDomain;
/**
* 注册
*/
@Builder.Default
@Column(nullable = false)
@Column(name = "is_register")
private Boolean register = true;
/**
* 注册传输协议
*/
@Builder.Default
@Column(length = 20)
private String registerTransport = "udp";
/**
* 网关状态
*/
@Builder.Default
@Column(length = 20)
private String status = "DOWN";
/**
* 是否启用
*/
@Builder.Default
@Column(nullable = false)
@Column(name = "is_enabled")
private Boolean enabled = true;
/**
@@ -121,7 +113,6 @@ public class FreeSwitchGatewayEntity extends BaseEntity {
/**
* 备注
*/
@Column(length = 500)
private String remarks;
/**

View File

@@ -14,6 +14,12 @@
package com.bytedesk.freeswitch.gateway;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;
import com.bytedesk.core.utils.ApplicationContextHolder;
import com.bytedesk.freeswitch.config.FreeSwitchEventPublisher;
import com.bytedesk.freeswitch.gateway.event.FreeSwitchGatewayCreateEvent;
import com.bytedesk.freeswitch.gateway.event.FreeSwitchGatewayUpdateEvent;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostUpdate;
@@ -30,11 +36,19 @@ public class FreeSwitchGatewayEntityListener {
public void postPersist(FreeSwitchGatewayEntity entity) {
log.info("FreeSwitch网关创建: name={}, proxy={}",
entity.getGatewayName(), entity.getProxy());
FreeSwitchGatewayEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchGatewayCreateEvent(cloneEntity));
}
@PostUpdate
public void postUpdate(FreeSwitchGatewayEntity entity) {
log.info("FreeSwitch网关更新: name={}, status={}, enabled={}",
entity.getGatewayName(), entity.getStatus(), entity.getEnabled());
FreeSwitchGatewayEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchGatewayUpdateEvent(cloneEntity));
}
}

View File

@@ -0,0 +1,52 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:37:30
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.gateway;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.bytedesk.freeswitch.gateway.event.FreeSwitchGatewayCreateEvent;
import com.bytedesk.freeswitch.gateway.event.FreeSwitchGatewayUpdateEvent;
import lombok.extern.slf4j.Slf4j;
/**
* FreeSwitch事件监听器
*/
@Slf4j
@Component
public class FreeSwitchGatewayEventListener {
@EventListener
public void onFreeSwitchGatewayCreateEvent(FreeSwitchGatewayCreateEvent event) {
FreeSwitchGatewayEntity gateway = event.getGateway();
log.info("收到FreeSwitch网关创建事件: name={}, proxy={}",
gateway.getGatewayName(), gateway.getProxy());
// 这里可以添加额外的处理逻辑,比如:
// 1. 自动注册网关到FreeSwitch服务器
// 2. 更新网关状态监控信息
}
@EventListener
public void onFreeSwitchGatewayUpdateEvent(FreeSwitchGatewayUpdateEvent event) {
FreeSwitchGatewayEntity gateway = event.getGateway();
log.info("收到FreeSwitch网关更新事件: name={}, status={}",
gateway.getGatewayName(), gateway.getStatus());
// 这里可以添加额外的处理逻辑
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 22:05:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.gateway.event;
import com.bytedesk.freeswitch.gateway.FreeSwitchGatewayEntity;
import lombok.Getter;
@Getter
public class FreeSwitchGatewayCreateEvent {
private final FreeSwitchGatewayEntity gateway;
public FreeSwitchGatewayCreateEvent(FreeSwitchGatewayEntity gateway) {
this.gateway = gateway;
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 22:05:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.gateway.event;
import com.bytedesk.freeswitch.gateway.FreeSwitchGatewayEntity;
import lombok.Getter;
@Getter
public class FreeSwitchGatewayUpdateEvent {
private final FreeSwitchGatewayEntity gateway;
public FreeSwitchGatewayUpdateEvent(FreeSwitchGatewayEntity gateway) {
this.gateway = gateway;
}
}

View File

@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import com.bytedesk.core.utils.JsonResult;
import lombok.AllArgsConstructor;
@@ -37,17 +37,17 @@ import java.util.stream.Collectors;
@RequestMapping("/freeswitch/api/v1/users")
@AllArgsConstructor
@ConditionalOnProperty(name = "bytedesk.freeswitch.enabled", havingValue = "true")
public class FreeSwitchUserController {
public class FreeSwitchNumberController {
private final FreeSwitchUserService userService;
private final FreeSwitchNumberService userService;
/**
* 创建用户
*/
@PostMapping
public ResponseEntity<JsonResult<?>> createUser(@Valid @RequestBody FreeSwitchUserRequest request) {
public ResponseEntity<JsonResult<?>> createNumber(@Valid @RequestBody FreeSwitchNumberRequest request) {
try {
FreeSwitchUserEntity user = userService.createUser(
FreeSwitchNumberEntity user = userService.createNumber(
request.getUsername(),
request.getDomain(),
request.getPassword(),
@@ -56,7 +56,7 @@ public class FreeSwitchUserController {
request.getAccountcode()
);
FreeSwitchUserResponse response = FreeSwitchUserResponse.fromEntitySafe(user);
FreeSwitchNumberResponse response = FreeSwitchNumberResponse.fromEntitySafe(user);
return ResponseEntity.ok(JsonResult.success("用户创建成功", response));
} catch (Exception e) {
log.error("创建用户失败", e);
@@ -68,10 +68,10 @@ public class FreeSwitchUserController {
* 获取用户详情
*/
@GetMapping("/{id}")
public ResponseEntity<JsonResult<?>> getUser(@PathVariable Long id) {
Optional<FreeSwitchUserEntity> user = userService.findById(id);
public ResponseEntity<JsonResult<?>> getNumber(@PathVariable Long id) {
Optional<FreeSwitchNumberEntity> user = userService.findById(id);
if (user.isPresent()) {
FreeSwitchUserResponse response = FreeSwitchUserResponse.fromEntitySafe(user.get());
FreeSwitchNumberResponse response = FreeSwitchNumberResponse.fromEntitySafe(user.get());
return ResponseEntity.ok(JsonResult.success("获取用户详情成功", response));
} else {
return ResponseEntity.notFound().build();
@@ -82,10 +82,10 @@ public class FreeSwitchUserController {
* 根据用户名获取用户
*/
@GetMapping("/username/{username}")
public ResponseEntity<JsonResult<?>> getUserByUsername(@PathVariable String username) {
Optional<FreeSwitchUserEntity> user = userService.findByUsername(username);
public ResponseEntity<JsonResult<?>> getNumberByNumbername(@PathVariable String username) {
Optional<FreeSwitchNumberEntity> user = userService.findByNumbername(username);
if (user.isPresent()) {
FreeSwitchUserResponse response = FreeSwitchUserResponse.fromEntitySafe(user.get());
FreeSwitchNumberResponse response = FreeSwitchNumberResponse.fromEntitySafe(user.get());
return ResponseEntity.ok(JsonResult.success("获取用户详情成功", response));
} else {
return ResponseEntity.notFound().build();
@@ -96,11 +96,11 @@ public class FreeSwitchUserController {
* 根据用户名和域名获取用户
*/
@GetMapping("/username/{username}/domain/{domain}")
public ResponseEntity<JsonResult<?>> getUserByUsernameAndDomain(
public ResponseEntity<JsonResult<?>> getNumberByNumbernameAndDomain(
@PathVariable String username, @PathVariable String domain) {
Optional<FreeSwitchUserEntity> user = userService.findByUsernameAndDomain(username, domain);
Optional<FreeSwitchNumberEntity> user = userService.findByNumbernameAndDomain(username, domain);
if (user.isPresent()) {
FreeSwitchUserResponse response = FreeSwitchUserResponse.fromEntitySafe(user.get());
FreeSwitchNumberResponse response = FreeSwitchNumberResponse.fromEntitySafe(user.get());
return ResponseEntity.ok(JsonResult.success("获取用户详情成功", response));
} else {
return ResponseEntity.notFound().build();
@@ -111,7 +111,7 @@ public class FreeSwitchUserController {
* 获取用户列表分页
*/
@GetMapping
public ResponseEntity<JsonResult<?>> getUsers(
public ResponseEntity<JsonResult<?>> getNumbers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "id") String sortBy,
@@ -121,8 +121,8 @@ public class FreeSwitchUserController {
Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
Pageable pageable = PageRequest.of(page, size, sort);
Page<FreeSwitchUserEntity> userPage = userService.findAll(pageable);
Page<FreeSwitchUserResponse> responsePage = userPage.map(FreeSwitchUserResponse::fromEntitySafe);
Page<FreeSwitchNumberEntity> userPage = userService.findAll(pageable);
Page<FreeSwitchNumberResponse> responsePage = userPage.map(FreeSwitchNumberResponse::fromEntitySafe);
return ResponseEntity.ok(JsonResult.success("获取用户列表成功", responsePage));
}
@@ -131,10 +131,10 @@ public class FreeSwitchUserController {
* 根据域名获取用户列表
*/
@GetMapping("/domain/{domain}")
public ResponseEntity<JsonResult<?>> getUsersByDomain(@PathVariable String domain) {
List<FreeSwitchUserEntity> users = userService.findByDomain(domain);
List<FreeSwitchUserResponse> responses = users.stream()
.map(FreeSwitchUserResponse::fromEntitySafe)
public ResponseEntity<JsonResult<?>> getNumbersByDomain(@PathVariable String domain) {
List<FreeSwitchNumberEntity> users = userService.findByDomain(domain);
List<FreeSwitchNumberResponse> responses = users.stream()
.map(FreeSwitchNumberResponse::fromEntitySafe)
.collect(Collectors.toList());
return ResponseEntity.ok(JsonResult.success("获取域名用户列表成功", responses));
@@ -144,10 +144,10 @@ public class FreeSwitchUserController {
* 获取启用的用户列表
*/
@GetMapping("/enabled")
public ResponseEntity<JsonResult<?>> getEnabledUsers() {
List<FreeSwitchUserEntity> users = userService.findEnabledUsers();
List<FreeSwitchUserResponse> responses = users.stream()
.map(FreeSwitchUserResponse::fromEntitySafe)
public ResponseEntity<JsonResult<?>> getEnabledNumbers() {
List<FreeSwitchNumberEntity> users = userService.findEnabledNumbers();
List<FreeSwitchNumberResponse> responses = users.stream()
.map(FreeSwitchNumberResponse::fromEntitySafe)
.collect(Collectors.toList());
return ResponseEntity.ok(JsonResult.success("获取启用用户列表成功", responses));
@@ -157,10 +157,10 @@ public class FreeSwitchUserController {
* 获取在线的用户列表
*/
@GetMapping("/online")
public ResponseEntity<JsonResult<?>> getOnlineUsers() {
List<FreeSwitchUserEntity> users = userService.findOnlineUsers();
List<FreeSwitchUserResponse> responses = users.stream()
.map(FreeSwitchUserResponse::fromEntitySafe)
public ResponseEntity<JsonResult<?>> getOnlineNumbers() {
List<FreeSwitchNumberEntity> users = userService.findOnlineNumbers();
List<FreeSwitchNumberResponse> responses = users.stream()
.map(FreeSwitchNumberResponse::fromEntitySafe)
.collect(Collectors.toList());
return ResponseEntity.ok(JsonResult.success("获取在线用户列表成功", responses));
@@ -170,10 +170,10 @@ public class FreeSwitchUserController {
* 根据邮箱获取用户列表
*/
@GetMapping("/email/{email}")
public ResponseEntity<JsonResult<?>> getUsersByEmail(@PathVariable String email) {
List<FreeSwitchUserEntity> users = userService.findByEmail(email);
List<FreeSwitchUserResponse> responses = users.stream()
.map(FreeSwitchUserResponse::fromEntitySafe)
public ResponseEntity<JsonResult<?>> getNumbersByEmail(@PathVariable String email) {
List<FreeSwitchNumberEntity> users = userService.findByEmail(email);
List<FreeSwitchNumberResponse> responses = users.stream()
.map(FreeSwitchNumberResponse::fromEntitySafe)
.collect(Collectors.toList());
return ResponseEntity.ok(JsonResult.success("获取用户列表成功", responses));
@@ -183,10 +183,10 @@ public class FreeSwitchUserController {
* 根据账户代码获取用户列表
*/
@GetMapping("/accountcode/{accountcode}")
public ResponseEntity<JsonResult<?>> getUsersByAccountcode(@PathVariable String accountcode) {
List<FreeSwitchUserEntity> users = userService.findByAccountcode(accountcode);
List<FreeSwitchUserResponse> responses = users.stream()
.map(FreeSwitchUserResponse::fromEntitySafe)
public ResponseEntity<JsonResult<?>> getNumbersByAccountcode(@PathVariable String accountcode) {
List<FreeSwitchNumberEntity> users = userService.findByAccountcode(accountcode);
List<FreeSwitchNumberResponse> responses = users.stream()
.map(FreeSwitchNumberResponse::fromEntitySafe)
.collect(Collectors.toList());
return ResponseEntity.ok(JsonResult.success("获取用户列表成功", responses));
@@ -196,11 +196,11 @@ public class FreeSwitchUserController {
* 更新用户
*/
@PutMapping("/{id}")
public ResponseEntity<JsonResult<?>> updateUser(
public ResponseEntity<JsonResult<?>> updateNumber(
@PathVariable Long id,
@Valid @RequestBody FreeSwitchUserRequest request) {
@Valid @RequestBody FreeSwitchNumberRequest request) {
try {
FreeSwitchUserEntity user = userService.updateUser(
FreeSwitchNumberEntity user = userService.updateNumber(
id,
request.getPassword(),
request.getDisplayName(),
@@ -208,7 +208,7 @@ public class FreeSwitchUserController {
request.getAccountcode()
);
FreeSwitchUserResponse response = FreeSwitchUserResponse.fromEntitySafe(user);
FreeSwitchNumberResponse response = FreeSwitchNumberResponse.fromEntitySafe(user);
return ResponseEntity.ok(JsonResult.success("用户更新成功", response));
} catch (Exception e) {
log.error("更新用户失败", e);
@@ -220,9 +220,9 @@ public class FreeSwitchUserController {
* 启用用户
*/
@PutMapping("/{id}/enable")
public ResponseEntity<JsonResult<?>> enableUser(@PathVariable Long id) {
public ResponseEntity<JsonResult<?>> enableNumber(@PathVariable Long id) {
try {
userService.enableUser(id);
userService.enableNumber(id);
return ResponseEntity.ok(JsonResult.success("用户启用成功"));
} catch (Exception e) {
log.error("启用用户失败", e);
@@ -234,9 +234,9 @@ public class FreeSwitchUserController {
* 禁用用户
*/
@PutMapping("/{id}/disable")
public ResponseEntity<JsonResult<?>> disableUser(@PathVariable Long id) {
public ResponseEntity<JsonResult<?>> disableNumber(@PathVariable Long id) {
try {
userService.disableUser(id);
userService.disableNumber(id);
return ResponseEntity.ok(JsonResult.success("用户禁用成功"));
} catch (Exception e) {
log.error("禁用用户失败", e);
@@ -248,13 +248,13 @@ public class FreeSwitchUserController {
* 更新用户注册信息
*/
@PutMapping("/registration")
public ResponseEntity<JsonResult<?>> updateUserRegistration(
public ResponseEntity<JsonResult<?>> updateNumberRegistration(
@RequestParam String username,
@RequestParam String domain,
@RequestParam String registerIp,
@RequestParam(required = false) String userAgent) {
try {
userService.updateUserRegistration(username, domain, registerIp, userAgent);
userService.updateNumberRegistration(username, domain, registerIp, userAgent);
return ResponseEntity.ok(JsonResult.success("用户注册信息更新成功"));
} catch (Exception e) {
log.error("更新用户注册信息失败", e);
@@ -266,9 +266,9 @@ public class FreeSwitchUserController {
* 删除用户
*/
@DeleteMapping("/{id}")
public ResponseEntity<JsonResult<?>> deleteUser(@PathVariable Long id) {
public ResponseEntity<JsonResult<?>> deleteNumber(@PathVariable Long id) {
try {
userService.deleteUser(id);
userService.deleteNumber(id);
return ResponseEntity.ok(JsonResult.success("用户删除成功"));
} catch (Exception e) {
log.error("删除用户失败", e);
@@ -280,11 +280,11 @@ public class FreeSwitchUserController {
* 验证用户密码
*/
@PostMapping("/validate")
public ResponseEntity<JsonResult<?>> validateUserPassword(
public ResponseEntity<JsonResult<?>> validateNumberPassword(
@RequestParam String username,
@RequestParam String domain,
@RequestParam String password) {
boolean valid = userService.validateUserPassword(username, domain, password);
boolean valid = userService.validateNumberPassword(username, domain, password);
return ResponseEntity.ok(JsonResult.success("密码验证完成", valid));
}
@@ -292,12 +292,12 @@ public class FreeSwitchUserController {
* 获取用户统计信息
*/
@GetMapping("/stats")
public ResponseEntity<JsonResult<?>> getUserStats() {
public ResponseEntity<JsonResult<?>> getNumberStats() {
long totalCount = userService.countTotal();
long enabledCount = userService.countEnabled();
long onlineCount = userService.countOnline();
UserStats stats = new UserStats(totalCount, enabledCount, onlineCount);
NumberStats stats = new NumberStats(totalCount, enabledCount, onlineCount);
return ResponseEntity.ok(JsonResult.success("获取用户统计成功", stats));
}
@@ -305,7 +305,7 @@ public class FreeSwitchUserController {
* 根据域名获取用户统计信息
*/
@GetMapping("/stats/domain/{domain}")
public ResponseEntity<JsonResult<?>> getUserStatsByDomain(@PathVariable String domain) {
public ResponseEntity<JsonResult<?>> getNumberStatsByDomain(@PathVariable String domain) {
long domainCount = userService.countByDomain(domain);
return ResponseEntity.ok(JsonResult.success("获取域名用户统计成功", domainCount));
}
@@ -314,22 +314,22 @@ public class FreeSwitchUserController {
* 检查用户名和域名组合是否存在
*/
@GetMapping("/exists")
public ResponseEntity<JsonResult<?>> checkUserExists(
public ResponseEntity<JsonResult<?>> checkNumberExists(
@RequestParam String username,
@RequestParam String domain) {
boolean exists = userService.existsByUsernameAndDomain(username, domain);
boolean exists = userService.existsByNumbernameAndDomain(username, domain);
return ResponseEntity.ok(JsonResult.success("检查用户名成功", exists));
}
/**
* 用户统计信息内部类
*/
public static class UserStats {
public static class NumberStats {
private final long totalCount;
private final long enabledCount;
private final long onlineCount;
public UserStats(long totalCount, long enabledCount, long onlineCount) {
public NumberStats(long totalCount, long enabledCount, long onlineCount) {
this.totalCount = totalCount;
this.enabledCount = enabledCount;
this.onlineCount = onlineCount;

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 19:50:07
* @LastEditTime: 2025-06-08 21:29:40
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import java.time.LocalDateTime;
@@ -40,75 +40,66 @@ import lombok.experimental.SuperBuilder;
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
@EntityListeners({FreeSwitchUserEntityListener.class})
@Table(name = "bytedesk_freeswitch_user")
public class FreeSwitchUserEntity extends BaseEntity {
@EntityListeners({FreeSwitchNumberEntityListener.class})
@Table(name = "bytedesk_freeswitch_number")
public class FreeSwitchNumberEntity extends BaseEntity {
/**
* 用户名SIP用户名
*/
@Column(nullable = false, unique = true, length = 50)
@Column(unique = true)
private String username;
/**
* SIP域名
*/
@Column(nullable = false, length = 100)
private String domain;
/**
* 密码
*/
@Column(nullable = false, length = 255)
private String password;
/**
* 显示名称
*/
@Column(length = 100)
private String displayName;
/**
* 邮箱
*/
@Column(length = 100)
private String email;
/**
* 账户代码
*/
@Column(length = 50)
private String accountcode;
/**
* 是否启用
*/
@Builder.Default
@Column(nullable = false)
@Column(name = "is_enabled")
private Boolean enabled = true;
/**
* 最后注册时间
*/
@Column
private LocalDateTime lastRegister;
/**
* 注册IP地址
*/
@Column(length = 45)
private String registerIp;
/**
* 用户代理
*/
@Column(length = 255)
private String userAgent;
/**
* 备注
*/
@Column(length = 500)
private String remarks;
/**

View File

@@ -0,0 +1,54 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:30:46
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.number;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;
import com.bytedesk.core.utils.ApplicationContextHolder;
import com.bytedesk.freeswitch.config.FreeSwitchEventPublisher;
import com.bytedesk.freeswitch.number.event.FreeSwitchNumberCreateEvent;
import com.bytedesk.freeswitch.number.event.FreeSwitchNumberUpdateEvent;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostUpdate;
import lombok.extern.slf4j.Slf4j;
/**
* FreeSwitch用户实体监听器
*/
@Slf4j
@Component
public class FreeSwitchNumberEntityListener {
@PostPersist
public void postPersist(FreeSwitchNumberEntity entity) {
log.info("FreeSwitch用户创建: username={}, domain={}",
entity.getUsername(), entity.getDomain());
FreeSwitchNumberEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchNumberCreateEvent(cloneEntity));
}
@PostUpdate
public void postUpdate(FreeSwitchNumberEntity entity) {
log.info("FreeSwitch用户更新: username={}, enabled={}",
entity.getUsername(), entity.getEnabled());
FreeSwitchNumberEntity cloneEntity = SerializationUtils.clone(entity);
FreeSwitchEventPublisher freeSwitchEventPublisher = ApplicationContextHolder.getBean(FreeSwitchEventPublisher.class);
freeSwitchEventPublisher.publishEvent(new FreeSwitchNumberUpdateEvent(cloneEntity));
}
}

View File

@@ -0,0 +1,55 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 21:38:22
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.number;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.bytedesk.freeswitch.number.event.FreeSwitchNumberCreateEvent;
import com.bytedesk.freeswitch.number.event.FreeSwitchNumberUpdateEvent;
import lombok.extern.slf4j.Slf4j;
/**
* FreeSwitch事件监听器
*/
@Slf4j
@Component
public class FreeSwitchNumberEventListener {
@Order(1)
@EventListener
public void onFreeSwitchNumberCreateEvent(FreeSwitchNumberCreateEvent event) {
FreeSwitchNumberEntity user = event.getUser();
log.info("收到FreeSwitch用户创建事件: username={}, domain={}",
user.getUsername(), user.getDomain());
// 这里可以添加额外的处理逻辑,比如:
// 1. 发送欢迎消息给新用户
// 2. 添加用户到默认组或会议室
}
@Order(1)
@EventListener
public void onFreeSwitchNumberUpdateEvent(FreeSwitchNumberUpdateEvent event) {
FreeSwitchNumberEntity user = event.getUser();
log.info("收到FreeSwitch用户更新事件: username={}, enabled={}",
user.getUsername(), user.getEnabled());
// 这里可以添加额外的处理逻辑,比如:
// 1. 如果用户被禁用,断开其当前连接
// 2. 更新用户权限
}
}

View File

@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import java.time.LocalDateTime;
@@ -26,7 +26,7 @@ import lombok.Data;
* https://github.com/alibaba/easyexcel
*/
@Data
public class FreeSwitchUserExcel {
public class FreeSwitchNumberExcel {
@ExcelProperty(index = 0, value = "用户名")
@ColumnWidth(20)

View File

@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import java.time.LocalDateTime;
import java.util.List;
@@ -29,63 +29,63 @@ import org.springframework.stereotype.Repository;
* FreeSwitch用户仓库接口
*/
@Repository
public interface FreeSwitchUserRepository extends JpaRepository<FreeSwitchUserEntity, Long>,
JpaSpecificationExecutor<FreeSwitchUserEntity> {
public interface FreeSwitchNumberRepository extends JpaRepository<FreeSwitchNumberEntity, Long>,
JpaSpecificationExecutor<FreeSwitchNumberEntity> {
/**
* 根据UID查找用户
*/
Optional<FreeSwitchUserEntity> findByUid(String uid);
Optional<FreeSwitchNumberEntity> findByUid(String uid);
/**
* 根据用户名查找用户
*/
Optional<FreeSwitchUserEntity> findByUsername(String username);
Optional<FreeSwitchNumberEntity> findByNumbername(String username);
/**
* 根据用户名和域名查找用户
*/
Optional<FreeSwitchUserEntity> findByUsernameAndDomain(String username, String domain);
Optional<FreeSwitchNumberEntity> findByNumbernameAndDomain(String username, String domain);
/**
* 根据邮箱查找用户
*/
List<FreeSwitchUserEntity> findByEmail(String email);
List<FreeSwitchNumberEntity> findByEmail(String email);
/**
* 查找启用的用户
*/
List<FreeSwitchUserEntity> findByEnabledTrue();
List<FreeSwitchNumberEntity> findByEnabledTrue();
/**
* 根据域名查找用户
*/
List<FreeSwitchUserEntity> findByDomain(String domain);
List<FreeSwitchNumberEntity> findByDomain(String domain);
/**
* 根据域名查找用户分页
*/
Page<FreeSwitchUserEntity> findByDomain(String domain, Pageable pageable);
Page<FreeSwitchNumberEntity> findByDomain(String domain, Pageable pageable);
/**
* 根据账户代码查找用户
*/
List<FreeSwitchUserEntity> findByAccountcode(String accountcode);
List<FreeSwitchNumberEntity> findByAccountcode(String accountcode);
/**
* 检查用户名是否存在
*/
boolean existsByUsername(String username);
boolean existsByNumbername(String username);
/**
* 检查用户名和域名组合是否存在
*/
boolean existsByUsernameAndDomain(String username, String domain);
boolean existsByNumbernameAndDomain(String username, String domain);
/**
* 查找在线用户最近指定时间内有注册记录
*/
List<FreeSwitchUserEntity> findByEnabledTrueAndLastRegisterAfter(LocalDateTime cutoffTime);
List<FreeSwitchNumberEntity> findByEnabledTrueAndLastRegisterAfter(LocalDateTime cutoffTime);
/**
* 统计域名下的用户数量
@@ -100,18 +100,18 @@ public interface FreeSwitchUserRepository extends JpaRepository<FreeSwitchUserEn
/**
* 查找在线用户最近5分钟内有注册记录
*/
@Query("SELECT u FROM FreeSwitchUserEntity u WHERE u.enabled = true AND u.lastRegister > :cutoffTime")
List<FreeSwitchUserEntity> findOnlineUsers(@Param("cutoffTime") LocalDateTime cutoffTime);
@Query("SELECT u FROM FreeSwitchNumberEntity u WHERE u.enabled = true AND u.lastRegister > :cutoffTime")
List<FreeSwitchNumberEntity> findOnlineNumbers(@Param("cutoffTime") LocalDateTime cutoffTime);
/**
* 根据用户名模糊搜索
*/
Page<FreeSwitchUserEntity> findByUsernameContainingIgnoreCase(String username, Pageable pageable);
Page<FreeSwitchNumberEntity> findByNumbernameContainingIgnoreCase(String username, Pageable pageable);
/**
* 根据显示名称模糊搜索
*/
Page<FreeSwitchUserEntity> findByDisplayNameContainingIgnoreCase(String displayName, Pageable pageable);
Page<FreeSwitchNumberEntity> findByDisplayNameContainingIgnoreCase(String displayName, Pageable pageable);
/**
* 统计启用的用户数量
@@ -121,13 +121,13 @@ public interface FreeSwitchUserRepository extends JpaRepository<FreeSwitchUserEn
/**
* 统计在线用户数量
*/
@Query("SELECT COUNT(u) FROM FreeSwitchUserEntity u WHERE u.enabled = true AND u.lastRegister > :cutoffTime")
long countOnlineUsers(@Param("cutoffTime") LocalDateTime cutoffTime);
@Query("SELECT COUNT(u) FROM FreeSwitchNumberEntity u WHERE u.enabled = true AND u.lastRegister > :cutoffTime")
long countOnlineNumbers(@Param("cutoffTime") LocalDateTime cutoffTime);
/**
* 更新用户最后注册时间和IP
*/
@Query("UPDATE FreeSwitchUserEntity u SET u.lastRegister = :registerTime, u.registerIp = :registerIp WHERE u.username = :username AND u.domain = :domain")
@Query("UPDATE FreeSwitchNumberEntity u SET u.lastRegister = :registerTime, u.registerIp = :registerIp WHERE u.username = :username AND u.domain = :domain")
int updateLastRegister(@Param("username") String username,
@Param("domain") String domain,
@Param("registerTime") LocalDateTime registerTime,

View File

@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import com.bytedesk.core.base.BaseRequest;
@@ -34,7 +34,7 @@ import lombok.experimental.SuperBuilder;
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class FreeSwitchUserRequest extends BaseRequest {
public class FreeSwitchNumberRequest extends BaseRequest {
/**
* 用户名SIP用户名

View File

@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import com.bytedesk.core.base.BaseResponse;
import lombok.AllArgsConstructor;
@@ -32,7 +32,7 @@ import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class FreeSwitchUserResponse extends BaseResponse {
public class FreeSwitchNumberResponse extends BaseResponse {
/**
* 用户名SIP用户名
@@ -97,12 +97,12 @@ public class FreeSwitchUserResponse extends BaseResponse {
/**
* 从实体安全转换为响应对象
*/
public static FreeSwitchUserResponse fromEntitySafe(FreeSwitchUserEntity entity) {
public static FreeSwitchNumberResponse fromEntitySafe(FreeSwitchNumberEntity entity) {
if (entity == null) {
return null;
}
return FreeSwitchUserResponse.builder()
return FreeSwitchNumberResponse.builder()
.uid(entity.getUid())
.username(entity.getUsername())
.domain(entity.getDomain())

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-08 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 10:00:00
* @LastEditTime: 2025-06-08 21:31:25
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
@@ -29,60 +29,60 @@ import lombok.AllArgsConstructor;
@RestController
@RequestMapping("/api/v1/freeswitch/user")
@AllArgsConstructor
public class FreeSwitchUserRestController extends BaseRestController<FreeSwitchUserRequest> {
public class FreeSwitchNumberRestController extends BaseRestController<FreeSwitchNumberRequest> {
private final FreeSwitchUserRestService freeSwitchUserRestService;
private final FreeSwitchNumberRestService freeSwitchNumberRestService;
@ActionAnnotation(title = "FreeSwitch用户", action = "组织查询", description = "query freeswitch user by org")
@Override
public ResponseEntity<?> queryByOrg(FreeSwitchUserRequest request) {
public ResponseEntity<?> queryByOrg(FreeSwitchNumberRequest request) {
Page<FreeSwitchUserResponse> users = freeSwitchUserRestService.queryByOrg(request);
Page<FreeSwitchNumberResponse> users = freeSwitchNumberRestService.queryByOrg(request);
return ResponseEntity.ok(JsonResult.success(users));
}
@ActionAnnotation(title = "FreeSwitch用户", action = "用户查询", description = "query freeswitch user by user")
@Override
public ResponseEntity<?> queryByUser(FreeSwitchUserRequest request) {
public ResponseEntity<?> queryByUser(FreeSwitchNumberRequest request) {
Page<FreeSwitchUserResponse> users = freeSwitchUserRestService.queryByUser(request);
Page<FreeSwitchNumberResponse> users = freeSwitchNumberRestService.queryByUser(request);
return ResponseEntity.ok(JsonResult.success(users));
}
@ActionAnnotation(title = "FreeSwitch用户", action = "查询", description = "query freeswitch user by uid")
@Override
public ResponseEntity<?> queryByUid(FreeSwitchUserRequest request) {
public ResponseEntity<?> queryByUid(FreeSwitchNumberRequest request) {
FreeSwitchUserResponse user = freeSwitchUserRestService.queryByUid(request);
FreeSwitchNumberResponse user = freeSwitchNumberRestService.queryByUid(request);
return ResponseEntity.ok(JsonResult.success(user));
}
@ActionAnnotation(title = "FreeSwitch用户", action = "创建", description = "create freeswitch user")
@Override
public ResponseEntity<?> create(FreeSwitchUserRequest request) {
public ResponseEntity<?> create(FreeSwitchNumberRequest request) {
FreeSwitchUserResponse user = freeSwitchUserRestService.create(request);
FreeSwitchNumberResponse user = freeSwitchNumberRestService.create(request);
return ResponseEntity.ok(JsonResult.success(user));
}
@ActionAnnotation(title = "FreeSwitch用户", action = "更新", description = "update freeswitch user")
@Override
public ResponseEntity<?> update(FreeSwitchUserRequest request) {
public ResponseEntity<?> update(FreeSwitchNumberRequest request) {
FreeSwitchUserResponse user = freeSwitchUserRestService.update(request);
FreeSwitchNumberResponse user = freeSwitchNumberRestService.update(request);
return ResponseEntity.ok(JsonResult.success(user));
}
@ActionAnnotation(title = "FreeSwitch用户", action = "删除", description = "delete freeswitch user")
@Override
public ResponseEntity<?> delete(FreeSwitchUserRequest request) {
public ResponseEntity<?> delete(FreeSwitchNumberRequest request) {
freeSwitchUserRestService.deleteByUid(request.getUid());
freeSwitchNumberRestService.deleteByUid(request.getUid());
return ResponseEntity.ok(JsonResult.success("删除成功", request.getUid()));
}
@@ -90,12 +90,12 @@ public class FreeSwitchUserRestController extends BaseRestController<FreeSwitchU
@ActionAnnotation(title = "FreeSwitch用户", action = "导出", description = "export freeswitch user to excel")
@Override
@GetMapping("/export")
public Object export(FreeSwitchUserRequest request, HttpServletResponse response) {
public Object export(FreeSwitchNumberRequest request, HttpServletResponse response) {
return exportTemplate(
request,
response,
freeSwitchUserRestService,
FreeSwitchUserExcel.class,
freeSwitchNumberRestService,
FreeSwitchNumberExcel.class,
"FreeSwitch用户",
"freeswitch_user"
);

View File

@@ -1,4 +1,4 @@
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import java.util.Optional;
@@ -24,9 +24,9 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
@AllArgsConstructor
public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwitchUserEntity, FreeSwitchUserRequest, FreeSwitchUserResponse, FreeSwitchUserExcel> {
public class FreeSwitchNumberRestService extends BaseRestServiceWithExcel<FreeSwitchNumberEntity, FreeSwitchNumberRequest, FreeSwitchNumberResponse, FreeSwitchNumberExcel> {
private final FreeSwitchUserRepository freeSwitchUserRepository;
private final FreeSwitchNumberRepository freeSwitchNumberRepository;
private final ModelMapper modelMapper;
@@ -35,51 +35,51 @@ public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwit
private final AuthService authService;
@Override
public Page<FreeSwitchUserEntity> queryByOrgEntity(FreeSwitchUserRequest request) {
public Page<FreeSwitchNumberEntity> queryByOrgEntity(FreeSwitchNumberRequest request) {
Pageable pageable = request.getPageable();
Specification<FreeSwitchUserEntity> specification = FreeSwitchUserSpecification.search(request);
return freeSwitchUserRepository.findAll(specification, pageable);
Specification<FreeSwitchNumberEntity> specification = FreeSwitchNumberSpecification.search(request);
return freeSwitchNumberRepository.findAll(specification, pageable);
}
@Override
public Page<FreeSwitchUserResponse> queryByOrg(FreeSwitchUserRequest request) {
Page<FreeSwitchUserEntity> entities = queryByOrgEntity(request);
public Page<FreeSwitchNumberResponse> queryByOrg(FreeSwitchNumberRequest request) {
Page<FreeSwitchNumberEntity> entities = queryByOrgEntity(request);
return entities.map(this::convertToResponse);
}
public Page<FreeSwitchUserEntity> queryByUserEntity(FreeSwitchUserRequest request) {
UserEntity user = authService.getUser();
request.setOrgUid(user.getOrgUid());
public Page<FreeSwitchNumberEntity> queryByNumberEntity(FreeSwitchNumberRequest request) {
// NumberEntity user = authService.getUser();
// request.setOrgUid(user.getOrgUid());
return queryByOrgEntity(request);
}
@Override
public Page<FreeSwitchUserResponse> queryByUser(FreeSwitchUserRequest request) {
Page<FreeSwitchUserEntity> entities = queryByUserEntity(request);
public Page<FreeSwitchNumberResponse> queryByUser(FreeSwitchNumberRequest request) {
Page<FreeSwitchNumberEntity> entities = queryByNumberEntity(request);
return entities.map(this::convertToResponse);
}
@Override
public Optional<FreeSwitchUserEntity> findByUid(String uid) {
return freeSwitchUserRepository.findByUid(uid);
public Optional<FreeSwitchNumberEntity> findByUid(String uid) {
return freeSwitchNumberRepository.findByUid(uid);
}
@Override
public FreeSwitchUserResponse convertToResponse(FreeSwitchUserEntity entity) {
return modelMapper.map(entity, FreeSwitchUserResponse.class);
public FreeSwitchNumberResponse convertToResponse(FreeSwitchNumberEntity entity) {
return modelMapper.map(entity, FreeSwitchNumberResponse.class);
}
public FreeSwitchUserEntity convertToEntity(FreeSwitchUserRequest request) {
return modelMapper.map(request, FreeSwitchUserEntity.class);
public FreeSwitchNumberEntity convertToEntity(FreeSwitchNumberRequest request) {
return modelMapper.map(request, FreeSwitchNumberEntity.class);
}
@Override
public FreeSwitchUserExcel convertToExcel(FreeSwitchUserEntity entity) {
return modelMapper.map(entity, FreeSwitchUserExcel.class);
public FreeSwitchNumberExcel convertToExcel(FreeSwitchNumberEntity entity) {
return modelMapper.map(entity, FreeSwitchNumberExcel.class);
}
@Override
public FreeSwitchUserResponse create(FreeSwitchUserRequest request) {
public FreeSwitchNumberResponse create(FreeSwitchNumberRequest request) {
UserEntity user = authService.getUser();
if (!StringUtils.hasText(request.getOrgUid())) {
request.setOrgUid(user.getOrgUid());
@@ -90,15 +90,15 @@ public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwit
}
// 检查用户名是否已存在
if (freeSwitchUserRepository.existsByUsernameAndDomain(request.getUsername(), request.getDomain())) {
if (freeSwitchNumberRepository.existsByNumbernameAndDomain(request.getUsername(), request.getDomain())) {
throw new RuntimeException("用户名已存在: " + request.getUsername() + "@" + request.getDomain());
}
FreeSwitchUserEntity entity = convertToEntity(request);
FreeSwitchNumberEntity entity = convertToEntity(request);
entity.setLevel(LevelEnum.PLATFORM.name());
entity.setPlatform(BytedeskConsts.PLATFORM_BYTEDESK);
FreeSwitchUserEntity savedEntity = save(entity);
FreeSwitchNumberEntity savedEntity = save(entity);
if (savedEntity == null) {
throw new RuntimeException("创建FreeSwitch用户失败");
}
@@ -107,13 +107,13 @@ public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwit
}
@Override
public FreeSwitchUserResponse update(FreeSwitchUserRequest request) {
Optional<FreeSwitchUserEntity> optional = findByUid(request.getUid());
public FreeSwitchNumberResponse update(FreeSwitchNumberRequest request) {
Optional<FreeSwitchNumberEntity> optional = findByUid(request.getUid());
if (!optional.isPresent()) {
throw new RuntimeException("FreeSwitch用户不存在");
}
FreeSwitchUserEntity entity = optional.get();
FreeSwitchNumberEntity entity = optional.get();
// 更新字段
if (StringUtils.hasText(request.getDisplayName())) {
@@ -132,7 +132,7 @@ public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwit
entity.setRemarks(request.getRemarks());
}
FreeSwitchUserEntity updatedEntity = save(entity);
FreeSwitchNumberEntity updatedEntity = save(entity);
if (updatedEntity == null) {
throw new RuntimeException("更新FreeSwitch用户失败");
}
@@ -141,22 +141,22 @@ public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwit
}
@Override
public FreeSwitchUserEntity save(FreeSwitchUserEntity entity) {
public FreeSwitchNumberEntity save(FreeSwitchNumberEntity entity) {
try {
return freeSwitchUserRepository.save(entity);
return freeSwitchNumberRepository.save(entity);
} catch (ObjectOptimisticLockingFailureException e) {
return handleOptimisticLockingFailureException(e, entity);
}
}
@Override
public FreeSwitchUserEntity doSave(FreeSwitchUserEntity entity) {
return freeSwitchUserRepository.save(entity);
public FreeSwitchNumberEntity doSave(FreeSwitchNumberEntity entity) {
return freeSwitchNumberRepository.save(entity);
}
@Override
public void deleteByUid(String uid) {
Optional<FreeSwitchUserEntity> optional = findByUid(uid);
Optional<FreeSwitchNumberEntity> optional = findByUid(uid);
optional.ifPresent(entity -> {
entity.setDeleted(true);
save(entity);
@@ -164,14 +164,14 @@ public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwit
}
@Override
public void delete(FreeSwitchUserRequest request) {
public void delete(FreeSwitchNumberRequest request) {
deleteByUid(request.getUid());
}
@Override
@Cacheable(value = "freeswitch_user", key = "#uid", unless = "#result == null")
public FreeSwitchUserResponse queryByUid(FreeSwitchUserRequest request) {
Optional<FreeSwitchUserEntity> optional = findByUid(request.getUid());
public FreeSwitchNumberResponse queryByUid(FreeSwitchNumberRequest request) {
Optional<FreeSwitchNumberEntity> optional = findByUid(request.getUid());
if (optional.isPresent()) {
return convertToResponse(optional.get());
}
@@ -179,13 +179,13 @@ public class FreeSwitchUserRestService extends BaseRestServiceWithExcel<FreeSwit
}
@Override
public FreeSwitchUserEntity handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, FreeSwitchUserEntity entity) {
public FreeSwitchNumberEntity handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, FreeSwitchNumberEntity entity) {
log.warn("FreeSwitch用户保存时发生乐观锁异常 uid: {}, version: {}", entity.getUid(), entity.getVersion());
// 重新查询最新版本并重试
try {
Optional<FreeSwitchUserEntity> latest = findByUid(entity.getUid());
Optional<FreeSwitchNumberEntity> latest = findByUid(entity.getUid());
if (latest.isPresent()) {
FreeSwitchUserEntity latestEntity = latest.get();
FreeSwitchNumberEntity latestEntity = latest.get();
// 将当前修改应用到最新版本
latestEntity.setPassword(entity.getPassword());
latestEntity.setEnabled(entity.getEnabled());

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 18:47:56
* @LastEditTime: 2025-06-08 21:32:17
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -33,17 +33,17 @@ import java.util.Optional;
@Service
@AllArgsConstructor
@ConditionalOnProperty(name = "bytedesk.freeswitch.enabled", havingValue = "true")
public class FreeSwitchUserService {
public class FreeSwitchNumberService {
private final FreeSwitchUserRepository userRepository;
private final FreeSwitchNumberRepository userRepository;
/**
* 创建新用户
*/
@Transactional
public FreeSwitchUserEntity createUser(String username, String domain, String password,
public FreeSwitchNumberEntity createNumber(String username, String domain, String password,
String displayName, String email, String accountcode) {
FreeSwitchUserEntity user = FreeSwitchUserEntity.builder()
FreeSwitchNumberEntity user = FreeSwitchNumberEntity.builder()
.username(username)
.domain(domain)
.password(password)
@@ -53,7 +53,7 @@ public class FreeSwitchUserService {
.enabled(true)
.build();
FreeSwitchUserEntity saved = userRepository.save(user);
FreeSwitchNumberEntity saved = userRepository.save(user);
log.info("创建用户: {} (ID: {}) -> {}@{}", username, saved.getId(), username, domain);
return saved;
}
@@ -61,49 +61,49 @@ public class FreeSwitchUserService {
/**
* 根据ID查找用户
*/
public Optional<FreeSwitchUserEntity> findById(Long id) {
public Optional<FreeSwitchNumberEntity> findById(Long id) {
return userRepository.findById(id);
}
/**
* 根据用户名查找用户
*/
public Optional<FreeSwitchUserEntity> findByUsername(String username) {
return userRepository.findByUsername(username);
public Optional<FreeSwitchNumberEntity> findByNumbername(String username) {
return userRepository.findByNumbername(username);
}
/**
* 根据用户名和域名查找用户
*/
public Optional<FreeSwitchUserEntity> findByUsernameAndDomain(String username, String domain) {
return userRepository.findByUsernameAndDomain(username, domain);
public Optional<FreeSwitchNumberEntity> findByNumbernameAndDomain(String username, String domain) {
return userRepository.findByNumbernameAndDomain(username, domain);
}
/**
* 获取指定域名的用户列表
*/
public List<FreeSwitchUserEntity> findByDomain(String domain) {
public List<FreeSwitchNumberEntity> findByDomain(String domain) {
return userRepository.findByDomain(domain);
}
/**
* 获取所有启用的用户
*/
public List<FreeSwitchUserEntity> findEnabledUsers() {
public List<FreeSwitchNumberEntity> findEnabledNumbers() {
return userRepository.findByEnabledTrue();
}
/**
* 获取所有用户分页
*/
public Page<FreeSwitchUserEntity> findAll(Pageable pageable) {
public Page<FreeSwitchNumberEntity> findAll(Pageable pageable) {
return userRepository.findAll(pageable);
}
/**
* 根据域名查找用户分页
*/
public Page<FreeSwitchUserEntity> findByDomain(String domain, Pageable pageable) {
public Page<FreeSwitchNumberEntity> findByDomain(String domain, Pageable pageable) {
return userRepository.findByDomain(domain, pageable);
}
@@ -111,9 +111,9 @@ public class FreeSwitchUserService {
* 更新用户信息
*/
@Transactional
public FreeSwitchUserEntity updateUser(Long id, String password, String displayName,
public FreeSwitchNumberEntity updateNumber(Long id, String password, String displayName,
String email, String accountcode) {
FreeSwitchUserEntity user = userRepository.findById(id)
FreeSwitchNumberEntity user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("用户不存在: " + id));
if (password != null) user.setPassword(password);
@@ -121,7 +121,7 @@ public class FreeSwitchUserService {
if (email != null) user.setEmail(email);
if (accountcode != null) user.setAccountcode(accountcode);
FreeSwitchUserEntity saved = userRepository.save(user);
FreeSwitchNumberEntity saved = userRepository.save(user);
log.info("更新用户: {} (ID: {})", user.getUsername(), id);
return saved;
}
@@ -130,8 +130,8 @@ public class FreeSwitchUserService {
* 启用用户
*/
@Transactional
public void enableUser(Long id) {
FreeSwitchUserEntity user = userRepository.findById(id)
public void enableNumber(Long id) {
FreeSwitchNumberEntity user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("用户不存在: " + id));
user.setEnabled(true);
@@ -143,8 +143,8 @@ public class FreeSwitchUserService {
* 禁用用户
*/
@Transactional
public void disableUser(Long id) {
FreeSwitchUserEntity user = userRepository.findById(id)
public void disableNumber(Long id) {
FreeSwitchNumberEntity user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("用户不存在: " + id));
user.setEnabled(false);
@@ -156,10 +156,10 @@ public class FreeSwitchUserService {
* 更新用户注册信息
*/
@Transactional
public void updateUserRegistration(String username, String domain, String registerIp, String userAgent) {
Optional<FreeSwitchUserEntity> userOpt = userRepository.findByUsernameAndDomain(username, domain);
public void updateNumberRegistration(String username, String domain, String registerIp, String userAgent) {
Optional<FreeSwitchNumberEntity> userOpt = userRepository.findByNumbernameAndDomain(username, domain);
if (userOpt.isPresent()) {
FreeSwitchUserEntity user = userOpt.get();
FreeSwitchNumberEntity user = userOpt.get();
user.setLastRegister(LocalDateTime.now());
user.setRegisterIp(registerIp);
user.setUserAgent(userAgent);
@@ -174,8 +174,8 @@ public class FreeSwitchUserService {
* 删除用户
*/
@Transactional
public void deleteUser(Long id) {
FreeSwitchUserEntity user = userRepository.findById(id)
public void deleteNumber(Long id) {
FreeSwitchNumberEntity user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("用户不存在: " + id));
userRepository.delete(user);
@@ -185,7 +185,7 @@ public class FreeSwitchUserService {
/**
* 获取在线用户列表
*/
public List<FreeSwitchUserEntity> findOnlineUsers() {
public List<FreeSwitchNumberEntity> findOnlineNumbers() {
LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(5);
return userRepository.findByEnabledTrueAndLastRegisterAfter(cutoffTime);
}
@@ -193,14 +193,14 @@ public class FreeSwitchUserService {
/**
* 根据邮箱查找用户
*/
public List<FreeSwitchUserEntity> findByEmail(String email) {
public List<FreeSwitchNumberEntity> findByEmail(String email) {
return userRepository.findByEmail(email);
}
/**
* 根据账户代码查找用户
*/
public List<FreeSwitchUserEntity> findByAccountcode(String accountcode) {
public List<FreeSwitchNumberEntity> findByAccountcode(String accountcode) {
return userRepository.findByAccountcode(accountcode);
}
@@ -236,17 +236,17 @@ public class FreeSwitchUserService {
/**
* 检查用户名和域名组合是否存在
*/
public boolean existsByUsernameAndDomain(String username, String domain) {
return userRepository.existsByUsernameAndDomain(username, domain);
public boolean existsByNumbernameAndDomain(String username, String domain) {
return userRepository.existsByNumbernameAndDomain(username, domain);
}
/**
* 验证用户密码
*/
public boolean validateUserPassword(String username, String domain, String password) {
Optional<FreeSwitchUserEntity> userOpt = userRepository.findByUsernameAndDomain(username, domain);
public boolean validateNumberPassword(String username, String domain, String password) {
Optional<FreeSwitchNumberEntity> userOpt = userRepository.findByNumbernameAndDomain(username, domain);
if (userOpt.isPresent()) {
FreeSwitchUserEntity user = userOpt.get();
FreeSwitchNumberEntity user = userOpt.get();
return user.getEnabled() && user.getPassword().equals(password);
}
return false;
@@ -257,9 +257,9 @@ public class FreeSwitchUserService {
*/
@Transactional
public void updateLastRegistration(String username, LocalDateTime lastRegistration) {
Optional<FreeSwitchUserEntity> userOpt = userRepository.findByUsername(username);
Optional<FreeSwitchNumberEntity> userOpt = userRepository.findByNumbername(username);
if (userOpt.isPresent()) {
FreeSwitchUserEntity user = userOpt.get();
FreeSwitchNumberEntity user = userOpt.get();
user.setLastRegister(lastRegistration);
userRepository.save(user);
log.debug("更新用户 {} 最后注册时间: {}", username, lastRegistration);

View File

@@ -11,7 +11,7 @@
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import java.util.ArrayList;
import java.util.List;
@@ -25,9 +25,9 @@ import jakarta.persistence.criteria.Predicate;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FreeSwitchUserSpecification extends BaseSpecification {
public class FreeSwitchNumberSpecification extends BaseSpecification {
public static Specification<FreeSwitchUserEntity> search(FreeSwitchUserRequest request) {
public static Specification<FreeSwitchNumberEntity> search(FreeSwitchNumberRequest request) {
log.info("request: {}", request);
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 22:10:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.number.event;
import com.bytedesk.freeswitch.number.FreeSwitchNumberEntity;
import lombok.Getter;
@Getter
public class FreeSwitchNumberCreateEvent {
private final FreeSwitchNumberEntity user;
public FreeSwitchNumberCreateEvent(FreeSwitchNumberEntity user) {
this.user = user;
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-08 22:10:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.number.event;
import com.bytedesk.freeswitch.number.FreeSwitchNumberEntity;
import lombok.Getter;
@Getter
public class FreeSwitchNumberUpdateEvent {
private final FreeSwitchNumberEntity user;
public FreeSwitchNumberUpdateEvent(FreeSwitchNumberEntity user) {
this.user = user;
}
}

View File

@@ -1,5 +1,5 @@
@NonNullApi
package com.bytedesk.freeswitch.user;
package com.bytedesk.freeswitch.number;
import org.springframework.lang.NonNullApi;

View File

@@ -1,40 +0,0 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-06-09 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-09 10:00:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.freeswitch.user;
import org.springframework.stereotype.Component;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostUpdate;
import lombok.extern.slf4j.Slf4j;
/**
* FreeSwitch用户实体监听器
*/
@Slf4j
@Component
public class FreeSwitchUserEntityListener {
@PostPersist
public void postPersist(FreeSwitchUserEntity entity) {
log.info("FreeSwitch用户创建: username={}, domain={}",
entity.getUsername(), entity.getDomain());
}
@PostUpdate
public void postUpdate(FreeSwitchUserEntity entity) {
log.info("FreeSwitch用户更新: username={}, enabled={}",
entity.getUsername(), entity.getEnabled());
}
}