uakino: Reformat code
This commit is contained in:
parent
cbcddbd8f3
commit
c8ef8de606
1 changed files with 156 additions and 121 deletions
|
@ -1,14 +1,13 @@
|
||||||
package com.lagradost
|
package com.lagradost
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||||
|
import java.util.*
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class UakinoProvider : MainAPI() {
|
class UakinoProvider : MainAPI() {
|
||||||
|
|
||||||
|
@ -18,50 +17,46 @@ class UakinoProvider : MainAPI() {
|
||||||
override val hasMainPage = true
|
override val hasMainPage = true
|
||||||
override var lang = "uk"
|
override var lang = "uk"
|
||||||
override val hasDownloadSupport = true
|
override val hasDownloadSupport = true
|
||||||
override val supportedTypes = setOf(
|
override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries, TvType.Anime)
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries,
|
|
||||||
TvType.Anime
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sections
|
// Sections
|
||||||
override val mainPage = mainPageOf(
|
override val mainPage =
|
||||||
"$mainUrl/filmy/page/" to "Фільми",
|
mainPageOf(
|
||||||
"$mainUrl/seriesss/page/" to "Серіали",
|
"$mainUrl/filmy/page/" to "Фільми",
|
||||||
"$mainUrl/seriesss/doramy/page/" to "Дорами",
|
"$mainUrl/seriesss/page/" to "Серіали",
|
||||||
"$mainUrl/animeukr/page/" to "Аніме",
|
"$mainUrl/seriesss/doramy/page/" to "Дорами",
|
||||||
"$mainUrl/cartoon/page/" to "Мультфільми",
|
"$mainUrl/animeukr/page/" to "Аніме",
|
||||||
"$mainUrl/cartoon/cartoonseries/page/" to "Мультсеріали",
|
"$mainUrl/cartoon/page/" to "Мультфільми",
|
||||||
)
|
"$mainUrl/cartoon/cartoonseries/page/" to "Мультсеріали",
|
||||||
|
)
|
||||||
|
|
||||||
val blackUrls = "(/news/)|(/franchise/)"
|
val blackUrls = "(/news/)|(/franchise/)"
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
||||||
page: Int,
|
|
||||||
request: MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val document = app.get(request.data + page).document
|
val document = app.get(request.data + page).document
|
||||||
val home = document.select("div.owl-item, div.movie-item")
|
val home =
|
||||||
.filterNot { el -> el.select("a.movie-title, a.full-movie").attr("href").contains(Regex(blackUrls)) }
|
document
|
||||||
.map {
|
.select("div.owl-item, div.movie-item")
|
||||||
Log.d("CakesTwix-Debug", it.select("a.movie-title, a.full-movie").attr("href"))
|
.filterNot { el ->
|
||||||
it.toSearchResponse()
|
el.select("a.movie-title, a.full-movie").attr("href").contains(Regex(blackUrls))
|
||||||
}
|
}
|
||||||
|
.map {
|
||||||
|
// Log.d("CakesTwix-Debug", it.select("a.movie-title, a.full-movie").attr("href"))
|
||||||
|
it.toSearchResponse()
|
||||||
|
}
|
||||||
return newHomePageResponse(request.name, home)
|
return newHomePageResponse(request.name, home)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Element.toSearchResponse(): SearchResponse {
|
private fun Element.toSearchResponse(): SearchResponse {
|
||||||
val title = this.selectFirst("a.movie-title, div.full-movie-title")?.text()?.trim().toString()
|
val title =
|
||||||
|
this.selectFirst("a.movie-title, div.full-movie-title")?.text()?.trim().toString()
|
||||||
val href = this.selectFirst("a.movie-title, a.full-movie")?.attr("href").toString()
|
val href = this.selectFirst("a.movie-title, a.full-movie")?.attr("href").toString()
|
||||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl }
|
||||||
this.posterUrl = posterUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun Element.getSeasonInfo(): SearchResponse {
|
private suspend fun Element.getSeasonInfo(): SearchResponse {
|
||||||
Log.d("CakesTwix-Debug", "getSeasonInfo: ${this.attr("href")}")
|
// Log.d("CakesTwix-Debug", "getSeasonInfo: ${this.attr("href")}")
|
||||||
val document = app.get(this.attr("href")).document
|
val document = app.get(this.attr("href")).document
|
||||||
val title = document.selectFirst("h1 span.solototle")?.text()?.trim().toString()
|
val title = document.selectFirst("h1 span.solototle")?.text()?.trim().toString()
|
||||||
val poster = mainUrl + document.selectFirst("div.film-poster img")?.attr("src").toString()
|
val poster = mainUrl + document.selectFirst("div.film-poster img")?.attr("src").toString()
|
||||||
|
@ -69,24 +64,27 @@ class UakinoProvider : MainAPI() {
|
||||||
return newMovieSearchResponse(title, this.attr("href"), TvType.Movie) {
|
return newMovieSearchResponse(title, this.attr("href"), TvType.Movie) {
|
||||||
this.posterUrl = poster
|
this.posterUrl = poster
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
override suspend fun search(query: String): List<SearchResponse> {
|
||||||
val document = app.post(
|
val document =
|
||||||
url = mainUrl,
|
app.post(
|
||||||
data = mapOf(
|
url = mainUrl,
|
||||||
"do" to "search",
|
data =
|
||||||
"subaction" to "search",
|
mapOf(
|
||||||
"story" to query.replace(" ", "+")
|
"do" to "search",
|
||||||
|
"subaction" to "search",
|
||||||
|
"story" to query.replace(" ", "+")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
).document
|
.document
|
||||||
|
|
||||||
return document.select("div.movie-item.short-item")
|
return document
|
||||||
.filterNot { el -> el.select("a.movie-title, a.full-movie").attr("href").contains(Regex(blackUrls)) }
|
.select("div.movie-item.short-item")
|
||||||
.map {
|
.filterNot { el ->
|
||||||
it.toSearchResponse()
|
el.select("a.movie-title, a.full-movie").attr("href").contains(Regex(blackUrls))
|
||||||
}
|
}
|
||||||
|
.map { it.toSearchResponse() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detailed information
|
// Detailed information
|
||||||
|
@ -108,7 +106,9 @@ class UakinoProvider : MainAPI() {
|
||||||
contains("Рік виходу:") -> year = metadata.select(".fi-desc").text().toInt()
|
contains("Рік виходу:") -> year = metadata.select(".fi-desc").text().toInt()
|
||||||
contains("Жанр:") -> tags = metadata.select(".fi-desc").text().split(" , ")
|
contains("Жанр:") -> tags = metadata.select(".fi-desc").text().split(" , ")
|
||||||
contains("Актори:") -> actors = metadata.select(".fi-desc").text().split(", ")
|
contains("Актори:") -> actors = metadata.select(".fi-desc").text().split(", ")
|
||||||
contains("") -> rating = metadata.select(".fi-desc").text().substringBefore("/").toRatingInt()
|
contains("") ->
|
||||||
|
rating =
|
||||||
|
metadata.select(".fi-desc").text().substringBefore("/").toRatingInt()
|
||||||
}
|
}
|
||||||
// Log.d("CakesTwix-Debug", this)
|
// Log.d("CakesTwix-Debug", this)
|
||||||
// Log.d("CakesTwix-Debug", metadata.select(".fi-desc").text())
|
// Log.d("CakesTwix-Debug", metadata.select(".fi-desc").text())
|
||||||
|
@ -118,43 +118,50 @@ class UakinoProvider : MainAPI() {
|
||||||
// reversed need for check "Мультсеріали"
|
// reversed need for check "Мультсеріали"
|
||||||
// tags: Мультфільми , Мультсеріали
|
// tags: Мультфільми , Мультсеріали
|
||||||
// It's Cartoon, not Movie
|
// It's Cartoon, not Movie
|
||||||
var tvType = with(tags.reversed()){
|
var tvType =
|
||||||
when{
|
with(tags.reversed()) {
|
||||||
contains("Повнометражне аніме") -> TvType.AnimeMovie
|
when {
|
||||||
contains("Мультсеріали") -> TvType.Cartoon
|
contains("Повнометражне аніме") -> TvType.AnimeMovie
|
||||||
contains("Мультфільми") -> TvType.Movie
|
contains("Мультсеріали") -> TvType.Cartoon
|
||||||
contains("Багатосерійне аніме") -> TvType.Anime
|
contains("Мультфільми") -> TvType.Movie
|
||||||
contains("Дорами") -> TvType.AsianDrama
|
contains("Багатосерійне аніме") -> TvType.Anime
|
||||||
else -> TvType.Others
|
contains("Дорами") -> TvType.AsianDrama
|
||||||
|
else -> TvType.Others
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Log.d("CakesTwix-Debug", tvType.toString())
|
// Log.d("CakesTwix-Debug", tvType.toString())
|
||||||
if (tvType == TvType.Others) {
|
if (tvType == TvType.Others) {
|
||||||
tvType = if (url.contains(Regex("(/anime-series)|(/seriesss)|(/cartoonseries)"))) TvType.TvSeries else TvType.Movie
|
tvType =
|
||||||
|
if (url.contains(Regex("(/anime-series)|(/seriesss)|(/cartoonseries)")))
|
||||||
|
TvType.TvSeries
|
||||||
|
else TvType.Movie
|
||||||
}
|
}
|
||||||
|
|
||||||
val description = document.selectFirst("div[itemprop=description]")?.text()?.trim()
|
val description = document.selectFirst("div[itemprop=description]")?.text()?.trim()
|
||||||
val trailer = document.selectFirst("iframe#pre")?.attr("data-src")
|
val trailer = document.selectFirst("iframe#pre")?.attr("data-src")
|
||||||
|
|
||||||
// Add seasons to recommendations
|
// Add seasons to recommendations
|
||||||
val recommendations = document.select(".seasons li a").map{
|
val recommendations =
|
||||||
it.getSeasonInfo()
|
document.select(".seasons li a").map { it.getSeasonInfo() }.toMutableList()
|
||||||
}.toMutableList()
|
|
||||||
|
|
||||||
// Other recommendations
|
// Other recommendations
|
||||||
recommendations += document.select(".related-item").map {
|
recommendations += document.select(".related-item").map { it.toSearchResponse() }
|
||||||
it.toSearchResponse()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return to app
|
// Return to app
|
||||||
// Parse Episodes as Series
|
// Parse Episodes as Series
|
||||||
return if (tvType != TvType.Movie && tvType != TvType.AnimeMovie) {
|
return if (tvType != TvType.Movie && tvType != TvType.AnimeMovie) {
|
||||||
val id = url.split("/").last().split("-").first()
|
val id = url.split("/").last().split("-").first()
|
||||||
val episodes =
|
val episodes =
|
||||||
app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}")
|
app.get(
|
||||||
.parsedSafe<Responses>()?.response.let {
|
"$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}"
|
||||||
Jsoup.parse(it.toString()).select("div.playlists-videos li").mapNotNull { eps ->
|
)
|
||||||
val href = "$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}"
|
.parsedSafe<Responses>()
|
||||||
|
?.response
|
||||||
|
.let {
|
||||||
|
Jsoup.parse(it.toString()).select("div.playlists-videos li").mapNotNull {
|
||||||
|
eps ->
|
||||||
|
val href =
|
||||||
|
"$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}"
|
||||||
val name = eps.text().trim() // Серія 1
|
val name = eps.text().trim() // Серія 1
|
||||||
if (href.isNotEmpty()) {
|
if (href.isNotEmpty()) {
|
||||||
Episode(
|
Episode(
|
||||||
|
@ -166,7 +173,7 @@ class UakinoProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newTvSeriesLoadResponse(title, url, tvType, episodes.distinctBy{ it.name }) {
|
newTvSeriesLoadResponse(title, url, tvType, episodes.distinctBy { it.name }) {
|
||||||
this.posterUrl = poster
|
this.posterUrl = poster
|
||||||
this.year = year
|
this.year = year
|
||||||
this.plot = description
|
this.plot = description
|
||||||
|
@ -199,36 +206,43 @@ class UakinoProvider : MainAPI() {
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val dataList = data.split(",")
|
val dataList = data.split(",")
|
||||||
// TODO: OPTIMIZE code!!! Remove this shitty code as soon as possible!!!!!!
|
// TODO: OPTIMIZE code!!! Remove this shitty code as soon as possible!!!!!!
|
||||||
if(dataList.size == 1){
|
if (dataList.size == 1) {
|
||||||
val id = data.split("/").last().split("-").first()
|
val id = data.split("/").last().split("-").first()
|
||||||
val responseGet = app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}").parsedSafe<Responses>()
|
val responseGet =
|
||||||
|
app.get(
|
||||||
|
"$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}"
|
||||||
|
)
|
||||||
|
.parsedSafe<Responses>()
|
||||||
if (responseGet?.success == true) { // Its serial
|
if (responseGet?.success == true) { // Its serial
|
||||||
responseGet.response?.let {
|
responseGet.response?.let {
|
||||||
Jsoup.parse(it).select("div.playlists-videos li")
|
Jsoup.parse(it).select("div.playlists-videos li").mapNotNull { eps ->
|
||||||
.mapNotNull { eps ->
|
var href = eps.attr("data-file") // ashdi
|
||||||
var href = eps.attr("data-file") // ashdi
|
// Can be without https:
|
||||||
// Can be without https:
|
if (!href.contains("https://")) {
|
||||||
if (!href.contains("https://")) {
|
href = "https:$href"
|
||||||
href = "https:$href"
|
|
||||||
}
|
|
||||||
val dub = eps.attr("data-voice") // FanWoxUA
|
|
||||||
|
|
||||||
// Get m3u from player script
|
|
||||||
app.get(href, referer = "$mainUrl/").document.select("script")
|
|
||||||
.map { script ->
|
|
||||||
if (script.data().contains("var player = new Playerjs({")) {
|
|
||||||
val m3uLink = script.data().substringAfterLast("file:\"")
|
|
||||||
.substringBefore("\",")
|
|
||||||
|
|
||||||
// Add as source
|
|
||||||
M3u8Helper.generateM3u8(
|
|
||||||
source = dub,
|
|
||||||
streamUrl = m3uLink,
|
|
||||||
referer = "https://ashdi.vip/"
|
|
||||||
).forEach(callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
val dub = eps.attr("data-voice") // FanWoxUA
|
||||||
|
|
||||||
|
// Get m3u from player script
|
||||||
|
app.get(href, referer = "$mainUrl/").document.select("script").map { script
|
||||||
|
->
|
||||||
|
if (script.data().contains("var player = new Playerjs({")) {
|
||||||
|
val m3uLink =
|
||||||
|
script
|
||||||
|
.data()
|
||||||
|
.substringAfterLast("file:\"")
|
||||||
|
.substringBefore("\",")
|
||||||
|
|
||||||
|
// Add as source
|
||||||
|
M3u8Helper.generateM3u8(
|
||||||
|
source = dub,
|
||||||
|
streamUrl = m3uLink,
|
||||||
|
referer = "https://ashdi.vip/"
|
||||||
|
)
|
||||||
|
.forEach(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Its maybe film
|
// Its maybe film
|
||||||
|
@ -236,16 +250,24 @@ class UakinoProvider : MainAPI() {
|
||||||
val iframeUrl = document.selectFirst("iframe#pre")?.attr("src")
|
val iframeUrl = document.selectFirst("iframe#pre")?.attr("src")
|
||||||
// Get m3u from player script
|
// Get m3u from player script
|
||||||
if (iframeUrl != null) {
|
if (iframeUrl != null) {
|
||||||
app.get(iframeUrl, referer = "$mainUrl/").document.select("script").map { script ->
|
app.get(iframeUrl, referer = "$mainUrl/").document.select("script").map { script
|
||||||
|
->
|
||||||
if (script.data().contains("var player = new Playerjs({")) {
|
if (script.data().contains("var player = new Playerjs({")) {
|
||||||
val m3uLink = script.data().substringAfterLast("file:\"").substringBefore("\",")
|
val m3uLink =
|
||||||
|
script.data().substringAfterLast("file:\"").substringBefore("\",")
|
||||||
|
|
||||||
// Add as source
|
// Add as source
|
||||||
M3u8Helper.generateM3u8(
|
M3u8Helper.generateM3u8(
|
||||||
source = document.selectFirst("h1 span.solototle")?.text()?.trim().toString(),
|
source =
|
||||||
|
document
|
||||||
|
.selectFirst("h1 span.solototle")
|
||||||
|
?.text()
|
||||||
|
?.trim()
|
||||||
|
.toString(),
|
||||||
streamUrl = m3uLink,
|
streamUrl = m3uLink,
|
||||||
referer = "https://ashdi.vip/"
|
referer = "https://ashdi.vip/"
|
||||||
).forEach(callback)
|
)
|
||||||
|
.forEach(callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,30 +276,38 @@ class UakinoProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseGet = app.get(dataList[0]).parsedSafe<Responses>() // ajax link
|
val responseGet = app.get(dataList[0]).parsedSafe<Responses>() // ajax link
|
||||||
if (responseGet?.success == true){ // Its serial
|
if (responseGet?.success == true) { // Its serial
|
||||||
responseGet?.response?.let {
|
responseGet?.response?.let {
|
||||||
Jsoup.parse(it).select("div.playlists-videos li:contains(${dataList[1]})").mapNotNull { eps ->
|
Jsoup.parse(it)
|
||||||
var href = eps.attr("data-file") // ashdi
|
.select("div.playlists-videos li:contains(${dataList[1]})")
|
||||||
// Can be without https:
|
.mapNotNull { eps ->
|
||||||
if (! href.contains("https://")) {
|
var href = eps.attr("data-file") // ashdi
|
||||||
href = "https:$href"
|
// Can be without https:
|
||||||
}
|
if (!href.contains("https://")) {
|
||||||
val dub = eps.attr("data-voice") // FanWoxUA
|
href = "https:$href"
|
||||||
|
}
|
||||||
|
val dub = eps.attr("data-voice") // FanWoxUA
|
||||||
|
|
||||||
// Get m3u from player script
|
// Get m3u from player script
|
||||||
app.get(href, referer = "$mainUrl/").document.select("script").map { script ->
|
app.get(href, referer = "$mainUrl/").document.select("script").map { script
|
||||||
if (script.data().contains("var player = new Playerjs({")) {
|
->
|
||||||
val m3uLink = script.data().substringAfterLast("file:\"").substringBefore("\",")
|
if (script.data().contains("var player = new Playerjs({")) {
|
||||||
|
val m3uLink =
|
||||||
|
script
|
||||||
|
.data()
|
||||||
|
.substringAfterLast("file:\"")
|
||||||
|
.substringBefore("\",")
|
||||||
|
|
||||||
// Add as source
|
// Add as source
|
||||||
M3u8Helper.generateM3u8(
|
M3u8Helper.generateM3u8(
|
||||||
source = dub,
|
source = dub,
|
||||||
streamUrl = m3uLink,
|
streamUrl = m3uLink,
|
||||||
referer = "https://ashdi.vip/"
|
referer = "https://ashdi.vip/"
|
||||||
).forEach(callback)
|
)
|
||||||
|
.forEach(callback)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Its maybe film
|
// Its maybe film
|
||||||
|
@ -287,20 +317,26 @@ class UakinoProvider : MainAPI() {
|
||||||
if (iframeUrl != null) {
|
if (iframeUrl != null) {
|
||||||
app.get(iframeUrl, referer = "$mainUrl/").document.select("script").map { script ->
|
app.get(iframeUrl, referer = "$mainUrl/").document.select("script").map { script ->
|
||||||
if (script.data().contains("var player = new Playerjs({")) {
|
if (script.data().contains("var player = new Playerjs({")) {
|
||||||
val m3uLink = script.data().substringAfterLast("file:\"").substringBefore("\",")
|
val m3uLink =
|
||||||
|
script.data().substringAfterLast("file:\"").substringBefore("\",")
|
||||||
|
|
||||||
// Add as source
|
// Add as source
|
||||||
M3u8Helper.generateM3u8(
|
M3u8Helper.generateM3u8(
|
||||||
source = document.selectFirst("h1 span.solototle")?.text()?.trim().toString(),
|
source =
|
||||||
|
document
|
||||||
|
.selectFirst("h1 span.solototle")
|
||||||
|
?.text()
|
||||||
|
?.trim()
|
||||||
|
.toString(),
|
||||||
streamUrl = m3uLink,
|
streamUrl = m3uLink,
|
||||||
referer = "https://ashdi.vip/"
|
referer = "https://ashdi.vip/"
|
||||||
).forEach(callback)
|
)
|
||||||
|
.forEach(callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,5 +344,4 @@ class UakinoProvider : MainAPI() {
|
||||||
val success: Boolean?,
|
val success: Boolean?,
|
||||||
val response: String,
|
val response: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue