add call recording time
This commit is contained in:
parent
913c1b6789
commit
9bf88d9f5f
@ -2,6 +2,7 @@ package com.pudonghot.yo.model.domain;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import java.util.Date;
|
||||||
import me.chyxion.tigon.mybatis.Table;
|
import me.chyxion.tigon.mybatis.Table;
|
||||||
import me.chyxion.tigon.mybatis.Transient;
|
import me.chyxion.tigon.mybatis.Transient;
|
||||||
import me.chyxion.tigon.mybatis.NotUpdate;
|
import me.chyxion.tigon.mybatis.NotUpdate;
|
||||||
@ -24,6 +25,8 @@ public class CallRecording extends BaseDomain {
|
|||||||
private String connId;
|
private String connId;
|
||||||
@NotUpdate
|
@NotUpdate
|
||||||
private String path;
|
private String path;
|
||||||
|
@NotUpdate
|
||||||
|
private Date callTime;
|
||||||
@Transient
|
@Transient
|
||||||
private String url;
|
private String url;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package com.pudonghot.yo.fsagent.service.impl;
|
package com.pudonghot.yo.fsagent.service.impl;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import com.pudonghot.yo.mapper.TenantMapper;
|
import com.pudonghot.yo.mapper.TenantMapper;
|
||||||
import com.pudonghot.yo.model.domain.Tenant;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import com.pudonghot.yo.mapper.CallRecordingMapper;
|
import com.pudonghot.yo.mapper.CallRecordingMapper;
|
||||||
import com.pudonghot.yo.model.domain.CallRecording;
|
import com.pudonghot.yo.model.domain.CallRecording;
|
||||||
import com.pudonghot.yo.common.httpclient.HttpClient;
|
import com.pudonghot.yo.common.httpclient.HttpClient;
|
||||||
@ -17,7 +21,6 @@ import org.springframework.scheduling.annotation.Async;
|
|||||||
import com.pudonghot.yo.fsagent.service.RecordingService;
|
import com.pudonghot.yo.fsagent.service.RecordingService;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import com.pudonghot.yo.common.httpclient.HttpRequestResult;
|
|
||||||
import com.pudonghot.yo.common.httpclient.RequestBodyParams;
|
import com.pudonghot.yo.common.httpclient.RequestBodyParams;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
@ -47,6 +50,10 @@ public class RecordingServiceImpl
|
|||||||
@Value("${yo.fsagent.recording.file-ext:.ogg}")
|
@Value("${yo.fsagent.recording.file-ext:.ogg}")
|
||||||
private String recordingFileExt;
|
private String recordingFileExt;
|
||||||
|
|
||||||
|
private final Pattern PATTERN_REC_LOC =
|
||||||
|
Pattern.compile("^\\w+_(\\d{4}-\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2})_\\w+-\\w+\\.\\w+$");
|
||||||
|
private final String REC_CALL_TIME_PATTERN = "yyyy-MM-dd_HH-mm-ss";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@ -54,7 +61,7 @@ public class RecordingServiceImpl
|
|||||||
@Override
|
@Override
|
||||||
public void postRecording(final Integer tenantId, final String location) {
|
public void postRecording(final Integer tenantId, final String location) {
|
||||||
log.info("Post recording file [{}].", location);
|
log.info("Post recording file [{}].", location);
|
||||||
final File file = new File(location);
|
val file = new File(location);
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
log.warn("Recording file [{}] does not exist.", file);
|
log.warn("Recording file [{}] does not exist.", file);
|
||||||
@ -63,19 +70,21 @@ public class RecordingServiceImpl
|
|||||||
|
|
||||||
uploadRec(file);
|
uploadRec(file);
|
||||||
|
|
||||||
final String name = file.getName();
|
val name = file.getName();
|
||||||
|
val connId = name.substring(0, name.indexOf("_"));
|
||||||
|
|
||||||
final String connId = name.substring(0, name.indexOf("_"));
|
|
||||||
if (StringUtils.isNotBlank(connId)) {
|
if (StringUtils.isNotBlank(connId)) {
|
||||||
final Tenant tenant = tenantMapper.find(tenantId);
|
val tenant = tenantMapper.find(tenantId);
|
||||||
Assert.state(tenant != null,
|
Assert.state(tenant != null,
|
||||||
() -> "No tenant [" + tenantId + "] found");
|
() -> "No tenant [" + tenantId + "] found");
|
||||||
|
|
||||||
final CallRecording callRec = new CallRecording();
|
val callRec = new CallRecording();
|
||||||
callRec.setTenantId(tenantId);
|
callRec.setTenantId(tenantId);
|
||||||
callRec.setTenantCode(tenant.getCode());
|
callRec.setTenantCode(tenant.getCode());
|
||||||
callRec.setConnId(connId);
|
callRec.setConnId(connId);
|
||||||
|
callRec.setCallTime(getCallTime(name));
|
||||||
callRec.setPath(name);
|
callRec.setPath(name);
|
||||||
|
|
||||||
log.info("Insert call [{}] recording [{}].", connId, callRec);
|
log.info("Insert call [{}] recording [{}].", connId, callRec);
|
||||||
callRecordingMapper.insert(callRec);
|
callRecordingMapper.insert(callRec);
|
||||||
}
|
}
|
||||||
@ -92,10 +101,10 @@ public class RecordingServiceImpl
|
|||||||
final String callerNumber,
|
final String callerNumber,
|
||||||
final String calledNumber) {
|
final String calledNumber) {
|
||||||
|
|
||||||
final long now = System.currentTimeMillis();
|
val now = System.currentTimeMillis();
|
||||||
return recDir + DateFormatUtils.format(now, "/yyyy/MM/dd/HH/") +
|
return recDir + DateFormatUtils.format(now, "/yyyy/MM/dd/HH/") +
|
||||||
connId + "_" +
|
connId + "_" +
|
||||||
DateFormatUtils.format(now, "yyyy-MM-dd_HH-mm-ss") + "_" +
|
DateFormatUtils.format(now, REC_CALL_TIME_PATTERN) + "_" +
|
||||||
callerNumber + "-" +
|
callerNumber + "-" +
|
||||||
calledNumber +
|
calledNumber +
|
||||||
recordingFileExt;
|
recordingFileExt;
|
||||||
@ -115,16 +124,28 @@ public class RecordingServiceImpl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String url = fileServerBasePath + file.getName();
|
val url = fileServerBasePath + file.getName();
|
||||||
final RequestBodyParams<File> params =
|
val params = new RequestBodyParams<File>(file);
|
||||||
new RequestBodyParams<>(file);
|
|
||||||
params.setHeaders(REQ_HEADERS);
|
params.setHeaders(REQ_HEADERS);
|
||||||
final HttpRequestResult result = httpClient.put(url, params);
|
val result = httpClient.put(url, params);
|
||||||
final int status = result.getStatus();
|
val status = result.getStatus();
|
||||||
log.info("Upload recording file [{}] result [{}]", url, status);
|
log.info("Upload recording file [{}] result [{}]", url, status);
|
||||||
if (status >= 200 && status < 300) {
|
if (status >= 200 && status < 300) {
|
||||||
log.info("Upload recording file [{}] successfully, delete file.", file);
|
log.info("Upload recording file [{}] successfully, delete file.", file);
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
Date getCallTime(final String recName) {
|
||||||
|
val m = PATTERN_REC_LOC.matcher(recName);
|
||||||
|
if (m.matches()) {
|
||||||
|
val callTime = m.group(1);
|
||||||
|
log.debug("Rec [{}] call time [{}] parsed.", recName, callTime);
|
||||||
|
return DateUtils.parseDate(callTime, REC_CALL_TIME_PATTERN);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Rec [{}] no call time parsed, use now.", recName);
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package com.pudonghot.yo.fsagent;
|
package com.pudonghot.yo.fsagent.service.impl;
|
||||||
|
|
||||||
import com.pudonghot.yo.YoServer;
|
import lombok.val;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import com.pudonghot.yo.YoServer;
|
||||||
import com.pudonghot.yo.fsagent.service.RecordingService;
|
import com.pudonghot.yo.fsagent.service.RecordingService;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Donghuang
|
* @author Donghuang
|
||||||
* @date Jul 24, 2020 15:38:41
|
* @date Jul 24, 2020 15:38:41
|
||||||
@ -19,11 +22,18 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||||||
public class RecordingServiceTest {
|
public class RecordingServiceTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RecordingService recordingService;
|
private RecordingServiceImpl recordingService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRecordingLoc() {
|
public void testRecordingLoc() {
|
||||||
log.info("Rec location [{}].",
|
log.info("Rec location [{}].",
|
||||||
recordingService.recLoc("AAA", "donghuang", "bingpo"));
|
recordingService.recLoc("AAA", "donghuang", "bingpo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCallTime() {
|
||||||
|
val name = "615ff67285301479ccb256d7_2021-10-08_15-43-01_800435-0ee07e1711b367df06796327c05b7ec7.mp3";
|
||||||
|
val callTime = recordingService.getCallTime(name);
|
||||||
|
log.info("Call time [{}].", callTime);
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,8 +2,13 @@ package com.pudonghot.yo.state;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
|
||||||
@ -31,4 +36,15 @@ public class TestDriver {
|
|||||||
log.info("Yesterday [{}].", DateUtils.addDays(
|
log.info("Yesterday [{}].", DateUtils.addDays(
|
||||||
DateUtils.truncate(new Date(), Calendar.DATE), -1));
|
DateUtils.truncate(new Date(), Calendar.DATE), -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRecLoc() {
|
||||||
|
val name = "615ff67285301479ccb256d7_2021-10-08_15-43-01_800435-0ee07e1711b367df06796327c05b7ec7.mp3";
|
||||||
|
val pattern = Pattern.compile("^\\w+_(\\d{4}-\\d{2}-\\d{2})_(\\d{2})-(\\d{2})-(\\d{2})_\\w+-\\w+\\.\\w+$");
|
||||||
|
val m = pattern.matcher(name);
|
||||||
|
if (m.matches()) {
|
||||||
|
log.info("Date: {}.", m.group(1));
|
||||||
|
log.info("Time: {}:{}:{}.", m.group(2), m.group(3), m.group(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
102
server/src/test/resources/application.yml
Normal file
102
server/src/test/resources/application.yml
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
server:
|
||||||
|
port: 8083
|
||||||
|
error:
|
||||||
|
include-stacktrace: ALWAYS
|
||||||
|
shutdown: GRACEFUL
|
||||||
|
|
||||||
|
tigon:
|
||||||
|
web:
|
||||||
|
jsonview:
|
||||||
|
success-key: success
|
||||||
|
code-key: retcode
|
||||||
|
code-type: string
|
||||||
|
message-key: message
|
||||||
|
data-key:
|
||||||
|
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: yo-server
|
||||||
|
lifecycle:
|
||||||
|
# Allow grace timeout period for 42 seconds
|
||||||
|
timeout-per-shutdown-phase: 42s
|
||||||
|
freemarker:
|
||||||
|
cache: false
|
||||||
|
settings:
|
||||||
|
number_format: computer
|
||||||
|
suffix: ''
|
||||||
|
template-loader-path: classpath:/templates
|
||||||
|
jackson:
|
||||||
|
serialization:
|
||||||
|
fail-on-empty-beans: false
|
||||||
|
write-dates-as-timestamps: true
|
||||||
|
time-zone: GMT+8
|
||||||
|
redis:
|
||||||
|
host: localhost
|
||||||
|
port: 6379
|
||||||
|
password: 123456
|
||||||
|
redisson:
|
||||||
|
lock-watchdog-timeout: 5000
|
||||||
|
|
||||||
|
dubbo:
|
||||||
|
application:
|
||||||
|
qos-accept-foreign-ip: false
|
||||||
|
qos-enable: true
|
||||||
|
qos-port: 22222
|
||||||
|
protocol:
|
||||||
|
name: dubbo
|
||||||
|
port: -1
|
||||||
|
provider:
|
||||||
|
retries: 0
|
||||||
|
timeout: 24000
|
||||||
|
registry:
|
||||||
|
address: zookeeper://localhost:2181
|
||||||
|
file: ${user.home}/dubbo-cache/${spring.application.name}/dubbo.cache
|
||||||
|
scan:
|
||||||
|
base-packages: com.pudonghot.yo
|
||||||
|
|
||||||
|
yo:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mysql://localhost/yoqw?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
|
||||||
|
username: yoqw
|
||||||
|
password: yoqw_query!
|
||||||
|
esl:
|
||||||
|
client:
|
||||||
|
host: 192.168.3.7
|
||||||
|
freeswitch:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mysql://localhost/fs_dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
|
||||||
|
username: freeswitch
|
||||||
|
password: RR!h5IpirsnJ
|
||||||
|
fsagent:
|
||||||
|
agent-status:
|
||||||
|
audio:
|
||||||
|
not-ready:
|
||||||
|
ok: http://172.16.46.35/voice/20191126/5ddcd2ca82745b00016922d1.wav
|
||||||
|
err: http://172.16.46.35/voice/20191126/5ddcfef282745b00016922d9.wav
|
||||||
|
ready:
|
||||||
|
ok: http://172.16.46.35/voice/20191126/5ddcd2c882745b00016922cd.wav
|
||||||
|
err: http://172.16.46.35/voice/20191126/5ddcfef182745b00016922d5.wav
|
||||||
|
dubbo:
|
||||||
|
service:
|
||||||
|
version: 1.0.0
|
||||||
|
recording-server:
|
||||||
|
base-path: http://172.16.52.80/fs/rec/
|
||||||
|
campaign:
|
||||||
|
task-scheduler:
|
||||||
|
fixed-rate: 8000
|
||||||
|
dial-batch: 36
|
||||||
|
calling-list:
|
||||||
|
task-scheduler:
|
||||||
|
fixed-rate: 240000
|
||||||
|
batch-cron: 12 12 0 * * *
|
||||||
|
citic:
|
||||||
|
feign:
|
||||||
|
# base-url: http://stsl.wldmz.cc/stsl-web-partner
|
||||||
|
base-url: http://e.test.bank.ecitic.com/citiccard/stsl-web-partner
|
||||||
|
path:
|
||||||
|
calling-list: /call-data/taskdata/dx-hzqw
|
||||||
|
black-list-verify: /resource/black-list/verify
|
||||||
|
black-list-batch-verify: /resource/black-list/batch-verify
|
||||||
|
black-list:
|
||||||
|
verify: true
|
||||||
|
batch-verify: true
|
Loading…
x
Reference in New Issue
Block a user