mirror of
https://github.com/dalbodeule/chibot-chzzk-bot.git
synced 2025-08-07 21:01:14 +00:00
Fix /user/{uid} endoints.
- ChzzkApis.kt moved to common - ChzzkApis.kt response data is nullable data. - if require {uid}'s data, getStreamInfo function called.
This commit is contained in:
@@ -1,148 +0,0 @@
|
||||
package space.mori.chzzk_bot.chatbot.chzzk
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import java.io.IOException
|
||||
|
||||
data class IData<T>(
|
||||
val code: Int = 200,
|
||||
val message: String? = null,
|
||||
val content: T
|
||||
)
|
||||
|
||||
// Follows
|
||||
data class IFollowContent(
|
||||
val userIdHash: String = "",
|
||||
val nickname: String = "",
|
||||
val profileImageUrl: String = "",
|
||||
val userRoleCode: String = "",
|
||||
val badge: Badge? = null,
|
||||
val title: Title? = null,
|
||||
val verifiedMark: Boolean = false,
|
||||
val activityBadges: List<Badge> = emptyList(),
|
||||
val streamingProperty: StreamingProperty = StreamingProperty()
|
||||
)
|
||||
|
||||
data class Badge(
|
||||
val badgeNo: Int?,
|
||||
val badgeId: String?,
|
||||
val imageUrl: String?,
|
||||
val title: String?,
|
||||
val description: String?,
|
||||
val activated: Boolean?
|
||||
)
|
||||
|
||||
data class Title(
|
||||
val name: String = "",
|
||||
val color: String = ""
|
||||
)
|
||||
|
||||
data class StreamingProperty(
|
||||
val following: Following? = Following(),
|
||||
val nicknameColor: NicknameColor = NicknameColor()
|
||||
)
|
||||
|
||||
data class Following(
|
||||
val followDate: String? = null
|
||||
)
|
||||
|
||||
data class NicknameColor(
|
||||
val colorCode: String = ""
|
||||
)
|
||||
|
||||
// Stream info
|
||||
data class IStreamInfo(
|
||||
val liveId: Int = 0,
|
||||
val liveTitle: String = "",
|
||||
val status: String = "",
|
||||
val liveImageUrl: String = "",
|
||||
val defaultThumbnailImageUrl: String? = null,
|
||||
val concurrentUserCount: Int = 0,
|
||||
val accumulateCount: Int = 0,
|
||||
val openDate: String = "",
|
||||
val closeDate: String = "",
|
||||
val adult: Boolean = false,
|
||||
val clipActive: Boolean = false,
|
||||
val tags: List<String> = emptyList(),
|
||||
val chatChannelId: String = "",
|
||||
val categoryType: String = "",
|
||||
val liveCategory: String = "",
|
||||
val liveCategoryValue: String = "",
|
||||
val chatActive: Boolean = true,
|
||||
val chatAvailableGroup: String = "",
|
||||
val paidPromotion: Boolean = false,
|
||||
val chatAvailableCondition: String = "",
|
||||
val minFollowerMinute: Int = 0,
|
||||
val livePlaybackJson: String = "",
|
||||
val p2pQuality: List<Any> = emptyList(),
|
||||
val channel: Channel = Channel(),
|
||||
val livePollingStatusJson: String = "",
|
||||
val userAdultStatus: String? = null,
|
||||
val chatDonationRankingExposure: Boolean = true,
|
||||
val adParameter: AdParameter = AdParameter()
|
||||
)
|
||||
|
||||
data class Channel(
|
||||
val channelId: String = "",
|
||||
val channelName: String = "",
|
||||
val channelImageUrl: String = "",
|
||||
val verifiedMark: Boolean = false
|
||||
)
|
||||
|
||||
data class AdParameter(
|
||||
val tag: String = ""
|
||||
)
|
||||
|
||||
// OkHttpClient에 Interceptor 추가
|
||||
val client = OkHttpClient.Builder()
|
||||
.addNetworkInterceptor { chain ->
|
||||
chain.proceed(
|
||||
chain.request()
|
||||
.newBuilder()
|
||||
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
|
||||
.build()
|
||||
)
|
||||
}
|
||||
.build()
|
||||
val gson = Gson()
|
||||
|
||||
fun getFollowDate(chatID: String, userId: String) : IData<IFollowContent> {
|
||||
val url = "https://comm-api.game.naver.com/nng_main/v1/chats/$chatID/users/$userId/profile-card?chatType=STREAMING"
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.build()
|
||||
|
||||
client.newCall(request).execute().use { response ->
|
||||
try {
|
||||
if(!response.isSuccessful) throw IOException("Unexpected code ${response.code}")
|
||||
val body = response.body?.string()
|
||||
val follow = gson.fromJson(body, object: TypeToken<IData<IFollowContent>>() {})
|
||||
|
||||
return follow
|
||||
} catch(e: Exception) {
|
||||
println(e.stackTrace)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getStreamInfo(userId: String) : IData<IStreamInfo> {
|
||||
val url = "https://api.chzzk.naver.com/service/v2/channels/${userId}/live-detail"
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.build()
|
||||
|
||||
client.newCall(request).execute().use { response ->
|
||||
try {
|
||||
if(!response.isSuccessful) throw IOException("Unexpected code ${response.code}")
|
||||
val body = response.body?.string()
|
||||
val follow = gson.fromJson(body, object: TypeToken<IData<IStreamInfo>>() {})
|
||||
|
||||
return follow
|
||||
} catch(e: Exception) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
@@ -14,8 +14,7 @@ import space.mori.chzzk_bot.common.models.User
|
||||
import space.mori.chzzk_bot.common.services.LiveStatusService
|
||||
import space.mori.chzzk_bot.common.services.TimerConfigService
|
||||
import space.mori.chzzk_bot.common.services.UserService
|
||||
import space.mori.chzzk_bot.common.utils.convertChzzkDateToLocalDateTime
|
||||
import space.mori.chzzk_bot.common.utils.getUptime
|
||||
import space.mori.chzzk_bot.common.utils.*
|
||||
import xyz.r2turntrue.chzzk4j.chat.ChatEventListener
|
||||
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
||||
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
|
||||
@@ -42,7 +41,7 @@ object ChzzkHandler {
|
||||
|
||||
handlers.forEach { handler ->
|
||||
val streamInfo = getStreamInfo(handler.listener.channelId)
|
||||
if (streamInfo.content.status == "OPEN") handler.isActive(true, streamInfo)
|
||||
if (streamInfo.content?.status == "OPEN") handler.isActive(true, streamInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +75,8 @@ object ChzzkHandler {
|
||||
if (!running) return@forEach
|
||||
try {
|
||||
val streamInfo = getStreamInfo(it.channel.channelId)
|
||||
if (streamInfo.content.status == "OPEN" && !it.isActive) it.isActive(true, streamInfo)
|
||||
if (streamInfo.content.status == "CLOSE" && it.isActive) it.isActive(false, streamInfo)
|
||||
if (streamInfo.content?.status == "OPEN" && !it.isActive) it.isActive(true, streamInfo)
|
||||
if (streamInfo.content?.status == "CLOSE" && it.isActive) it.isActive(false, streamInfo)
|
||||
} catch(e: SocketTimeoutException) {
|
||||
logger.info("Timeout: ${it.channel.channelName} / ${e.stackTraceToString()}")
|
||||
} catch (e: Exception) {
|
||||
@@ -152,14 +151,14 @@ class UserHandler(
|
||||
internal val isActive: Boolean
|
||||
get() = _isActive
|
||||
|
||||
internal fun isActive(value: Boolean, status: IData<IStreamInfo>) {
|
||||
internal fun isActive(value: Boolean, status: IData<IStreamInfo?>) {
|
||||
if(value) {
|
||||
logger.info("${user.username} is live.")
|
||||
|
||||
logger.info("ChzzkChat connecting... ${channel.channelName} - ${channel.channelId}")
|
||||
listener.connectBlocking()
|
||||
|
||||
streamStartTime = convertChzzkDateToLocalDateTime(status.content.openDate)
|
||||
streamStartTime = status.content?.openDate?.let { convertChzzkDateToLocalDateTime(it) }
|
||||
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
when(TimerConfigService.getConfig(UserService.getUser(channel.channelId)!!)?.option) {
|
||||
|
@@ -1,16 +1,7 @@
|
||||
package space.mori.chzzk_bot.chatbot.chzzk
|
||||
|
||||
import io.github.cdimascio.dotenv.dotenv
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.java.KoinJavaComponent.inject
|
||||
import org.slf4j.LoggerFactory
|
||||
import space.mori.chzzk_bot.common.events.CoroutinesEventBus
|
||||
import space.mori.chzzk_bot.common.events.GetUserEvents
|
||||
import space.mori.chzzk_bot.common.events.GetUserType
|
||||
import space.mori.chzzk_bot.common.services.LiveStatusService
|
||||
import space.mori.chzzk_bot.common.services.UserService
|
||||
import xyz.r2turntrue.chzzk4j.Chzzk
|
||||
import xyz.r2turntrue.chzzk4j.ChzzkBuilder
|
||||
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
||||
@@ -24,34 +15,10 @@ object Connector {
|
||||
.withAuthorization(dotenv["NID_AUT"], dotenv["NID_SES"])
|
||||
.build()
|
||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||
private val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java)
|
||||
|
||||
fun getChannel(channelId: String): ChzzkChannel? = chzzk.getChannel(channelId)
|
||||
|
||||
|
||||
init {
|
||||
logger.info("chzzk logged: ${chzzk.isLoggedIn} / ${chzzk.loggedUser?.nickname ?: "----"}")
|
||||
dispatcher.subscribe(GetUserEvents::class) {
|
||||
if (it.type == GetUserType.REQUEST) {
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
val channel = getChannel(it.uid ?: "")
|
||||
if(channel == null) dispatcher.post(GetUserEvents(
|
||||
GetUserType.NOTFOUND, null, null, null, null
|
||||
))
|
||||
else {
|
||||
val user = UserService.getUser(channel.channelId)
|
||||
dispatcher.post(
|
||||
GetUserEvents(
|
||||
GetUserType.RESPONSE,
|
||||
channel.channelId,
|
||||
channel.channelName,
|
||||
LiveStatusService.getLiveStatus(user!!)?.status ?: false,
|
||||
channel.channelImageUrl
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,6 +7,7 @@ import org.koin.java.KoinJavaComponent.inject
|
||||
import space.mori.chzzk_bot.common.events.*
|
||||
import space.mori.chzzk_bot.common.models.User
|
||||
import space.mori.chzzk_bot.common.services.*
|
||||
import space.mori.chzzk_bot.common.utils.getFollowDate
|
||||
import space.mori.chzzk_bot.common.utils.getUptime
|
||||
import space.mori.chzzk_bot.common.utils.getYoutubeVideo
|
||||
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
||||
@@ -280,7 +281,7 @@ class MessageHandler(
|
||||
result = followPattern.replace(result) { _ ->
|
||||
try {
|
||||
val followingDate = getFollowDate(listener.chatId, msg.userId)
|
||||
.content.streamingProperty.following?.followDate
|
||||
.content?.streamingProperty?.following?.followDate
|
||||
|
||||
val period = followingDate?.let {
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||
|
@@ -12,8 +12,8 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEve
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
||||
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder
|
||||
import org.slf4j.LoggerFactory
|
||||
import space.mori.chzzk_bot.chatbot.chzzk.IData
|
||||
import space.mori.chzzk_bot.chatbot.chzzk.IStreamInfo
|
||||
import space.mori.chzzk_bot.common.utils.IData
|
||||
import space.mori.chzzk_bot.common.utils.IStreamInfo
|
||||
import space.mori.chzzk_bot.chatbot.discord.commands.*
|
||||
import space.mori.chzzk_bot.common.models.User
|
||||
import space.mori.chzzk_bot.common.services.ManagerService
|
||||
@@ -33,18 +33,19 @@ class Discord: ListenerAdapter() {
|
||||
internal fun getChannel(guildId: Long, channelId: Long) =
|
||||
bot.getGuildById(guildId)?.getTextChannelById(channelId)
|
||||
|
||||
fun sendDiscord(user: User, status: IData<IStreamInfo>) {
|
||||
fun sendDiscord(user: User, status: IData<IStreamInfo?>) {
|
||||
if(status.content == null) return
|
||||
if(user.liveAlertMessage != "" && user.liveAlertGuild != null && user.liveAlertChannel != null) {
|
||||
val channel = getChannel(user.liveAlertGuild!!, user.liveAlertChannel!!) ?: throw RuntimeException("${user.liveAlertChannel} is not valid.")
|
||||
|
||||
val embed = EmbedBuilder()
|
||||
embed.setTitle(status.content.liveTitle, "https://chzzk.naver.com/live/${user.token}")
|
||||
embed.setTitle(status.content!!.liveTitle, "https://chzzk.naver.com/live/${user.token}")
|
||||
embed.setDescription("${user.username} 님이 방송을 시작했습니다.")
|
||||
embed.setTimestamp(Instant.now())
|
||||
embed.setAuthor(user.username, "https://chzzk.naver.com/live/${user.token}", status.content.channel.channelImageUrl)
|
||||
embed.addField("카테고리", status.content.liveCategoryValue, true)
|
||||
embed.addField("태그", status.content.tags.joinToString(", "), true)
|
||||
embed.setImage(status.content.liveImageUrl.replace("{type}", "1080"))
|
||||
embed.setAuthor(user.username, "https://chzzk.naver.com/live/${user.token}", status.content!!.channel.channelImageUrl)
|
||||
embed.addField("카테고리", status.content!!.liveCategoryValue, true)
|
||||
embed.addField("태그", status.content!!.tags.joinToString(", "), true)
|
||||
embed.setImage(status.content!!.liveImageUrl.replace("{type}", "1080"))
|
||||
|
||||
channel.sendMessage(
|
||||
MessageCreateBuilder()
|
||||
|
Reference in New Issue
Block a user