This commit is contained in:
lunaticbum 2025-02-24 18:12:51 +09:00
parent 6baa7fe9fb
commit 88a1c7fae4
4 changed files with 329 additions and 34 deletions

View File

@ -6,6 +6,7 @@ import com.google.gson.annotations.SerializedName
import jakarta.servlet.http.HttpServletRequest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kr.lunaticbum.back.lun.configs.GlobalEnvironment
import kr.lunaticbum.back.lun.model.*
@ -13,11 +14,14 @@ import kr.lunaticbum.back.lun.utils.LogService
import org.jsoup.Jsoup
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.web.bind.annotation.*
import org.springframework.web.reactive.function.BodyInserter
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.bodyToMono
import java.math.BigDecimal
import java.math.RoundingMode
import java.net.URLEncoder
@ -54,13 +58,106 @@ class Telegram {
@ResponseBody
@PostMapping("webhook")
fun test(httpServletRequest: HttpServletRequest, @RequestBody update : kr.lunaticbum.back.lun.model.Result) : String {
suspend fun test(httpServletRequest: HttpServletRequest, @RequestBody update : kr.lunaticbum.back.lun.model.Result) : String {
try {
println("test strat ${Gson().toJson(update)}")
println("test strat ${httpServletRequest.requestURI}")
// println("test strat ${httpServletRequest.requestURI}")
update?.message?.let { msg ->
if(msg.text?.startsWith("/") == true) {
if(msg?.location != null && msg?.location?.latitude != 0.0 && msg?.location?.latitude != 0.0 ) {
CoroutineScope(Dispatchers.IO).launch {
try {
println("test strat ${msg.location}")
val lat = BigDecimal(msg?.location?.latitude!!).setScale(6, RoundingMode.HALF_UP)
val long = BigDecimal(msg?.location?.longitude!!).setScale(6, RoundingMode.HALF_UP)
WebClient.create().get()
.uri("http://api.weatherapi.com/v1/current.json?key=${globalEvv.weatherApiKey}&q=${lat},${long}&aqi=no")
.retrieve()
.bodyToMono(CurrentWeather::class.java)
.timeout(Duration.ofSeconds(30L))
.block()?.let { sss ->
println("test strat ${sss}")
CoroutineScope(Dispatchers.IO).launch {
try {
val msg = TelegramSendMsg(
"${msg.from!!.id!!}",
sss.getSummaryInfo(lat.toString(), long.toString())
)
println("msg >>> ${Gson().toJson(msg)}")
// val fullUrl =
// "https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${msg.userId}&text=${msg.msg}"
val fullUrl =
"https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage"
val result = WebClient.create(fullUrl)
// .get()
.post()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(Gson().toJson(msg)))
.retrieve()
.bodyToMono(String::class.java).block() ?: "FAIL"
println("fullUrl ${fullUrl} : result $result")
} catch (e: Exception) {
e.printStackTrace()
}
}
}
var restUrl = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${lat}%2c${long}&radius=5000&type=restaurant&key=AIzaSyARLXyvmr_554tOy3UCh3naFlZQS3-qQQM"
WebClient.create().get()
.uri(restUrl)
.retrieve()
.bodyToMono(PlaceGoogle::class.java)
.timeout(Duration.ofSeconds(30L))
.block()?.let { sss ->
println("restUrl >>> ${restUrl}")
var topResult = arrayListOf<Place>()
sss.results.forEach {
try {
if (it.rating?.toDouble() ?: 0.0 > 4.0) {
it.getDistane(lat.toDouble(),long.toDouble())
println("${it.name} => ${Gson().toJson(it)}")
topResult.add(it)
}
} catch (e : Exception) {
}
}
topResult.sortedBy { it.rating }.forEach {
try {
val msg = TelegramSendMsg(
"${msg.from!!.id!!}",
it.toString()
)
println("msg >>> ${Gson().toJson(msg)}")
// val fullUrl =
// "https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${msg.userId}&text=${msg.msg}"
val fullUrl =
"https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage"
val result = WebClient.create(fullUrl)
// .get()
.post()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(Gson().toJson(msg)))
.retrieve()
.bodyToMono(String::class.java).block() ?: "FAIL"
println("fullUrl ${fullUrl} : result $result")
} catch (e: Exception) {
e.printStackTrace()
}
}
}
// "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${lat},${long}&radius=5000&type=cafe&key=AIzaSyARLXyvmr_554tOy3UCh3naFlZQS3-qQQM"
}
catch (e : Exception) {
e.printStackTrace()
}
}
} else if(msg.text?.startsWith("/") == true) {
msg.text?.split(" ")?.let { cmds ->
cmds[0].let { cmd ->
when(cmd.trim()) {
@ -81,6 +178,7 @@ class Telegram {
"/lama" -> {
val req = BumlamaReq(msg.text!!.replace(cmd,""))
CoroutineScope(Dispatchers.IO).launch {
val fullUrl =
"https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${globalEvv.telegramMyId}&text=lama 에게 전송 ${req.reqMsg}"
logService.log("fullUrl >>> ${fullUrl}")
@ -95,7 +193,7 @@ class Telegram {
try {
val client = WebClient.create()
client.post()
.uri("https://lama.lunaticbum.kr/api/generate")
.uri(lamaGenerated)
.body(BodyInserters.fromValue(Gson().toJson(req)))
.retrieve()
.bodyToMono(String::class.java).timeout(Duration.ofSeconds(6000L)).block()?.let { result ->
@ -166,8 +264,7 @@ class Telegram {
} else if (req.reqMsg?.contains("검색") == true) {
var originalQuery = req.reqMsg
originalQuery?.replace("오늘", SimpleDateFormat("yyyMMdd").format(Date()))
val gSearch = "https://www.googleapis.com/customsearch/v1?key=AIzaSyARLXyvmr_554tOy3UCh3naFlZQS3-qQQM&cx=207f328d3ad7242f2&q=${originalQuery}&num=5&lr=kr"
val gSearch = "https://www.googleapis.com/customsearch/v1?key=AIzaSyARLXyvmr_554tOy3UCh3naFlZQS3-qQQM&cx=207f328d3ad7242f2&q=${originalQuery?.replace("오늘", SimpleDateFormat("yyyMMdd").format(Date()))}&num=5&lr=kr"
println("gSearch >>> ${gSearch}")
WebClient.create().get()
.uri(gSearch)
@ -198,7 +295,7 @@ class Telegram {
val client = WebClient.create()
client.post()
.uri("https://lama.lunaticbum.kr/api/generate")
.uri(lamaGenerated)
.body(BodyInserters.fromValue(Gson().toJson(req)))
.retrieve()
.bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L)).block()?.let { result ->
@ -231,7 +328,7 @@ class Telegram {
} else {
val client = WebClient.create()
client.post()
.uri("https://lama.lunaticbum.kr/api/generate")
.uri(lamaGenerated)
.body(BodyInserters.fromValue(Gson().toJson(req)))
.retrieve()
.bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L)).block()?.let { result ->
@ -259,34 +356,102 @@ class Telegram {
return "Success"
}
inner class BumlamaReq {
private constructor()
constructor(reqMsg: String?) {
this.reqMsg = reqMsg
enum class LamaQueryType(val keywords : ArrayList<String>) {
None(arrayListOf()),
Search(arrayListOf("검색")),
Weather(arrayListOf("날씨")),
NearBy(arrayListOf("주변에","근처에")),
Post(arrayListOf("POST","저장")),
}
class LamaQuery {
var userQuery : String? = null
var now = SimpleDateFormat("yyyy년MM월dd일 HH:mm:ss").format(Date())
var userId : String? = null
var queryType : LamaQueryType = LamaQueryType.None
var req : BumlamaReq? = null
var telegramBotKey : String? = null
fun start() {
req = BumlamaReq(userQuery)
LamaQueryType.values().reversed().forEach { type ->
type.keywords.forEach {
if (queryType.equals(LamaQueryType.None)) {
if(userQuery?.contains(it) == true) {
queryType = type
}
}
}
}
when (queryType) {
// LamaQueryType.None -> {
//
// }
LamaQueryType.Search -> {
}
LamaQueryType.Weather -> {
}
LamaQueryType.Post -> {
}
else -> {
askToLama()
}
}
}
fun searchInfo() {
askToLama()
}
fun searchWeather() {
askToLama()
}
fun searchNearBy() {
askToLama()
}
fun askToLama() {
CoroutineScope(Dispatchers.IO).launch {
req?.let { req ->
val client = WebClient.create()
client.post()
.uri(lamaGenerated)
.body(BodyInserters.fromValue(Gson().toJson(req)))
.retrieve()
.bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L)).block()?.let { result ->
Gson().fromJson(result, BumlamaResp::class.java)?.let { sss ->
CoroutineScope(Dispatchers.IO).launch {
var toalmsg = "${userQuery}의 대답이 도착했어요.\n" + "${sss.response}"
val fullUrl = "https://api.telegram.org/${telegramBotKey}/sendMessage"
toalmsg.chunked(2048).forEach { chunkedMsg ->
println("fullUrl >>> ${fullUrl}")
var tlgSend = TelegramSendMsg(userId!!, chunkedMsg)
WebClient
.create()
.post()
.uri(fullUrl)
.body(BodyInserters.fromValue(Gson().toJson(tlgSend)))
.retrieve().bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L))
.block()?.let { result ->
}
}
}
}
}
}
}.start()
}
@SerializedName("prompt")
var reqMsg : String? = ""
var model : String = "phi4:14b"
// var format : String = "json"
var stream = false
}
inner class BumlamaResp {
var model : String? = ""//"phi4:14b",
var created_at : String? = ""// "": "2025-02-13T06:38:53.619359Z",
var response : String? = ""// "{ \n \"response\": \"Hello! How can I assist you today?\" \n}",
var done : Boolean? = true
var done_reason : String? = "stop"
var context : ArrayList<Long>? = arrayListOf()
var total_duration : Long = 0L//: 1600246875,
var load_duration : Long = 0L//: 27544792,
var prompt_eval_count : Long = 0L//: 11,
var prompt_eval_duration : Long = 0L//: 279000000,
var eval_count : Long = 0L//: 19,
var eval_duration : Long = 0L//: 1292000000
}
@ -417,3 +582,42 @@ fun before5Min(): Long {
cal.add(Calendar.MINUTE, -10)
return cal.timeInMillis
}
class BumlamaReq {
private constructor()
constructor(reqMsg: String?) {
this.reqMsg = reqMsg
}
@SerializedName("prompt")
var reqMsg : String? = ""
var model : String = "phi4:14b"
// var format : String = "json"
var stream = false
}
class BumlamaResp {
var model : String? = ""//"phi4:14b",
var created_at : String? = ""// "": "2025-02-13T06:38:53.619359Z",
var response : String? = ""// "{ \n \"response\": \"Hello! How can I assist you today?\" \n}",
var done : Boolean? = true
var done_reason : String? = "stop"
var context : ArrayList<Long>? = arrayListOf()
var total_duration : Long = 0L//: 1600246875,
var load_duration : Long = 0L//: 27544792,
var prompt_eval_count : Long = 0L//: 11,
var prompt_eval_duration : Long = 0L//: 279000000,
var eval_count : Long = 0L//: 19,
var eval_duration : Long = 0L//: 1292000000
}
val lamaGenerated : String = "https://lama.lunaticbum.kr/api/generate"
data class TelegramSendMsg(
@SerializedName("chat_id")
val userId: String, // null을 허용하지 않음
@SerializedName("text")
val msg: String // null을 허용하지 않음
)

View File

@ -75,6 +75,7 @@ interface LocationLogRepository : ReactiveMongoRepository<LocationLog, String> {
fun findAllBy() : Mono<LocationLog>
fun findFirstByOrderByTimeDesc() : Mono<LocationLog>
fun findFirstByUserIdOrderByTimeDesc(userId: String) : Mono<LocationLog>
fun save(log: LocationLog): Mono<LocationLog>
}
interface LocationService {
@ -96,6 +97,10 @@ class LocationLogService : LocationService {
return logRepository.findFirstByOrderByTimeDesc().block()
}
fun getLocationLogBy(userId : String) : LocationLog? {
return logRepository.findFirstByOrderByTimeDesc().block()
}
fun save(log: LocationLog) {
println("saved msg before ${log}")

View File

@ -0,0 +1,62 @@
package kr.lunaticbum.back.lun.model
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
class PlaceGoogle {
var results : ArrayList<Place> = arrayListOf()
}
class Place {
var name : String = ""
var price_level : String? = null
var rating : String? = null
var reviews : ArrayList<PlaceReview>? = null
var user_ratings_total : String? = null
var geometry : PlaceGeometry? = null
var distance : Double = 0.0
var place_id : String? = null
fun getDistane(currentLat : Double, currentLng : Double) : Double {
distance = calculateDistance(currentLat, currentLng, geometry!!.location!!.lat, geometry!!.location!!.lng)
return distance
}
override fun toString(): String = "상호 : ${name}\n 총 리뷰수: ${user_ratings_total}\n평점 : \n${rating}\n거리 : \n${distance}\n링크 열기: https://www.google.com/maps/search/?api=1&query=${geometry!!.location!!.lat}%2C${geometry!!.location!!.lng}&query_place_id=${place_id}"
}
class PlaceGeometry {
var location : PlaceLocation? = null
}
class PlaceLocation {
var lat : Double = 0.0//37.3890078,
var lng : Double = 0.0//126.9510394
}
class PlaceReview {
var author_name : String? = null
var rating : String? = null
var relative_time_description : String? = null
var time : String? = null
var author_url : String? = null
var language : String? = null
var original_language : String? = null
var profile_photo_url : String? = null
var text : String? = null
var translated : String? = null
}
const val EARTH_RADIUS = 6371.0 // 지구 반지름 (km)
fun calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
val dLat = Math.toRadians(lat2 - lat1)
val dLon = Math.toRadians(lon2 - lon1)
val a = sin(dLat / 2) * sin(dLat / 2) +
cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) * sin(dLon / 2) * sin(dLon / 2)
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
return EARTH_RADIUS * c // km 단위 거리 반환
}

View File

@ -1,5 +1,7 @@
package kr.lunaticbum.back.lun.model
import com.fasterxml.jackson.annotation.JsonProperty
import com.google.gson.annotations.SerializedName
import kr.lunaticbum.back.lun.utils.LogService
import lombok.AllArgsConstructor
import lombok.Data
@ -58,10 +60,32 @@ class Message {
var text: String? = null
@BsonIgnore
var entities: ArrayList<Entity>? = null
var location : TelegramLocation? = null
// var location : Map<String,String>? = null
}
class TelegramLocation {
@SerializedName("longitude")
var longitude: Double? = null
@SerializedName("latitude")
var latitude: Double? = null
@SerializedName("horizontal_accuracy")
var horizontalAccuracy: Double? = null
@SerializedName("live_period")
var livePeriod: Int? = null
@SerializedName("heading")
var heading: Int? = null
@SerializedName("proximity_alert_radius")
var proximityAlertRadius: Int? = null
}
class Result {
var update_id: Int = 0