forked from recloudstream/cloudstream
		
	Merge remote-tracking branch 'origin/master'
This commit is contained in:
		
						commit
						a114c8658e
					
				
					 9 changed files with 488 additions and 64 deletions
				
			
		
							
								
								
									
										33
									
								
								.github/ISSUE_TEMPLATE/-bug--short-title.md
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								.github/ISSUE_TEMPLATE/-bug--short-title.md
									
										
									
									
										vendored
									
									
								
							|  | @ -1,33 +0,0 @@ | ||||||
| --- |  | ||||||
| name: "[Bug] Short Title" |  | ||||||
| about: 'Report any bugs or errors found on App. ' |  | ||||||
| title: '' |  | ||||||
| labels: '' |  | ||||||
| assignees: '' |  | ||||||
| 
 |  | ||||||
| --- |  | ||||||
| 
 |  | ||||||
| **Guidelines:** |  | ||||||
| - [ ] It **is not** a duplicate issue. |  | ||||||
| - [ ] If related to a provider, I have checked the site and it works, but not the app. |  | ||||||
| 
 |  | ||||||
| **To Reproduce** |  | ||||||
| Steps to reproduce the behavior: |  | ||||||
| 1. Go to '...' |  | ||||||
| 2. Click on '....' |  | ||||||
| 3. Scroll down to '....' |  | ||||||
| 4. See error |  | ||||||
| 
 |  | ||||||
| **Expected behavior** |  | ||||||
| A clear and concise description of what you expected to happen. |  | ||||||
| 
 |  | ||||||
| **Screenshots or video** |  | ||||||
| If applicable, add screenshots to help explain your problem. |  | ||||||
| 
 |  | ||||||
| **Device (please complete the following information):** |  | ||||||
|  - Android Version: [e.g. Android 11 API 30, Android TV]  |  | ||||||
|  - App Version: [e.g. v2.7.14] |  | ||||||
|  - Provider: [e.g. https://trailers.to/en/movie/4391225/red-notice-2021] |  | ||||||
| 
 |  | ||||||
| **Additional context** |  | ||||||
| Add any other context about the problem here. |  | ||||||
|  | @ -1,24 +0,0 @@ | ||||||
| --- |  | ||||||
| name: "[Feature Request] Title" |  | ||||||
| about: 'Suggest enhancement for the App. ' |  | ||||||
| title: '' |  | ||||||
| labels: '' |  | ||||||
| assignees: '' |  | ||||||
| 
 |  | ||||||
| --- |  | ||||||
| 
 |  | ||||||
| **Guidelines:** |  | ||||||
| - [ ] It **is not** a duplicate issue. |  | ||||||
| - [ ] It **is not** a request to add a website. Write it here instead https://github.com/LagradOst/CloudStream-3/issues/24 |  | ||||||
| 
 |  | ||||||
| **Choose one of the following:** |  | ||||||
| - UI/UX enhancement |  | ||||||
| - New feature |  | ||||||
| - Other |  | ||||||
| 
 |  | ||||||
| **Describe your request here** *(fill this up)* |  | ||||||
| - [ ] How it works. |  | ||||||
| - [ ] Issues it solves. |  | ||||||
| - [ ] Why it is needed. |  | ||||||
| 
 |  | ||||||
| **Other related info** |  | ||||||
							
								
								
									
										83
									
								
								.github/ISSUE_TEMPLATE/application-bug.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								.github/ISSUE_TEMPLATE/application-bug.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | ||||||
|  | name: 🐞 Application Issue Report | ||||||
|  | description: Report a issue in CloudStream | ||||||
|  | labels: [bug] | ||||||
|  | body: | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: reproduce-steps | ||||||
|  |     attributes: | ||||||
|  |       label: Steps to reproduce | ||||||
|  |       description: Provide an example of the issue. | ||||||
|  |       placeholder: | | ||||||
|  |         Example: | ||||||
|  |           1. First step | ||||||
|  |           2. Second step | ||||||
|  |           3. Issue here | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: expected-behavior | ||||||
|  |     attributes: | ||||||
|  |       label: Expected behavior | ||||||
|  |       placeholder: | | ||||||
|  |         Example: | ||||||
|  |           "This should happen..." | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: actual-behavior | ||||||
|  |     attributes: | ||||||
|  |       label: Actual behavior | ||||||
|  |       placeholder: | | ||||||
|  |         Example: | ||||||
|  |           "This happened instead..." | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: input | ||||||
|  |     id: cloudstream-version | ||||||
|  |     attributes: | ||||||
|  |       label: Cloudstream version | ||||||
|  |       description: | | ||||||
|  |         You can find your Cloudstream version in **Settings**. | ||||||
|  |       placeholder: | | ||||||
|  |         Example: "2.8.16" | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: input | ||||||
|  |     id: android-version | ||||||
|  |     attributes: | ||||||
|  |       label: Android version | ||||||
|  |       description: | | ||||||
|  |         You can find this somewhere in your Android settings. | ||||||
|  |       placeholder: | | ||||||
|  |         Example: "Android 12" | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: other-details | ||||||
|  |     attributes: | ||||||
|  |       label: Other details | ||||||
|  |       placeholder: | | ||||||
|  |         Additional details and attachments. | ||||||
|  | 
 | ||||||
|  |   - type: checkboxes | ||||||
|  |     id: acknowledgements | ||||||
|  |     attributes: | ||||||
|  |       label: Acknowledgements | ||||||
|  |       description: Your issue will be closed if you haven't done these steps. | ||||||
|  |       options: | ||||||
|  |         - label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open issue. | ||||||
|  |           required: true | ||||||
|  |         - label: I have written a short but informative title. | ||||||
|  |           required: true | ||||||
|  |         - label: I have updated the app to pre-release version **[Latest](https://github.com/LagradOst/CloudStream-3/releases)**. | ||||||
|  |           required: true | ||||||
|  |         - label: If related to a provider, I have checked the site and it works, but not the app.  | ||||||
|  |           required: true | ||||||
|  |         - label: I will fill out all of the requested information in this form. | ||||||
|  |           required: true | ||||||
							
								
								
									
										35
									
								
								.github/ISSUE_TEMPLATE/feature-request.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								.github/ISSUE_TEMPLATE/feature-request.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | name: ⭐ Feature request | ||||||
|  | description: Suggest a feature to improve the app | ||||||
|  | labels: [feature request] | ||||||
|  | body: | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: feature-description | ||||||
|  |     attributes: | ||||||
|  |       label: Describe your suggested feature | ||||||
|  |       description: How can an existing source be improved? | ||||||
|  |       placeholder: | | ||||||
|  |         Example: | ||||||
|  |           "It should work like this..." | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: other-details | ||||||
|  |     attributes: | ||||||
|  |       label: Other details | ||||||
|  |       placeholder: | | ||||||
|  |         Additional details and attachments. | ||||||
|  | 
 | ||||||
|  |   - type: checkboxes | ||||||
|  |     id: acknowledgements | ||||||
|  |     attributes: | ||||||
|  |       label: Acknowledgements | ||||||
|  |       description: Your issue will be closed if you haven't done these steps. | ||||||
|  |       options: | ||||||
|  |         - label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open issue. | ||||||
|  |           required: true | ||||||
|  |         - label: I have written a short but informative title. | ||||||
|  |           required: true | ||||||
|  |         - label: I will fill out all of the requested information in this form. | ||||||
|  |           required: true | ||||||
							
								
								
									
										84
									
								
								.github/ISSUE_TEMPLATE/provider-bug.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								.github/ISSUE_TEMPLATE/provider-bug.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | ||||||
|  | name: 🐞 Provider Issue Report | ||||||
|  | description: Report a source issue | ||||||
|  | labels: [provider] | ||||||
|  | body: | ||||||
|  | 
 | ||||||
|  |   - type: input | ||||||
|  |     id: source | ||||||
|  |     attributes: | ||||||
|  |       label: Source information | ||||||
|  |       description: | | ||||||
|  |         You can find the source name in navigation drawer. | ||||||
|  |       placeholder: | | ||||||
|  |         Example: "Bflix" | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: input | ||||||
|  |     id: source-url | ||||||
|  |     attributes: | ||||||
|  |       label: Source link | ||||||
|  |       placeholder: | | ||||||
|  |         Example: | ||||||
|  |           "www.example.org" | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: reproduce-steps | ||||||
|  |     attributes: | ||||||
|  |       label: Steps to reproduce | ||||||
|  |       description: Provide an example of the issue. | ||||||
|  |       placeholder: | | ||||||
|  |         Example: | ||||||
|  |           1. First step | ||||||
|  |           2. Second step | ||||||
|  |           3. Issue here | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: input | ||||||
|  |     id: cloudstream-version | ||||||
|  |     attributes: | ||||||
|  |       label: CloudStream version | ||||||
|  |       description: | | ||||||
|  |         You can find your CloudStream version in **Settings**. | ||||||
|  |       placeholder: | | ||||||
|  |         Example: "2.8.16" | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: input | ||||||
|  |     id: android-version | ||||||
|  |     attributes: | ||||||
|  |       label: Android version | ||||||
|  |       description: | | ||||||
|  |         You can find this somewhere in your Android settings. | ||||||
|  |       placeholder: | | ||||||
|  |         Example: "Android 12" | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  | 
 | ||||||
|  |   - type: textarea | ||||||
|  |     id: other-details | ||||||
|  |     attributes: | ||||||
|  |       label: Other details | ||||||
|  |       placeholder: | | ||||||
|  |         Additional details and attachments. | ||||||
|  | 
 | ||||||
|  |   - type: checkboxes | ||||||
|  |     id: acknowledgements | ||||||
|  |     attributes: | ||||||
|  |       label: Acknowledgements | ||||||
|  |       description: Your issue will be closed if you haven't done these steps. | ||||||
|  |       options: | ||||||
|  |         - label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open issue. | ||||||
|  |           required: true | ||||||
|  |         - label: I have written a short but informative title. | ||||||
|  |           required: true | ||||||
|  |         - label: I have updated the app to pre-release version **[Latest](https://github.com/LagradOst/CloudStream-3/releases)**. | ||||||
|  |           required: true | ||||||
|  |         - label: If related to a provider, I have checked the site and it works, but not the app.  | ||||||
|  |           required: true | ||||||
|  |         - label: I will fill out all of the requested information in this form. | ||||||
|  |           required: true | ||||||
|  | @ -102,6 +102,7 @@ object APIHolder { | ||||||
|             TenshiProvider(), |             TenshiProvider(), | ||||||
|             WcoProvider(), |             WcoProvider(), | ||||||
|             AnimePaheProvider(), |             AnimePaheProvider(), | ||||||
|  |             DreamSubProvider(), | ||||||
|             NineAnimeProvider(), |             NineAnimeProvider(), | ||||||
|             AnimeWorldProvider(), |             AnimeWorldProvider(), | ||||||
|             ZoroProvider(), |             ZoroProvider(), | ||||||
|  |  | ||||||
|  | @ -0,0 +1,263 @@ | ||||||
|  | package com.lagradost.cloudstream3.animeproviders | ||||||
|  | 
 | ||||||
|  | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addRating | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer | ||||||
|  | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
|  | import org.jsoup.nodes.Element | ||||||
|  | 
 | ||||||
|  | class DreamSubProvider : MainAPI() { | ||||||
|  |     override var mainUrl = "https://dreamsub.me" | ||||||
|  |     override var name = "DreamSub" | ||||||
|  |     override val lang = "it" | ||||||
|  |     override val hasMainPage = true | ||||||
|  | 
 | ||||||
|  |     override val supportedTypes = setOf( | ||||||
|  |         TvType.Anime, | ||||||
|  |         TvType.AnimeMovie, | ||||||
|  |         TvType.OVA | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     companion object { | ||||||
|  |         fun getType(t: String?): TvType { | ||||||
|  |             return when (t?.lowercase()) { | ||||||
|  |                 "film" -> TvType.AnimeMovie | ||||||
|  |                 "ova" -> TvType.OVA | ||||||
|  |                 else -> TvType.Anime | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun getStatus(t: String?): ShowStatus? { | ||||||
|  |             return when (t?.lowercase()) { | ||||||
|  |                 "conclusa" -> ShowStatus.Completed | ||||||
|  |                 "in corso" -> ShowStatus.Ongoing | ||||||
|  |                 else -> null | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun Element.toSearchResponse(): AnimeSearchResponse { | ||||||
|  |         val title = this.select(".title").first()?.text() | ||||||
|  |             ?: throw ErrorLoadingException("No title found") | ||||||
|  |         val url = this.select(".showStreaming a").first()?.attr("href") | ||||||
|  |             ?: throw ErrorLoadingException("No url found") | ||||||
|  | 
 | ||||||
|  |         val type = TvType.Anime | ||||||
|  |         val posterUrl = this.select(".cover").first()?.attr("style") | ||||||
|  |             ?.substringAfter("url(")?.substringBefore(")")?.trim() | ||||||
|  | 
 | ||||||
|  |         val dubInfo = this.select(".showStreaming").first()?.text() | ||||||
|  |             ?.substringAfter("Lingua:")?.substringBefore("\n")?.trim() | ||||||
|  |         val dub = dubInfo?.contains("DUB ITA", ignoreCase = true) ?: false | ||||||
|  |         val sub = dubInfo?.contains("SUB ITA", ignoreCase = true) ?: true | ||||||
|  | 
 | ||||||
|  |         val desc = this.select(".desc").text() | ||||||
|  |         val episodes = desc.substringAfter("Episodi:").substringBefore(",") | ||||||
|  |             .removeSuffix("+").trim().toIntOrNull() | ||||||
|  |         val year = desc.substringAfter("Anno di inizio:").substringBefore(",") | ||||||
|  |             .trim().toIntOrNull() | ||||||
|  | 
 | ||||||
|  |         return newAnimeSearchResponse(title, url, type) { | ||||||
|  |             addDubStatus(dub, sub, episodes, episodes) | ||||||
|  |             this.posterUrl = fixUrlNull(posterUrl) | ||||||
|  |             this.year = year | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun Element.episodeToSearchResponse(): AnimeSearchResponse { | ||||||
|  |         val title = this.select(".item-title a").first()?.text() | ||||||
|  |             ?: throw ErrorLoadingException("No title found") | ||||||
|  |         val url = fixUrlNull(this.select("a").first()?.attr("href")) | ||||||
|  |             ?: throw ErrorLoadingException("No url found") | ||||||
|  | 
 | ||||||
|  |         val type = getType(this.select(".gr-eps").first()?.text()) | ||||||
|  |         val posterUrl = this.select("img").first()?.attr("src") | ||||||
|  |         val episodes = this.select("div[style]").first()?.text() | ||||||
|  |             ?.replace("Ep", "")?.trim()?.toIntOrNull() | ||||||
|  | 
 | ||||||
|  |         val dubInfo = this.select(".grt-dub").first()?.text() | ||||||
|  |         val dub = dubInfo?.contains("DUB ITA", ignoreCase = true) ?: false | ||||||
|  |         val sub = dubInfo?.contains("SUB ITA", ignoreCase = true) ?: true | ||||||
|  | 
 | ||||||
|  |         return newAnimeSearchResponse(title, url, type) { | ||||||
|  |             addDubStatus(dub, sub, episodes, episodes) | ||||||
|  |             this.posterUrl = fixUrlNull(posterUrl) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun Element.toEpisode(season: Int? = null): Episode? { | ||||||
|  |         val available = this.select(".sli-btn").first() != null | ||||||
|  |         if (!available) | ||||||
|  |             return null | ||||||
|  | 
 | ||||||
|  |         val anchor = this.select(".sli-name a") | ||||||
|  |         val href = anchor.attr("href") | ||||||
|  |         val name = anchor.text().substringAfter(":").trim() | ||||||
|  |         val episode = anchor.text().substringAfter("Episodio").substringBefore(":") | ||||||
|  |             .trim().toIntOrNull() | ||||||
|  | 
 | ||||||
|  |         val date = this.select(".sli-name span").text() | ||||||
|  | 
 | ||||||
|  |         return newEpisode(href) { | ||||||
|  |             this.name = if (name != "TBA") name else null | ||||||
|  |             this.season = season | ||||||
|  |             this.episode = episode | ||||||
|  |             addDate(date, "dd MMMM yyyy") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override suspend fun getMainPage(): HomePageResponse { | ||||||
|  |         val document = app.get(mainUrl).document | ||||||
|  |         val list = ArrayList<HomePageList>() | ||||||
|  | 
 | ||||||
|  |         val episodeList = document.select("#episodiRecenti ul.grid-item li").map { | ||||||
|  |             it.episodeToSearchResponse() | ||||||
|  |         } | ||||||
|  |         list.add(HomePageList("Ultimi Episodi", episodeList)) | ||||||
|  | 
 | ||||||
|  |         val updatedList = document.select("#episodiNuovi ul.grid-item li").map { | ||||||
|  |             it.episodeToSearchResponse() | ||||||
|  |         } | ||||||
|  |         list.add(HomePageList("Ultimi Aggiornamenti", updatedList)) | ||||||
|  | 
 | ||||||
|  |         val recommendedList = document.select("#sliderEvidenza .tvBlock").map { | ||||||
|  |             it.toSearchResponse() | ||||||
|  |         } | ||||||
|  |         list.add(HomePageList("In Evidenza", recommendedList)) | ||||||
|  | 
 | ||||||
|  |         val lastedList = document.select("#sliderUltimeInserite .tvBlock").map { | ||||||
|  |             it.toSearchResponse() | ||||||
|  |         } | ||||||
|  |         list.add(HomePageList("Ultime Inserite", lastedList)) | ||||||
|  |         return HomePageResponse(list) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override suspend fun search(query: String): List<SearchResponse> { | ||||||
|  |         val document = app.get("$mainUrl/search/?q=$query").document | ||||||
|  |         return document.select(".tvBlock").map { | ||||||
|  |             it.toSearchResponse() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override suspend fun load(url: String): LoadResponse { | ||||||
|  |         val document = app.get(url).document | ||||||
|  | 
 | ||||||
|  |         val details = document.select("#animeDetails").first() | ||||||
|  |             ?: throw ErrorLoadingException("Not found") | ||||||
|  | 
 | ||||||
|  |         val title = details.select(".dc-title").text() | ||||||
|  |         val plot = document.select("#tramaLong").first()?.text() | ||||||
|  |             ?: document.select(".dci-desc").first()?.text() | ||||||
|  |         val posterUrl = fixUrl(details.select(".dc-thumb img").attr("src")) | ||||||
|  | 
 | ||||||
|  |         val rating = document.select("#vote_percent").text() | ||||||
|  |         val trailerUrl = document.select("#media-play iframe").attr("data-url") | ||||||
|  | 
 | ||||||
|  |         var type: TvType = TvType.Anime | ||||||
|  |         var duration: String? = null | ||||||
|  |         var dub = false | ||||||
|  |         var tags: List<String> = listOf() | ||||||
|  |         var year: Int? = null | ||||||
|  |         var status: ShowStatus? = null | ||||||
|  |         var japName: String? = null | ||||||
|  | 
 | ||||||
|  |         for (meta in document.select(".dci-spe .dcis")) { | ||||||
|  |             val key = meta.select("b").text() | ||||||
|  |             val value = meta.text().removePrefix(key).trim() | ||||||
|  |             when (key) { | ||||||
|  |                 "Tipo:" -> type = getType(value) | ||||||
|  |                 "Durata:" -> duration = value | ||||||
|  |                 "Lingua:" -> dub = value.contains("DUB ITA", ignoreCase = true) | ||||||
|  |                 "Genere:" -> tags = meta.select("a").map { it.text() } | ||||||
|  |                 "Data:" -> { | ||||||
|  |                     val values = value.split(",") | ||||||
|  |                     year = values[0].substringBefore(" a ").trim() | ||||||
|  |                         .split(" ").getOrNull(2)?.toIntOrNull() | ||||||
|  |                     status = getStatus(values.getOrNull(1)?.trim()) | ||||||
|  |                 } | ||||||
|  |                 // "Titolo giapponese:" -> japName = value | ||||||
|  |                 "Altri titoli:" -> japName = value | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         val episodes = mutableListOf<Episode>() | ||||||
|  |         val seasonElements = document.select("#episodes-sv > li.mainSeas") | ||||||
|  |         val episodeElements = document.select("#episodes-sv li.ep-item") | ||||||
|  |         when { | ||||||
|  |             seasonElements.isNotEmpty() -> { | ||||||
|  |                 seasonElements.forEachIndexed { index, element -> | ||||||
|  |                     val season = index + 1 | ||||||
|  |                     element.select("li.ep-item").forEach { | ||||||
|  |                         val episode = it.toEpisode(season) | ||||||
|  |                         if (episode != null) | ||||||
|  |                             episodes.add(episode) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             episodeElements.isNotEmpty() -> { | ||||||
|  |                 episodeElements.forEach { | ||||||
|  |                     val episode = it.toEpisode() | ||||||
|  |                     if (episode != null) | ||||||
|  |                         episodes.add(episode) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else -> episodes.add(newEpisode(url)) // Movie or Special | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         val recommendations = document.select(".related-list ul.grid-item li").map { | ||||||
|  |             it.episodeToSearchResponse() | ||||||
|  |         } | ||||||
|  |         val comingSoon = episodes.isEmpty() | ||||||
|  | 
 | ||||||
|  |         return newAnimeLoadResponse(title, url, type) { | ||||||
|  |             addEpisodes(if (dub) DubStatus.Dubbed else DubStatus.Subbed, episodes) | ||||||
|  |             addPoster(posterUrl) | ||||||
|  |             addRating(rating) | ||||||
|  |             addDuration(duration) | ||||||
|  |             addTrailer(trailerUrl) | ||||||
|  |             this.japName = japName | ||||||
|  |             this.year = year | ||||||
|  |             this.showStatus = status | ||||||
|  |             this.plot = plot | ||||||
|  |             this.tags = tags | ||||||
|  |             this.recommendations = recommendations | ||||||
|  |             this.comingSoon = comingSoon | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override suspend fun loadLinks( | ||||||
|  |         data: String, | ||||||
|  |         isCasting: Boolean, | ||||||
|  |         subtitleCallback: (SubtitleFile) -> Unit, | ||||||
|  |         callback: (ExtractorLink) -> Unit | ||||||
|  |     ): Boolean { | ||||||
|  |         val document = app.get(data).document | ||||||
|  | 
 | ||||||
|  |         val links = document.select("#main-content.onlyDesktop .goblock-content > div") | ||||||
|  |         if (links.isEmpty()) | ||||||
|  |             return false | ||||||
|  | 
 | ||||||
|  |         links.forEach { tab -> | ||||||
|  |             val sub = tab.select("b").text().contains("SUB") | ||||||
|  |             tab.select("a.dwButton").forEach { | ||||||
|  |                 val title = document.select("#current_episode_name").text() | ||||||
|  |                     .substringAfter(":").trim() | ||||||
|  |                 val url = it.attr("href") | ||||||
|  |                 val quality = getQualityFromName(it.text()) | ||||||
|  |                 callback.invoke( | ||||||
|  |                     ExtractorLink( | ||||||
|  |                         name, | ||||||
|  |                         (if (sub) "SUB ITA" else "DUB") + (if (title != "TBA") " - $title" else ""), | ||||||
|  |                         url, | ||||||
|  |                         referer = url, | ||||||
|  |                         headers = mapOf("host" to "https://cdn.dreamsub.me"), | ||||||
|  |                         quality = quality | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -72,13 +72,23 @@ class SoaptwoDayProvider:MainAPI() { | ||||||
|         val title = soup.selectFirst(".hidden-lg > div:nth-child(1) > h4")?.text() ?: "" |         val title = soup.selectFirst(".hidden-lg > div:nth-child(1) > h4")?.text() ?: "" | ||||||
|         val description = soup.selectFirst("p#wrap")?.text()?.trim() |         val description = soup.selectFirst("p#wrap")?.text()?.trim() | ||||||
|         val poster = soup.selectFirst(".col-md-5 > div:nth-child(1) > div:nth-child(1) > img")?.attr("src") |         val poster = soup.selectFirst(".col-md-5 > div:nth-child(1) > div:nth-child(1) > img")?.attr("src") | ||||||
|         val episodes = soup.select("div.alert > div > div > a").mapNotNull { |         val episodes = mutableListOf<Episode>() | ||||||
|             val link = fixUrlNull(it?.attr("href")) ?: return@mapNotNull null |         soup.select("div.alert").forEach { | ||||||
|             val name = it?.text()?.replace(Regex("(^(\\d+)\\.)"),"") |             val season = it?.selectFirst("h4")?.text()?.filter { c -> c.isDigit() }?.toIntOrNull() | ||||||
|             Episode( |             it?.select("div > div > a")?.forEach { entry -> | ||||||
|                 name = name, |                 val link = fixUrlNull(entry?.attr("href")) ?: return@forEach | ||||||
|                 data = link |                 val text = entry?.text() ?: "" | ||||||
|             ) |                 val name = text.replace(Regex("(^(\\d+)\\.)"),"") | ||||||
|  |                 val epNum = text.substring(0, text.indexOf(".")).toIntOrNull() | ||||||
|  |                 episodes.add( | ||||||
|  |                     Episode( | ||||||
|  |                         name = name, | ||||||
|  |                         data = link, | ||||||
|  |                         season = season, | ||||||
|  |                         episode = epNum | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         val otherInfoBody = soup.select("div.col-sm-8 div.panel-body").toString() |         val otherInfoBody = soup.select("div.col-sm-8 div.panel-body").toString() | ||||||
|         //Fetch casts |         //Fetch casts | ||||||
|  |  | ||||||
|  | @ -94,6 +94,11 @@ | ||||||
|         "status": 1, |         "status": 1, | ||||||
|         "url": "https://dramasee.net" |         "url": "https://dramasee.net" | ||||||
|     }, |     }, | ||||||
|  |     "DreamSubProvider": { | ||||||
|  |         "name": "DreamSub", | ||||||
|  |         "status": 1, | ||||||
|  |         "url": "https://dreamsub.me" | ||||||
|  |     }, | ||||||
|     "DubbedAnimeProvider": { |     "DubbedAnimeProvider": { | ||||||
|         "name": "DubbedAnime", |         "name": "DubbedAnime", | ||||||
|         "status": 1, |         "status": 1, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue