整理代码
This commit is contained in:
@@ -5,9 +5,9 @@ import ink.snowflake.server.gson
|
||||
import ink.snowflake.server.model.request.ChatRequest
|
||||
import ink.snowflake.server.model.response.ChatResponse
|
||||
import ink.snowflake.server.model.response.BaseResponse
|
||||
import ink.snowflake.server.utils.TokenUtils.getUserIdByToken
|
||||
import ink.snowflake.server.utils.WebSocketManager
|
||||
import ink.snowflake.server.utils.dao.ChatRecordsDao
|
||||
import ink.snowflake.server.utils.getUserIdByToken
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.request.*
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.google.gson.Gson
|
||||
import ink.snowflake.server.SERVER_PATH_FRP
|
||||
import ink.snowflake.server.model.request.DevicesInfoRequest
|
||||
import ink.snowflake.server.model.response.*
|
||||
import ink.snowflake.server.utils.runCommand
|
||||
import ink.snowflake.server.utils.CommandUtils.runCommand
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.plugins.auth.Auth
|
||||
|
||||
@@ -8,9 +8,13 @@ import ink.snowflake.server.model.request.RefreshTokenRequest
|
||||
import ink.snowflake.server.model.request.RegisterRequest
|
||||
import ink.snowflake.server.model.response.*
|
||||
import ink.snowflake.server.utils.AppConfig
|
||||
import ink.snowflake.server.utils.EmailUtils.generateVerificationCode
|
||||
import ink.snowflake.server.utils.EmailUtils.sendVerificationEmail
|
||||
import ink.snowflake.server.utils.TokenUtils.generateAccessToken
|
||||
import ink.snowflake.server.utils.TokenUtils.generateRefreshToken
|
||||
import ink.snowflake.server.utils.TokenUtils.getUserIdByToken
|
||||
import ink.snowflake.server.utils.dao.AIDao
|
||||
import ink.snowflake.server.utils.dao.UserDAO
|
||||
import ink.snowflake.server.utils.getUserIdByToken
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.request.*
|
||||
@@ -42,8 +46,7 @@ fun Application.User(config: AppConfig) {
|
||||
// 初始化 Redis 连接
|
||||
val redisClient: RedissonClient = setupRedis()
|
||||
routing {
|
||||
route("/api") {
|
||||
route("/user") {
|
||||
route("/api/user") {
|
||||
post("/login") {
|
||||
val loginRequest = call.receive<LoginRequest>()
|
||||
val email = loginRequest.account
|
||||
@@ -59,7 +62,7 @@ fun Application.User(config: AppConfig) {
|
||||
// 验证密码
|
||||
if (password == userPassword) {
|
||||
// 登录成功
|
||||
BaseResponse (
|
||||
BaseResponse(
|
||||
status = true, data = LoginResponse(
|
||||
userId,
|
||||
generateAccessToken(config, userId),
|
||||
@@ -182,96 +185,5 @@ fun Application.User(config: AppConfig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateAccessToken(config: AppConfig, userId: UUID): Token {
|
||||
// return generateToken(config, userId, 120, "access_token")
|
||||
return generateToken(config, userId, 2 * 60 * 60, "access_token")
|
||||
}
|
||||
|
||||
fun generateRefreshToken(config: AppConfig, userId: UUID): Token {
|
||||
return generateToken(config, userId, 10 * 24 * 60 * 60, "refresh_token")
|
||||
}
|
||||
|
||||
|
||||
fun generateToken(config: AppConfig, userId: UUID, second: Int, tokenType: String): Token {
|
||||
val expiresAt = Date(System.currentTimeMillis() + second * 1000) //
|
||||
val token = JWT.create()
|
||||
.withAudience(config.jwtAudience)
|
||||
.withIssuer(config.jwtDomain)
|
||||
.withClaim("user_id", userId.toString())
|
||||
.withClaim("token_type", tokenType)
|
||||
.withExpiresAt(expiresAt)
|
||||
.sign(Algorithm.HMAC256(config.jwtSecret))
|
||||
|
||||
return Token(token, expiresAt.time, DateFormat.getDateTimeInstance().format(expiresAt))
|
||||
}
|
||||
|
||||
// 生成4位随机验证码
|
||||
fun generateVerificationCode(): String {
|
||||
return String.format("%04d", Random().nextInt(10000))
|
||||
}
|
||||
|
||||
fun sendVerificationEmail(config: AppConfig, recipientEmail: String, verificationCode: String) {
|
||||
// 设置邮件会话的属性
|
||||
val properties = Properties().apply {
|
||||
put("mail.smtp.host", config.smtpHost)
|
||||
put("mail.smtp.port", config.smtpPort)
|
||||
put("mail.smtp.auth", "true") // 启用身份验证
|
||||
put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory") // 启用 SSL
|
||||
put("mail.smtp.socketFactory.fallback", "false") // 禁用备用连接
|
||||
}
|
||||
// 创建会话
|
||||
val session = Session.getInstance(properties, object : Authenticator() {
|
||||
override fun getPasswordAuthentication(): PasswordAuthentication {
|
||||
return PasswordAuthentication(config.smtpUser, config.smtpPassword)
|
||||
}
|
||||
})
|
||||
try {
|
||||
// Create email content with a more polished template
|
||||
val message = MimeMessage(session).apply {
|
||||
setFrom(InternetAddress(config.smtpUser))
|
||||
setRecipient(Message.RecipientType.TO, InternetAddress(recipientEmail))
|
||||
subject = "Welcome to BBIT-Lab! Verification Code:$verificationCode"
|
||||
val htmlContent = """
|
||||
<html>
|
||||
<body style="font-family: Arial, sans-serif; color: #333;">
|
||||
<div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 10px; background-color: #f9f9f9;">
|
||||
<h2 style="color: #4CAF50;">Welcome to BBIT-Lab!</h2>
|
||||
<p style="font-size: 16px;">Thank you for signing up with <strong>BBIT-Lab</strong>! We are excited to have you on board.</p>
|
||||
|
||||
<p style="font-size: 16px;">To complete your registration, please use the verification code below:</p>
|
||||
|
||||
<div style="background-color: #f1f1f1; padding: 15px; border-radius: 5px; font-size: 20px; text-align: center; color: #333;">
|
||||
<strong style="color: #4CAF50;">$verificationCode</strong>
|
||||
</div>
|
||||
|
||||
<p style="font-size: 16px; margin-top: 20px;">This code is valid for the next <strong>10 minutes</strong>. If you did not request this, please ignore this email.</p>
|
||||
|
||||
<p style="font-size: 16px; margin-top: 20px;">Please do not reply to this email. This inbox is not monitored.</p>
|
||||
<hr style="border-top: 1px solid #ddd; margin-top: 30px;">
|
||||
<p style="font-size: 14px; color: #888; text-align: center;">
|
||||
Best regards<br>
|
||||
<strong>The BBIT-Lab Account Team</strong>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
setContent(htmlContent, "text/html")
|
||||
}
|
||||
// 发送邮件
|
||||
Transport.send(message)
|
||||
println("Verification email sent successfully to $recipientEmail")
|
||||
} catch (e: MessagingException) {
|
||||
e.printStackTrace()
|
||||
println("Failed to send verification email.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun hashPassword(password: String): String {
|
||||
val bytes = MessageDigest.getInstance("SHA-256").digest(password.toByteArray(UTF_8))
|
||||
return bytes.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
@@ -12,8 +12,10 @@ import ink.snowflake.server.model.database.VideosTable.vATotalPeople
|
||||
import ink.snowflake.server.model.database.VideosTable.vStartDateTime
|
||||
import ink.snowflake.server.model.request.VideoAnalyticsRequest
|
||||
import ink.snowflake.server.model.response.*
|
||||
import ink.snowflake.server.utils.CommandUtils.runCommand
|
||||
import ink.snowflake.server.utils.MyUtils
|
||||
import ink.snowflake.server.utils.MyUtils.getFriendlyActionName
|
||||
import ink.snowflake.server.utils.WebSocketManager.broadcastMessage
|
||||
import ink.snowflake.server.utils.runCommand
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
@@ -26,6 +28,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.toJavaLocalDateTime
|
||||
import kotlinx.html.Entities
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.time.format.DateTimeFormatter
|
||||
@@ -99,7 +102,7 @@ fun Application.VideoAnalytics() {
|
||||
)
|
||||
println("-----------------" + command.joinToString(" "))
|
||||
runCommand(command) {
|
||||
println(it)
|
||||
println(Entities.it)
|
||||
}
|
||||
}
|
||||
// 获取已分析视频列表
|
||||
@@ -254,13 +257,3 @@ suspend fun broadcastMessage(message: String) { // 封装的广播消息方法
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFriendlyActionName(name: String): String {
|
||||
return if (name == "feed") {
|
||||
"喂桑"
|
||||
} else if (name == "disinfection") {
|
||||
"消毒"
|
||||
} else {
|
||||
name
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package ink.snowflake.server.utils
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
|
||||
object CommandUtils {
|
||||
|
||||
fun runCommand(command: String): String {
|
||||
println("command--$command")
|
||||
return try {
|
||||
val process = Runtime.getRuntime().exec(command)
|
||||
// 等待命令执行完毕
|
||||
process.waitFor()
|
||||
// 读取输出流
|
||||
val reader = BufferedReader(InputStreamReader(process.inputStream))
|
||||
val errorReader = BufferedReader(InputStreamReader(process.errorStream))
|
||||
val output = StringBuilder()
|
||||
// 读取标准输出
|
||||
reader.use { r ->
|
||||
var line: String? = r.readLine()
|
||||
while (line != null) {
|
||||
output.append(line).append("\n")
|
||||
line = r.readLine()
|
||||
}
|
||||
}
|
||||
// 读取错误输出
|
||||
errorReader.use { er ->
|
||||
var errorLine: String? = er.readLine()
|
||||
while (errorLine != null) {
|
||||
output.append("ERROR: ").append(errorLine).append("\n")
|
||||
errorLine = er.readLine()
|
||||
}
|
||||
}
|
||||
output.toString()
|
||||
} catch (e: Exception) {
|
||||
"Error running command: ${e.message}"
|
||||
}
|
||||
}
|
||||
|
||||
fun runCommand(command: List<String>, logCallback: (String) -> Unit): Process {
|
||||
// 使用 ProcessBuilder 构建命令并启动
|
||||
val process = ProcessBuilder(command)
|
||||
.redirectErrorStream(true) // 合并标准输出和错误输出
|
||||
.start()
|
||||
|
||||
// 创建一个 CoroutineScope 来管理协程
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
// 使用协程读取标准输出和错误输出
|
||||
scope.launch {
|
||||
try {
|
||||
val reader = BufferedReader(InputStreamReader(process.inputStream))
|
||||
var line: String?
|
||||
while (reader.readLine().also { line = it } != null) {
|
||||
logCallback(line ?: "") // 将日志推送到回调
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logCallback("Error reading output: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
return process
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package ink.snowflake.server.utils
|
||||
|
||||
import java.util.Properties
|
||||
import java.util.Random
|
||||
import javax.mail.Authenticator
|
||||
import javax.mail.Message
|
||||
import javax.mail.MessagingException
|
||||
import javax.mail.PasswordAuthentication
|
||||
import javax.mail.Session
|
||||
import javax.mail.Transport
|
||||
import javax.mail.internet.InternetAddress
|
||||
import javax.mail.internet.MimeMessage
|
||||
|
||||
object EmailUtils {
|
||||
|
||||
// 生成4位随机验证码
|
||||
fun generateVerificationCode(): String {
|
||||
return String.format("%04d", Random().nextInt(10000))
|
||||
}
|
||||
|
||||
fun sendVerificationEmail(config: AppConfig, recipientEmail: String, verificationCode: String) {
|
||||
// 设置邮件会话的属性
|
||||
val properties = Properties().apply {
|
||||
put("mail.smtp.host", config.smtpHost)
|
||||
put("mail.smtp.port", config.smtpPort)
|
||||
put("mail.smtp.auth", "true") // 启用身份验证
|
||||
put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory") // 启用 SSL
|
||||
put("mail.smtp.socketFactory.fallback", "false") // 禁用备用连接
|
||||
}
|
||||
// 创建会话
|
||||
val session = Session.getInstance(properties, object : Authenticator() {
|
||||
override fun getPasswordAuthentication(): PasswordAuthentication {
|
||||
return PasswordAuthentication(config.smtpUser, config.smtpPassword)
|
||||
}
|
||||
})
|
||||
try {
|
||||
// Create email content with a more polished template
|
||||
val message = MimeMessage(session).apply {
|
||||
setFrom(InternetAddress(config.smtpUser))
|
||||
setRecipient(Message.RecipientType.TO, InternetAddress(recipientEmail))
|
||||
subject = "Welcome to BBIT-Lab! Verification Code:$verificationCode"
|
||||
val htmlContent = """
|
||||
<html>
|
||||
<body style="font-family: Arial, sans-serif; color: #333;">
|
||||
<div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 10px; background-color: #f9f9f9;">
|
||||
<h2 style="color: #4CAF50;">Welcome to BBIT-Lab!</h2>
|
||||
<p style="font-size: 16px;">Thank you for signing up with <strong>BBIT-Lab</strong>! We are excited to have you on board.</p>
|
||||
|
||||
<p style="font-size: 16px;">To complete your registration, please use the verification code below:</p>
|
||||
|
||||
<div style="background-color: #f1f1f1; padding: 15px; border-radius: 5px; font-size: 20px; text-align: center; color: #333;">
|
||||
<strong style="color: #4CAF50;">$verificationCode</strong>
|
||||
</div>
|
||||
|
||||
<p style="font-size: 16px; margin-top: 20px;">This code is valid for the next <strong>10 minutes</strong>. If you did not request this, please ignore this email.</p>
|
||||
|
||||
<p style="font-size: 16px; margin-top: 20px;">Please do not reply to this email. This inbox is not monitored.</p>
|
||||
<hr style="border-top: 1px solid #ddd; margin-top: 30px;">
|
||||
<p style="font-size: 14px; color: #888; text-align: center;">
|
||||
Best regards<br>
|
||||
<strong>The BBIT-Lab Account Team</strong>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
setContent(htmlContent, "text/html")
|
||||
}
|
||||
// 发送邮件
|
||||
Transport.send(message)
|
||||
println("Verification email sent successfully to $recipientEmail")
|
||||
} catch (e: MessagingException) {
|
||||
e.printStackTrace()
|
||||
println("Failed to send verification email.")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,75 +14,26 @@ import java.text.SimpleDateFormat
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
|
||||
object MyUtils {
|
||||
|
||||
fun getUserIdByToken(call: ApplicationCall) : UUID?{
|
||||
// 通过token获取user_id
|
||||
return UUID.fromString(call.principal<JWTPrincipal>()?.payload?.getClaim("user_id")?.asString())
|
||||
}
|
||||
|
||||
fun formatDateToTargetString(date: Date, targetFormat: String): String {
|
||||
fun formatDateToTargetString(date: Date, targetFormat: String): String {
|
||||
val formatter = SimpleDateFormat(targetFormat) // 创建格式化器
|
||||
return formatter.format(date) // 格式化日期并返回字符串
|
||||
}
|
||||
}
|
||||
|
||||
fun formatLocalDateTimeToString(localDateTime: LocalDateTime): String {
|
||||
fun formatLocalDateTimeToString(localDateTime: LocalDateTime): String {
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") // 创建格式化器
|
||||
return localDateTime.toJavaLocalDateTime().format(formatter) // 转换并格式化
|
||||
}
|
||||
|
||||
fun runCommand(command: String): String {
|
||||
println("command--$command")
|
||||
return try {
|
||||
val process = Runtime.getRuntime().exec(command)
|
||||
// 等待命令执行完毕
|
||||
process.waitFor()
|
||||
// 读取输出流
|
||||
val reader = BufferedReader(InputStreamReader(process.inputStream))
|
||||
val errorReader = BufferedReader(InputStreamReader(process.errorStream))
|
||||
val output = StringBuilder()
|
||||
// 读取标准输出
|
||||
reader.use { r ->
|
||||
var line: String? = r.readLine()
|
||||
while (line != null) {
|
||||
output.append(line).append("\n")
|
||||
line = r.readLine()
|
||||
}
|
||||
}
|
||||
// 读取错误输出
|
||||
errorReader.use { er ->
|
||||
var errorLine: String? = er.readLine()
|
||||
while (errorLine != null) {
|
||||
output.append("ERROR: ").append(errorLine).append("\n")
|
||||
errorLine = er.readLine()
|
||||
}
|
||||
}
|
||||
output.toString()
|
||||
} catch (e: Exception) {
|
||||
"Error running command: ${e.message}"
|
||||
}
|
||||
}
|
||||
|
||||
fun runCommand(command: List<String>, logCallback: (String) -> Unit): Process {
|
||||
// 使用 ProcessBuilder 构建命令并启动
|
||||
val process = ProcessBuilder(command)
|
||||
.redirectErrorStream(true) // 合并标准输出和错误输出
|
||||
.start()
|
||||
|
||||
// 创建一个 CoroutineScope 来管理协程
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
// 使用协程读取标准输出和错误输出
|
||||
scope.launch {
|
||||
try {
|
||||
val reader = BufferedReader(InputStreamReader(process.inputStream))
|
||||
var line: String?
|
||||
while (reader.readLine().also { line = it } != null) {
|
||||
logCallback(line ?: "") // 将日志推送到回调
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logCallback("Error reading output: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
return process
|
||||
}
|
||||
|
||||
fun getFriendlyActionName(name: String): String {
|
||||
return if (name == "feed") {
|
||||
"喂桑"
|
||||
} else if (name == "disinfection") {
|
||||
"消毒"
|
||||
} else {
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package ink.snowflake.server.utils
|
||||
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import ink.snowflake.server.model.response.Token
|
||||
import io.ktor.server.application.ApplicationCall
|
||||
import io.ktor.server.auth.jwt.JWTPrincipal
|
||||
import io.ktor.server.auth.principal
|
||||
import java.security.MessageDigest
|
||||
import java.text.DateFormat
|
||||
import java.util.Date
|
||||
import java.util.UUID
|
||||
import kotlin.text.Charsets.UTF_8
|
||||
|
||||
object TokenUtils {
|
||||
|
||||
fun generateAccessToken(config: AppConfig, userId: UUID): Token {
|
||||
// return generateToken(config, userId, 120, "access_token")
|
||||
return generateToken(config, userId, 2 * 60 * 60, "access_token")
|
||||
}
|
||||
|
||||
fun generateRefreshToken(config: AppConfig, userId: UUID): Token {
|
||||
return generateToken(config, userId, 10 * 24 * 60 * 60, "refresh_token")
|
||||
}
|
||||
|
||||
fun getUserIdByToken(call: ApplicationCall) : UUID?{
|
||||
// 通过token获取user_id
|
||||
return UUID.fromString(call.principal<JWTPrincipal>()?.payload?.getClaim("user_id")?.asString())
|
||||
}
|
||||
|
||||
fun generateToken(config: AppConfig, userId: UUID, second: Int, tokenType: String): Token {
|
||||
val expiresAt = Date(System.currentTimeMillis() + second * 1000) //
|
||||
val token = JWT.create()
|
||||
.withAudience(config.jwtAudience)
|
||||
.withIssuer(config.jwtDomain)
|
||||
.withClaim("user_id", userId.toString())
|
||||
.withClaim("token_type", tokenType)
|
||||
.withExpiresAt(expiresAt)
|
||||
.sign(Algorithm.HMAC256(config.jwtSecret))
|
||||
|
||||
return Token(token, expiresAt.time, DateFormat.getDateTimeInstance().format(expiresAt))
|
||||
}
|
||||
|
||||
fun hashPassword(password: String): String {
|
||||
val bytes = MessageDigest.getInstance("SHA-256").digest(password.toByteArray(UTF_8))
|
||||
return bytes.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
var aiState = "等待分析任务中"
|
||||
// 实时发送AI状态
|
||||
webSocket("/handleState") { // WebSocket 路由
|
||||
clients.add(this) // 添加当前连接的客户端
|
||||
send(aiState) // 向客户端发送连接成功消息
|
||||
try {
|
||||
incoming.consumeEach { frame -> // 持续接收消息
|
||||
when (frame) {
|
||||
is Frame.Text -> {
|
||||
aiState = frame.readText() // 更新状态
|
||||
broadcastMessage(aiState) // 使用封装的方法广播消息
|
||||
}
|
||||
|
||||
is Frame.Close -> {
|
||||
println("Closed")
|
||||
clients.remove(this)
|
||||
close() // 确保关闭 WebSocket 连接
|
||||
return@consumeEach
|
||||
}
|
||||
// 其他消息类型的处理
|
||||
is Frame.Binary -> TODO() // 处理二进制消息
|
||||
is Frame.Ping -> TODO() // 处理 Ping 消息
|
||||
is Frame.Pong -> TODO() // 处理 Pong 消息
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// 处理接收消息时的异常
|
||||
close(CloseReason(CloseReason.Codes.NORMAL, "Client disconnected"))
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
clients.remove(this) // 确保在连接关闭时移除客户端
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 拍照保存为图片 并且调用Python程序进行分析
|
||||
//get("/takePhoto") {
|
||||
// val camera = call.request.queryParameters["cameraId"]
|
||||
// if (camera.isNullOrEmpty()) {
|
||||
// call.respond(BaseResponse(status = false, message = "摄像头名称不能为空", data = null))
|
||||
// return@get
|
||||
// }
|
||||
// stopHLSStream(camera)
|
||||
// call.respond(BaseResponse(message = "摄像头流已停止", data = null))
|
||||
//}
|
||||
@@ -3,7 +3,7 @@ package ink.snowflake.server.utils.dao
|
||||
import ink.snowflake.server.SERVER_PATH_OSS
|
||||
import ink.snowflake.server.model.request.ImageAnalyticsRequest
|
||||
import ink.snowflake.server.model.database.ScaImagesTable
|
||||
import ink.snowflake.server.utils.formatLocalDateTimeToString
|
||||
import ink.snowflake.server.utils.MyUtils.formatLocalDateTimeToString
|
||||
import kotlinx.datetime.toKotlinLocalDateTime
|
||||
import org.jetbrains.exposed.v1.core.SortOrder
|
||||
import org.jetbrains.exposed.v1.jdbc.insert
|
||||
|
||||
@@ -7,7 +7,7 @@ import ink.snowflake.server.model.database.VideosTable.vName
|
||||
import ink.snowflake.server.model.request.VideoAnalyticsRequest
|
||||
import ink.snowflake.server.model.request.VideoDetail
|
||||
import ink.snowflake.server.model.response.VideoListResponse
|
||||
import ink.snowflake.server.utils.formatLocalDateTimeToString
|
||||
import ink.snowflake.server.utils.MyUtils.formatLocalDateTimeToString
|
||||
import kotlinx.datetime.toKotlinLocalDateTime
|
||||
import org.jetbrains.exposed.v1.core.ResultRow
|
||||
import org.jetbrains.exposed.v1.core.SortOrder
|
||||
|
||||
Reference in New Issue
Block a user