This commit is contained in:
lunaticbum 2024-10-11 17:17:57 +09:00
parent a810db5d25
commit 23ed2e43cc
6 changed files with 428 additions and 94 deletions

View File

@ -43,6 +43,7 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
implementation ("org.jsoup:jsoup:1.18.1")
implementation("org.springframework.boot:spring-boot-starter-security")
compileOnly("org.projectlombok:lombok")
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")

View File

@ -2,21 +2,22 @@ package kr.lunaticbum.back.lun.controllers
import com.google.gson.Gson
import jakarta.servlet.http.HttpServletRequest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.launch
import kr.lunaticbum.back.lun.configs.GlobalEnvironment
import kr.lunaticbum.back.lun.model.CurrentWeather
import kr.lunaticbum.back.lun.model.Message
import kr.lunaticbum.back.lun.model.TelegramMsgService
import kr.lunaticbum.back.lun.model.TelegramUpdate
import kr.lunaticbum.back.lun.model.*
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.scheduling.annotation.Scheduled
import org.springframework.web.bind.annotation.*
import org.springframework.web.reactive.function.client.WebClient
import java.text.SimpleDateFormat
import java.util.*
@ -32,18 +33,56 @@ class Telegram {
@Autowired
lateinit var logService: LogService
@Autowired
lateinit var locationLogService: LocationLogService
@ResponseBody
@GetMapping("hello")
fun hello(): String {
return "hello1212"
}
@Autowired
lateinit var rssDataService: RssDataService
@ResponseBody
@PostMapping("webhook")
fun test(httpServletRequest: HttpServletRequest, @RequestBody update : TelegramUpdate?) {
fun test(httpServletRequest: HttpServletRequest, @RequestBody update : kr.lunaticbum.back.lun.model.Result) : String {
try {
logService.log("test strat ${update}")
logService.log("test strat ${Gson().toJson(update)}")
// logService.log("test strat ${Gson().toJson(update)}")
logService.log("test strat ${httpServletRequest.requestURI}")
update?.message?.let {
if(it.text?.startsWith("/") == true) {
it.text?.split(" ")?.let { cmds ->
cmds[0].let { cmd ->
when(cmd.trim()) {
"/get" ->{}
"/jf" ->{
CoroutineScope(Dispatchers.IO).launch {
logService.log("${cmd[0]} Start ${cmd[1]}")
String.format(String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9qYXZtb3N0LnRvL3NlYXJjaC9tb3ZpZS8lcw==".toByteArray())),cmd[1]).getJ().let { doc -> FeedParseManager.parse(doc,rssDataService) }
logService.log("${cmd[0]} END ${cmd[1]}")
}
CoroutineScope(Dispatchers.IO).launch {
logService.log("on Cmd JF with SO")
logService.log("${cmd[0]} Start ${cmd[1]}")
String.format(String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9rcjcwLnNvZ2lybC5zby8/cz0lcw==".toByteArray())),cmd[1]).getJ().let { doc -> FeedParseManager.parse(doc,rssDataService)}
logService.log("${cmd[0]} END ${cmd[1]}")
}
}
else -> {}
}
}
}
if (it.text?.contains(" ") == true) {
} else {
}
}
if (it.text?.contains("어디") == true) { it.from?.id?.let { sendMsg(it.toString()) } }
}
// val client0 = WebClient.create()
// client0.get()
// .uri("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w/getUpdates")
@ -71,8 +110,8 @@ class Telegram {
// fun test(@RequestBody str : String) {
// println("path >>> $str")
//>>>>>>> ab915d0a416c69708f1df1ad76d7a14c779c1f59
}
return "Success"
}
@ -110,76 +149,79 @@ class Telegram {
}
@Bean
@Scheduled(cron = "0 0/2 * * * *") //
fun pollingTelegramUpdate() {
try {
logService.log("pollingTelegramUpdate telegramBotKey >>>> ${globalEvv.telegramBotKey}")
logService.log("pollingTelegramUpdate telegramMyId >>>> ${globalEvv.telegramMyId}")
logService.log("pollingTelegramUpdate weatherApiKey >>>> ${globalEvv.weatherApiKey}")
if (
((globalEvv.weatherApiKey?.length ?: 0) > 3 )&&
((globalEvv.telegramBotKey?.length ?: 0) > 3 )&&
((globalEvv.telegramMyId?.length ?: 0) > 3)
) {
val client0 = WebClient.create()
val result = client0.get()
.uri("https://api.telegram.org/${globalEvv.telegramBotKey}/getUpdates")
.retrieve()
.bodyToMono(String::class.java).block() ?: "FAIL"
logService.log("pollingTelegramUpdate result >>>> $result")
Gson().fromJson(result, TelegramUpdate::class.java)?.let { sss ->
logService.log("pollingTelegramUpdate sss >>>> $sss")
if (sss.isSucces()) {
sss.result?.filter {
((it.message?.date ?: 0L) * 1000L) > before5Min()
}?.forEach {
logService.log("pollingTelegramUpdate before Query doOnSuccess m >>>> ${it}")
it.message?.let { msg ->
logService.log("pollingTelegramUpdate before Query doOnSuccess m >>>> ${msg.message_id}")
qns(msg.message_id,msg)
}
}
}
}
}
}catch (e : Exception) {
e.printStackTrace()
}
}
// @Bean
// @Scheduled(cron = "0 0/2 * * * *") //
// fun pollingTelegramUpdate() {
// try {
// logService.log("pollingTelegramUpdate telegramBotKey >>>> ${globalEvv.telegramBotKey}")
// logService.log("pollingTelegramUpdate telegramMyId >>>> ${globalEvv.telegramMyId}")
// logService.log("pollingTelegramUpdate weatherApiKey >>>> ${globalEvv.weatherApiKey}")
// if (
// ((globalEvv.weatherApiKey?.length ?: 0) > 3 )&&
// ((globalEvv.telegramBotKey?.length ?: 0) > 3 )&&
// ((globalEvv.telegramMyId?.length ?: 0) > 3)
// ) {
// val client0 = WebClient.create()
// val result = client0.get()
// .uri("https://api.telegram.org/${globalEvv.telegramBotKey}/getUpdates")
// .retrieve()
// .bodyToMono(String::class.java).block() ?: "FAIL"
// logService.log("pollingTelegramUpdate result >>>> $result")
// Gson().fromJson(result, TelegramUpdate::class.java)?.let { sss ->
// logService.log("pollingTelegramUpdate sss >>>> $sss")
// if (sss.isSucces()) {
// sss.result?.filter {
// ((it.message?.date ?: 0L) * 1000L) > before5Min()
// }?.forEach {
// logService.log("pollingTelegramUpdate before Query doOnSuccess m >>>> ${it}")
// it.message?.let { msg ->
// logService.log("pollingTelegramUpdate before Query doOnSuccess m >>>> ${msg.message_id}")
// qns(msg.message_id,msg)
// }
// }
// }
// }
// }
// }catch (e : Exception) {
// e.printStackTrace()
// }
// }
fun qns(it : String, msg : Message) {
var doSave = true
telegramService.findById(it)?.subscribe( { m ->
logService.log("pollingTelegramUpdate doOnSuccess m >>>> $m")
if (m != null) {
if (msg.text?.contains("어디") == true) {
// fun qns(it : String, msg : Message) {
// var doSave = true
// telegramService.findById(it)?.subscribe( { m ->
// logService.log("pollingTelegramUpdate doOnSuccess m >>>> $m")
// if (m != null) {
// if (msg.text?.contains("어디") == true) {
//
// } else {
// logService.log(msg.text ?: "NONE")
// }
// } else {
// doSave = false
// }
// },{ e ->
// e.printStackTrace()
// },{
// if (doSave) {
// telegramService.save(msg)
// if (msg.text?.contains("어디") == true || msg.text?.startsWith("\"") == true) {
// sendMsg()
// }
// }
// logService.log("pollingTelegramUpdate doOnSuccess comp")
// })
// }
} else {
logService.log(msg.text ?: "NONE")
}
} else {
doSave = false
}
},{ e ->
e.printStackTrace()
},{
if (doSave) {
telegramService.save(msg)
if (msg.text?.contains("어디") == true || msg.text?.startsWith("\"") == true) {
sendMsg()
}
}
logService.log("pollingTelegramUpdate doOnSuccess comp")
})
}
fun sendMsg() {
fun sendMsg(target : String) {
val client = WebClient.create()
client.get()
.uri("https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${globalEvv.telegramMyId}&text=/g_mustShareLocation")
.retrieve()
.bodyToMono(String::class.java).block() ?: "FAIL"
locationLogService.getLocationLog()?.let {
client.get()
.uri("https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${target}&text=${SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Date(it.time))}\n${it.mAddressLines.first()}")
.retrieve()
.bodyToMono(String::class.java).block() ?: "FAIL"
}
}

View File

@ -1,15 +1,23 @@
package kr.lunaticbum.back.lun.model
import com.google.gson.Gson
import kr.lunaticbum.back.lun.utils.LogService
import lombok.AllArgsConstructor
import lombok.Data
import lombok.NoArgsConstructor
import org.jsoup.Jsoup
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.annotation.Id
import org.springframework.data.domain.Page
import org.springframework.data.mongodb.core.mapping.Document
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.List
class BumsPrivate {
}
@ -64,7 +72,7 @@ class LocationLog {
@Repository
interface LocationLogRepository : ReactiveMongoRepository<LocationLog, String> {
fun findFirstByOrderByTimeDesc() : Mono<LocationLog>
fun save(log: LocationLog): Mono<LocationLog>
}
interface LocationService {
@ -79,6 +87,9 @@ class LocationLogService : LocationService {
@Autowired
private lateinit var logRepository: LocationLogRepository
fun getLocationLog() : LocationLog? {
return logRepository.findFirstByOrderByTimeDesc().block()
}
fun save(log: LocationLog) {
@ -88,4 +99,221 @@ class LocationLogService : LocationService {
})
}
}
interface RssDataInterface {
fun title() : String
fun thumbnailUrl() : String
fun originPage() : String
fun description() : String
fun pubDate() : Long
fun category() : RssDataType
fun getCho() : String?
}
enum class RssDataType {
NO_DATA,
YOUTUBE,
NewsFeed,
GURU,
Most,
TAGS,
REDDIT,
REDDIT_nsfw,
Dotax,
FmKorae,
DcInside,
RuliWeb,
Clien,
TheQoo,
Arca;
// fun getResId() = when (this) {
// YOUTUBE -> R.drawable.youtube
// REDDIT, REDDIT_nsfw -> R.drawable.reddit
// Dotax -> R.drawable.daum
// FmKorae -> R.drawable.fmk
// DcInside -> R.drawable.dcinside
// Arca -> R.drawable.arca
// else -> {
// 0
// }
// }
fun defaultImgSize() = when (this) {
YOUTUBE -> 200
REDDIT_nsfw,GURU,Most -> 360
else -> { 120 }
}
// fun getDefaultVisibiliy() = when (this) {
// REDDIT_nsfw,GURU,Most,NewsFeed -> View.GONE
// else -> { View.VISIBLE }
// }
}
class RssData : RssDataInterface {
@Id
var originPage : String? = null
var title : String? = null
var description : String? = null
var thumbnail : String? = null
var pubDate : Long = 0L
var category : String? = null
var chosung : String? = null
var mRssDataType : RssDataType? = null
override fun title(): String {
return when(category()){
RssDataType.NewsFeed -> {
if(title?.length ?: 0 > 30) title?.substring(0,30).plus("...") else title ?: ""
}
else -> title ?: ""
}.apply {
// chosung = JamoUtils.split(this).joinToString("")
}
}
override fun thumbnailUrl(): String {
return thumbnail ?: ""
}
override fun originPage(): String {
return originPage ?: ""
}
override fun description(): String {
return when(category()){
RssDataType.YOUTUBE -> {
if(description?.contains("게시자") == true) description!!.split("게시자")[0] else description ?: ""
}
RssDataType.NewsFeed -> {
category().name
}
else -> description.plus(" / ").plus(category().name)
}
}
override fun pubDate(): Long {
return pubDate
}
override fun category(): RssDataType {
if (mRssDataType == null)
mRssDataType = RssDataType.valueOf(category!!)
return mRssDataType!!
}
override fun getCho(): String? {
return chosung
}
}
val USAGT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15"
fun String.getJ() = Jsoup.connect(this).userAgent(USAGT).get()
object FeedParseManager {
val parsers = listOf<SoInterface>(QVZTb2dpcmw,SkFWTW9zdA)
fun parse(doc : org.jsoup.nodes.Document, service: RssDataService) {
try {
parsers.filter { doc.title().contains(it.getName()) }.first()?.let {
it.parse(doc,service)
}
} catch (e : Exception) {
e.printStackTrace()
}
}
}
interface SoInterface{
fun getName() : String
fun parse(doc : org.jsoup.nodes.Document,service: RssDataService)
}
object QVZTb2dpcmw : SoInterface {
override fun getName(): String {
return String(Base64.getMimeDecoder().decode(this.javaClass.simpleName.plus("==").toByteArray()))
}
override fun parse(doc : org.jsoup.nodes.Document, service : RssDataService) {
doc.getElementsByTag("article").forEach { article ->
val title = article.getElementsByTag("a").get(0).attr("title")
val href = article.getElementsByTag("a").get(0).attr("href")
val img = article.getElementsByTag("img").get(0).attr("data-src")
service.save(RssData().apply {
this.originPage = href
this.title = title
this.description = "Sogirl"
this.thumbnail = img
this.pubDate = Date().time
this.category = RssDataType.GURU.name
})
}
}
}
object SkFWTW9zdA : SoInterface {
var dmy = SimpleDateFormat("dd-MM-yyyy")
override fun getName(): String {
return String(Base64.getMimeDecoder().decode(this.javaClass.simpleName.plus("==").toByteArray()))
}
override fun parse(doc: org.jsoup.nodes.Document, service: RssDataService) {
doc.getElementsByClass("card").forEach { card ->
var thumb = if(card.getElementsByTag("img").size > 0) card.getElementsByTag("img").get(0).attr("src") else ""
if (thumb.contains("No+Poster")) thumb = if(card.getElementsByTag("img").size > 0) card.getElementsByTag("img").get(0).attr("data-src") else thumb
var model = if(card.getElementsByTag("img").size > 0) card.getElementsByTag("img").get(0).attr("alt") else ""
if(card.getElementsByClass("card-block").size > 0) if(card.getElementsByClass("card-block").size > 0) {
val link = card.getElementsByClass("card-block").get(0).getElementsByTag("a").get(0).attr("href")
val title = card.getElementsByClass("card-block").get(0).getElementsByTag("a").get(0).attr("title")
val date = card.getElementsByTag("span").get(0).text()
service.save(RssData().apply {
description = model
thumbnail = thumb
originPage = link
this.title = title
try {
pubDate = dmy.parse(date).time
}catch (e : Exception) {e.printStackTrace()}
})
}
}
}
}
@Repository
interface RssDataRepository : ReactiveMongoRepository<RssData, String> {
fun findFirstByOriginPageEquals(originPage : String): Mono<RssData>
fun findAllByOrderByPubDate() : Mono<List<RssData>>
fun save(log: RssData): Mono<RssData>
}
@Service
class RssDataService {
@Autowired
private lateinit var logService: LogService
@Autowired
private lateinit var rssDataRepository: RssDataRepository
fun hasItem(originPage : String) {
}
fun getLocationLog() : List<RssData>? {
return rssDataRepository.findAllByOrderByPubDate().block()
}
fun save(log: RssData) {
println("saved msg before ${Gson().toJson(log)}")
log.originPage?.let {
if(rssDataRepository.findFirstByOriginPageEquals(it).block() == null) {
rssDataRepository.save(log)
.subscribe({ println("saved msg after ${it}") }, { e -> e.printStackTrace() }, {
println("saved msg comp")
})
} else {
println("있어???")
}
}
}
}

View File

@ -0,0 +1,23 @@
:root{
--ButtonWidth:45%;
--ButtonHeight:45px;
}
#save {
right: 0;
position: absolute;
width: var(--ButtonWidth);
height: var(--ButtonHeight);
}
.layer > * {
height: var(--ButtonHeight);
}
input {
width: 100%;
}
select , #hashtag{
margin-left: 1%;
width: fit-content;
margin-right: 1%;
}

View File

@ -1,38 +1,63 @@
:root {
--WindowFull : 100svh;
--TopHeight: 50px;
--FooterHeight: 120px;
--WindowFull : 100%;
--TopHeight: 160px;
--FooterHeight: 160px;
--ContentVerticalMargin: 5px;
}
input, select ,button{
color: white;
background: #2d2f34;
border: black;
border-width: 1px;
padding: 0;
margin: 0;
position: relative;
}
body, html {
background-color: black;
margin: 0px;
margin-left: 2.5%;
margin-right: 2.5%;
height: 100lvh;
width: 95%;
}
header {
width: 100%;
align-content: center;
position: relative;
background-color: Gray;
height: var(--TopHeight);
background-image: url("../blog/post/images/42cc3207-42a4-4ceb-8a2f-f5f7a89496fc.jpg");
background-repeat: revert;
background-size: contain;
background-origin: revert;
}
#content {
margin-left: 2.5%;
margin-right: 2.5%;
position: relative;
overflow-y: auto;
overflow-x: clip;
background: black;
min-height: calc((var(--TopHeight) + var(--FooterHeight)) * 2);
height: calc(var(--WindowFull) - calc(var(--FooterHeight) + var(--TopHeight)));
background-image: url("../blog/post/images/bb109b5a-f907-4da1-9c4f-55533395ed6e.jpg");
background-repeat: revert;
background-size: contain;
background-origin: revert;
}
#content > * {
margin-top: 5px;
margin-bottom: 5px;
margin-top: var(--ContentVerticalMargin);
margin-bottom: var(--ContentVerticalMargin);
}
footer {
width: 100%;
align-content: center;
position: relative;
height: var(--FooterHeight);
background-color: aquamarine;
background-image: url("../blog/post/images/42cc3207-42a4-4ceb-8a2f-f5f7a89496fc.jpg");
background-repeat: revert;
background-size: contain;
transform: scaleY(-1);
}

View File

@ -7,20 +7,33 @@
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
<script type="text/javascript" th:src="@{/js/toast-ui.js}"></script>
<link th:href="@{/css/blog.css}" rel="stylesheet" />
<link th:href="@{/css/toast-ui.css}" rel="stylesheet" />
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
<!-- <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor-dark.css" />-->
<!-- <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor-dark.css" />-->
<script th:inline="javascript">
let editor
var editor
let onChange = () => {console.log(editor.getMarkdown())}
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
var h = document.querySelector('#content').getBoundingClientRect().height + 'px'
var style = getComputedStyle(document.body)
console.log(style.getPropertyValue('--ContentVerticalMargin'))
console.log(window.c)
console.log(style.getPropertyValue('--FooterHeight'))
console.log(style.getPropertyValue('--TopHeight'))
var editorHeght = (
document.querySelector('#content').getBoundingClientRect().height -
(
Number(style.getPropertyValue('--ButtonHegit').replace("px","") * 3)
+ Number(style.getPropertyValue('--TopHeight').replace("px",""))
)
)
editor = new toastui.Editor({
el: document.querySelector('#editor'),
previewStyle: 'tab',
height: '500px',
width:'100%',
height: editorHeght+ 'px',
width:'95%',
theme:'dark',
usageStatistics : false,
toolbar:null,
@ -80,14 +93,16 @@
</script>
</head>
<div layout:fragment="content" id="content">
<input id="title_layer" />
<div class="layer">
<input id="title_layer" />
</div>
<div id="editor" ></div>
<div id="hashtag_layer">
<div class="layer">
<select > </select>
<input id="hashtag" />
</div>
<div id="controll_layer" >
<button onclick="save()">asdsad</button>
<div id="layer" >
<button id="save" onclick="save()">asdsad</button>
</div>
</div>
</html>