Skip to content

Commit d8758a7

Browse files
authored
Merge pull request mouredev#6392 from blackriper/main
Reto#40-kotlin
2 parents 628f00f + 33326a1 commit d8758a7

File tree

1 file changed

+205
-0
lines changed

1 file changed

+205
-0
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import io.ktor.client.HttpClient
2+
import io.ktor.client.call.body
3+
import io.ktor.client.engine.cio.CIO
4+
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
5+
import io.ktor.client.request.forms.FormDataContent
6+
import io.ktor.client.request.get
7+
import io.ktor.client.request.headers
8+
import io.ktor.client.request.post
9+
import io.ktor.client.request.setBody
10+
import io.ktor.client.statement.bodyAsText
11+
import io.ktor.http.HttpHeaders
12+
import io.ktor.http.parameters
13+
import io.ktor.serialization.kotlinx.json.json
14+
import kotlinx.coroutines.Dispatchers
15+
import kotlinx.coroutines.async
16+
import kotlinx.coroutines.coroutineScope
17+
import kotlinx.coroutines.flow.Flow
18+
import kotlinx.coroutines.flow.asFlow
19+
import kotlinx.coroutines.flow.toList
20+
import kotlinx.coroutines.runBlocking
21+
import kotlinx.serialization.SerialName
22+
import kotlinx.serialization.Serializable
23+
import kotlinx.serialization.json.Json
24+
import java.time.Instant
25+
import java.time.LocalDateTime
26+
import java.time.ZoneId
27+
import java.time.format.DateTimeFormatter
28+
29+
30+
//1.- traer lista de usuarios
31+
val participans= listOf(
32+
"Abby","Ache","Adricontreras",
33+
"Agustin","Alexby","Ampeter",
34+
"Ander","AriGameplays","AriGeli",
35+
"Auronplay","Axozer","Beniju",
36+
"ByCalitos","Byviruzz","Carrera",
37+
"Celopan","Cheeto","CrystalMolly",
38+
"DarioEmehache","Dheylo","DjMariio",
39+
"Doble","Elvisa","Elyas360","Folagor",
40+
"Grefg","Guanyar","Hika","Hiper",
41+
"Ibai","Ibelky","illojuan","Imantado",
42+
"IrinaIsasia","Jesskiu","Jopa","JordiWild",
43+
"KenaiSouza","Keroro","KiddKeo","KikoRivera",
44+
"Knekro","Koko","KronnoZomber","Leviathan","LitKillan",
45+
"Lolalolita","Lolito","Luh","Luzu","Mangel","Mayichi",
46+
"Melo","MissaSinfonia","MixWell","MrJagger","NateGentile7",
47+
"Nexxuz","Nia","NilOjeda","Nissaxter","Ollie","Orslok","Outconsumer",
48+
"PapiGavi","Paracetamor","Patica","PaulaGonu","Pausenpall","Perxitaa",
49+
"Plex","PolisPol","Quackitty","Recuerdop","Reven","Rivers","Roberttpg","Roier",
50+
"Rojuu","Rubius","Shadoune","Silithur","Spoksponha","Spreen","Spursito","Staxx",
51+
"Suzyroxx","Vicens","Vituber","Werlyb","Xavi","Xcry","Xokas","Zarcort","Zeling","Zorman")
52+
53+
//2.- Configurar cliente Http Ktor
54+
//https://ktor.io/docs/client-create-new-application.html
55+
56+
val ktorClient= HttpClient(CIO){
57+
install(ContentNegotiation){
58+
json(Json{
59+
prettyPrint=true
60+
ignoreUnknownKeys=true
61+
})
62+
}
63+
}
64+
65+
//3.-Data clases para response , request
66+
const val CLIENTID="<YOUR CLIENT ID>"
67+
const val SECRET="<YOUR SECRET>"
68+
69+
@Serializable
70+
data class Token(
71+
@SerialName("access_token")
72+
val token: String
73+
)
74+
75+
76+
@Serializable
77+
data class Data(val data: List<TwitchUserDto>)
78+
79+
@Serializable
80+
data class TwitchUserDto(
81+
val id: String,
82+
@SerialName("display_name")
83+
val userName: String,
84+
@SerialName("created_at")
85+
val createdAt: String
86+
)
87+
88+
@Serializable
89+
data class Followers(val total: Long)
90+
91+
92+
data class TwitchUser(
93+
val userName: String,
94+
val createdAt: LocalDateTime,
95+
val followers: Long
96+
)
97+
98+
//extension para convertir el usuario
99+
fun TwitchUserDto.toTwicthUser(total: Long):TwitchUser{
100+
val created= Instant.parse(createdAt).let {
101+
it.atZone(ZoneId.systemDefault()).toLocalDateTime()
102+
}
103+
return TwitchUser(
104+
userName = userName,
105+
createdAt=created,
106+
followers = total
107+
)
108+
}
109+
110+
//4.- clase para consumir la Api y clase para retornar rakings
111+
class ParticipansApi{
112+
lateinit var token: String
113+
114+
suspend fun getJwtToken(){
115+
val response=ktorClient.post("https://id.twitch.tv/oauth2/token"){
116+
headers {
117+
append(HttpHeaders.ContentType,"application/x-www-form-urlencoded")
118+
}
119+
setBody(FormDataContent(parameters {
120+
append("client_id",CLIENTID)
121+
append("client_secret",SECRET)
122+
append("grant_type","client_credentials")
123+
}))
124+
}
125+
if (response.status.value!=200) throw Exception("error conecting twitch ${response.bodyAsText()}")
126+
127+
token=response.body<Token>().token
128+
}
129+
130+
suspend fun getTwitchUser(userName:String):TwitchUserDto?{
131+
val response=ktorClient.get("https://api.twitch.tv/helix/users?login=$userName"){
132+
headers {
133+
append(HttpHeaders.Authorization,"Bearer $token")
134+
append("Client-Id",CLIENTID)
135+
}
136+
}
137+
if (response.status.value!=200) return null
138+
return if (response.body<Data>().data.isEmpty()) null else response.body<Data>().data.first()
139+
}
140+
141+
suspend fun getNumberFollwers(userId: String): Long {
142+
val response = ktorClient.get("https://api.twitch.tv/helix/channels/followers?broadcaster_id=$userId") {
143+
headers {
144+
append(HttpHeaders.Authorization, "Bearer $token")
145+
append("Client-Id", CLIENTID)
146+
}
147+
}
148+
if (response.status.value != 200) return 0
149+
return response.body<Followers>().total
150+
}
151+
152+
}
153+
154+
class Ranking(private val api:ParticipansApi){
155+
156+
suspend fun getListTwitchUsers(): Flow<TwitchUser> = coroutineScope {
157+
return@coroutineScope async(Dispatchers.IO){
158+
val users= mutableListOf<TwitchUser>()
159+
for (par in participans){
160+
val user=api.getTwitchUser(par)
161+
if (user==null) users.add(TwitchUser(par, LocalDateTime.now(),0))
162+
if (user!=null){
163+
val followers=api.getNumberFollwers(user.id)
164+
users.add(user.toTwicthUser(followers))
165+
}
166+
167+
}
168+
users.asFlow()
169+
}.await()
170+
}
171+
172+
suspend fun rankOfFollowers(usersTwitch: List<TwitchUser>){
173+
usersTwitch.sortedByDescending{ it.followers }.run {
174+
println("Ranking for followers")
175+
this.forEach {
176+
if (it.followers==0L) println("The user ${it.userName} does not have a twitch account")
177+
else println("${it.userName} followers: ${it.followers}")
178+
}
179+
}
180+
181+
}
182+
183+
suspend fun rankOfCreatedAt(usersTwitch: List<TwitchUser>){
184+
usersTwitch.sortedBy{ it.createdAt }.run {
185+
println("Ranking for Created At")
186+
this.forEach {
187+
if (it.followers==0L) println("The user ${it.userName} does not have a twitch account")
188+
else println("${it.userName} createdAr: ${it.createdAt.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))}")
189+
}
190+
}
191+
192+
}
193+
194+
}
195+
196+
197+
fun main(): Unit= runBlocking {
198+
val api = ParticipansApi()
199+
api.getJwtToken()
200+
val rank=Ranking(api)
201+
val usersTwitch=rank.getListTwitchUsers().toList()
202+
rank.rankOfFollowers(usersTwitch)
203+
rank.rankOfCreatedAt(usersTwitch)
204+
205+
}

0 commit comments

Comments
 (0)