forked from recloudstream/cloudstream
		
	Merge branch 'my-temporary-work'
fuck git
This commit is contained in:
		
						commit
						42fe04a0b0
					
				
					 18 changed files with 440 additions and 272 deletions
				
			
		
							
								
								
									
										3
									
								
								.idea/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.idea/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,3 +0,0 @@ | ||||||
| # Default ignored files |  | ||||||
| /shelf/ |  | ||||||
| /workspace.xml |  | ||||||
							
								
								
									
										2
									
								
								.idea/gradle.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.idea/gradle.xml
									
										
									
										generated
									
									
									
								
							|  | @ -1,11 +1,11 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project version="4"> | <project version="4"> | ||||||
|   <component name="GradleMigrationSettings" migrationVersion="1" /> |  | ||||||
|   <component name="GradleSettings"> |   <component name="GradleSettings"> | ||||||
|     <option name="linkedExternalProjectsSettings"> |     <option name="linkedExternalProjectsSettings"> | ||||||
|       <GradleProjectSettings> |       <GradleProjectSettings> | ||||||
|         <option name="distributionType" value="DEFAULT_WRAPPED" /> |         <option name="distributionType" value="DEFAULT_WRAPPED" /> | ||||||
|         <option name="externalProjectPath" value="$PROJECT_DIR$" /> |         <option name="externalProjectPath" value="$PROJECT_DIR$" /> | ||||||
|  |         <option name="gradleJvm" value="jbr-11" /> | ||||||
|         <option name="modules"> |         <option name="modules"> | ||||||
|           <set> |           <set> | ||||||
|             <option value="$PROJECT_DIR$" /> |             <option value="$PROJECT_DIR$" /> | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								.idea/jarRepositories.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								.idea/jarRepositories.xml
									
										
									
										generated
									
									
									
								
							|  | @ -24,12 +24,12 @@ | ||||||
|     <remote-repository> |     <remote-repository> | ||||||
|       <option name="id" value="maven" /> |       <option name="id" value="maven" /> | ||||||
|       <option name="name" value="maven" /> |       <option name="name" value="maven" /> | ||||||
|       <option name="url" value="https://jitpack.io" /> |       <option name="url" value="https://github.com/psiegman/mvn-repo/raw/master/releases" /> | ||||||
|     </remote-repository> |     </remote-repository> | ||||||
|     <remote-repository> |     <remote-repository> | ||||||
|       <option name="id" value="maven" /> |       <option name="id" value="maven2" /> | ||||||
|       <option name="name" value="maven" /> |       <option name="name" value="maven2" /> | ||||||
|       <option name="url" value="https://github.com/psiegman/mvn-repo/raw/master/releases" /> |       <option name="url" value="https://jitpack.io" /> | ||||||
|     </remote-repository> |     </remote-repository> | ||||||
|   </component> |   </component> | ||||||
| </project> | </project> | ||||||
							
								
								
									
										8
									
								
								.idea/misc.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								.idea/misc.xml
									
										
									
										generated
									
									
									
								
							|  | @ -1,9 +1,5 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project version="4"> | <project version="4"> | ||||||
|   <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK"> |   <component name="ExternalStorageConfigurationManager" enabled="true" /> | ||||||
|     <output url="file://$PROJECT_DIR$/build/classes" /> |   <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" /> | ||||||
|   </component> |  | ||||||
|   <component name="ProjectType"> |  | ||||||
|     <option name="id" value="Android" /> |  | ||||||
|   </component> |  | ||||||
| </project> | </project> | ||||||
							
								
								
									
										124
									
								
								.idea/uiDesigner.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										124
									
								
								.idea/uiDesigner.xml
									
										
									
										generated
									
									
									
								
							|  | @ -1,124 +0,0 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <project version="4"> |  | ||||||
|   <component name="Palette2"> |  | ||||||
|     <group name="Swing"> |  | ||||||
|       <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" /> |  | ||||||
|         <initial-values> |  | ||||||
|           <property name="text" value="Button" /> |  | ||||||
|         </initial-values> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> |  | ||||||
|         <initial-values> |  | ||||||
|           <property name="text" value="RadioButton" /> |  | ||||||
|         </initial-values> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> |  | ||||||
|         <initial-values> |  | ||||||
|           <property name="text" value="CheckBox" /> |  | ||||||
|         </initial-values> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" /> |  | ||||||
|         <initial-values> |  | ||||||
|           <property name="text" value="Label" /> |  | ||||||
|         </initial-values> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |  | ||||||
|           <preferred-size width="150" height="-1" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |  | ||||||
|           <preferred-size width="150" height="-1" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |  | ||||||
|           <preferred-size width="150" height="-1" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="150" height="50" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="150" height="50" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="150" height="50" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="150" height="50" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="150" height="50" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="150" height="50" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="200" height="200" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> |  | ||||||
|           <preferred-size width="200" height="200" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1"> |  | ||||||
|           <preferred-size width="-1" height="20" /> |  | ||||||
|         </default-constraints> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" /> |  | ||||||
|       </item> |  | ||||||
|       <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> |  | ||||||
|         <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" /> |  | ||||||
|       </item> |  | ||||||
|     </group> |  | ||||||
|   </component> |  | ||||||
| </project> |  | ||||||
							
								
								
									
										2
									
								
								.idea/vcs.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.idea/vcs.xml
									
										
									
										generated
									
									
									
								
							|  | @ -1,6 +1,6 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project version="4"> | <project version="4"> | ||||||
|   <component name="VcsDirectoryMappings"> |   <component name="VcsDirectoryMappings"> | ||||||
|     <mapping directory="$PROJECT_DIR$" vcs="Git" /> |     <mapping directory="" vcs="Git" /> | ||||||
|   </component> |   </component> | ||||||
| </project> | </project> | ||||||
|  | @ -8,6 +8,7 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||||
| import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider | import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider | ||||||
| import com.lagradost.cloudstream3.animeproviders.ShiroProvider | import com.lagradost.cloudstream3.animeproviders.ShiroProvider | ||||||
| import com.lagradost.cloudstream3.animeproviders.TenshiProvider | import com.lagradost.cloudstream3.animeproviders.TenshiProvider | ||||||
|  | import com.lagradost.cloudstream3.animeproviders.WcoProvider | ||||||
| import com.lagradost.cloudstream3.movieproviders.HDMProvider | import com.lagradost.cloudstream3.movieproviders.HDMProvider | ||||||
| import com.lagradost.cloudstream3.movieproviders.LookMovieProvider | import com.lagradost.cloudstream3.movieproviders.LookMovieProvider | ||||||
| import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider | import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider | ||||||
|  | @ -33,6 +34,7 @@ object APIHolder { | ||||||
|     val apis = arrayListOf( |     val apis = arrayListOf( | ||||||
|         ShiroProvider(), |         ShiroProvider(), | ||||||
|         TenshiProvider(), |         TenshiProvider(), | ||||||
|  |         WcoProvider(), | ||||||
|         MeloMovieProvider(), |         MeloMovieProvider(), | ||||||
|         DubbedAnimeProvider(), |         DubbedAnimeProvider(), | ||||||
|         HDMProvider(), |         HDMProvider(), | ||||||
|  |  | ||||||
|  | @ -1,31 +1,24 @@ | ||||||
| package com.lagradost.cloudstream3.animeproviders | package com.lagradost.cloudstream3.animeproviders | ||||||
| 
 | 
 | ||||||
| import android.annotation.SuppressLint | import android.annotation.SuppressLint | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty |  | ||||||
| import com.fasterxml.jackson.module.kotlin.readValue |  | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.extractors.Vidstream |  | ||||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
|  | import khttp.structures.cookie.CookieJar | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| import org.jsoup.nodes.Document | import org.jsoup.nodes.Document | ||||||
| import java.util.* |  | ||||||
| import kotlin.collections.ArrayList |  | ||||||
| import khttp.structures.cookie.CookieJar |  | ||||||
| import java.text.SimpleDateFormat | import java.text.SimpleDateFormat | ||||||
| 
 | import java.util.* | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| class TenshiProvider : MainAPI() { | class TenshiProvider : MainAPI() { | ||||||
| 
 |  | ||||||
|     companion object { |     companion object { | ||||||
|         var token: String? = null |         var token: String? = null | ||||||
|         var cookie: CookieJar? = null |         var cookie: CookieJar? = null | ||||||
| 
 | 
 | ||||||
|         fun getType(t: String): TvType { |         fun getType(t: String): TvType { | ||||||
|             if (t.contains("OVA") || t.contains("Special"))  return TvType.ONA |             return if (t.contains("OVA") || t.contains("Special")) TvType.ONA | ||||||
|             else if (t.contains("Movie")) return TvType.Movie |             else if (t.contains("Movie")) TvType.Movie | ||||||
|             else return TvType.Anime |             else TvType.Anime | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -43,9 +36,7 @@ class TenshiProvider : MainAPI() { | ||||||
| 
 | 
 | ||||||
|     private fun loadToken(): Boolean { |     private fun loadToken(): Boolean { | ||||||
|         return try { |         return try { | ||||||
|             val response = khttp.get( |             val response = khttp.get(mainUrl) | ||||||
|                 "https://tenshi.moe/", |  | ||||||
|             ) |  | ||||||
|             cookie = response.cookies |             cookie = response.cookies | ||||||
|             val document = Jsoup.parse(response.text) |             val document = Jsoup.parse(response.text) | ||||||
|             token = document.selectFirst("""meta[name="csrf-token"]""").attr("content") |             token = document.selectFirst("""meta[name="csrf-token"]""").attr("content") | ||||||
|  | @ -179,7 +170,7 @@ class TenshiProvider : MainAPI() { | ||||||
|         return returnValue |         return returnValue | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun load(slug: String): LoadResponse? { |     override fun load(slug: String): LoadResponse { | ||||||
|         val url = "$mainUrl/anime/${slug}" |         val url = "$mainUrl/anime/${slug}" | ||||||
| 
 | 
 | ||||||
|         val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb")) |         val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb")) | ||||||
|  | @ -189,7 +180,6 @@ class TenshiProvider : MainAPI() { | ||||||
|         val japaneseTitle = document.selectFirst("span.value > span[title=\"Japanese\"]")?.parent()?.text()?.trim() |         val japaneseTitle = document.selectFirst("span.value > span[title=\"Japanese\"]")?.parent()?.text()?.trim() | ||||||
|         val canonicalTitle = document.selectFirst("header.entry-header > h1.mb-3").text().trim() |         val canonicalTitle = document.selectFirst("header.entry-header > h1.mb-3").text().trim() | ||||||
| 
 | 
 | ||||||
|         val isDubbed = false |  | ||||||
|         val episodeNodes = document.select("li[class*=\"episode\"] > a") |         val episodeNodes = document.select("li[class*=\"episode\"] > a") | ||||||
| 
 | 
 | ||||||
|         val episodes = ArrayList<AnimeEpisode>(episodeNodes?.map { |         val episodes = ArrayList<AnimeEpisode>(episodeNodes?.map { | ||||||
|  | @ -212,7 +202,7 @@ class TenshiProvider : MainAPI() { | ||||||
|         val (year) = pattern.find(yearText)!!.destructured |         val (year) = pattern.find(yearText)!!.destructured | ||||||
| 
 | 
 | ||||||
|         val poster = document.selectFirst("img.cover-image")?.attr("src") |         val poster = document.selectFirst("img.cover-image")?.attr("src") | ||||||
|         val type = document.selectFirst("a[href*=\"https://tenshi.moe/type/\"]")?.text()?.trim() |         val type = document.selectFirst("a[href*=\"$mainUrl/type/\"]")?.text()?.trim() | ||||||
| 
 | 
 | ||||||
|         val synopsis = document.selectFirst(".entry-description > .card-body")?.text()?.trim() |         val synopsis = document.selectFirst(".entry-description > .card-body")?.text()?.trim() | ||||||
|         val genre = document.select("li.genre.meta-data > span.value").map { it?.text()?.trim().toString() } |         val genre = document.select("li.genre.meta-data > span.value").map { it?.text()?.trim().toString() } | ||||||
|  | @ -232,7 +222,7 @@ class TenshiProvider : MainAPI() { | ||||||
|             episodes, |             episodes, | ||||||
|             status, |             status, | ||||||
|             synopsis, |             synopsis, | ||||||
|             ArrayList(genre) ?: ArrayList(), |             ArrayList(genre), | ||||||
|             ArrayList(synonyms), |             ArrayList(synonyms), | ||||||
|             null, |             null, | ||||||
|             null, |             null, | ||||||
|  |  | ||||||
|  | @ -0,0 +1,212 @@ | ||||||
|  | package com.lagradost.cloudstream3.animeproviders | ||||||
|  | 
 | ||||||
|  | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.extractors.WcoStream | ||||||
|  | import org.jsoup.Jsoup | ||||||
|  | import org.jsoup.nodes.Document | ||||||
|  | import java.util.* | ||||||
|  | import kotlin.collections.ArrayList | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class WcoProvider : MainAPI() { | ||||||
|  |     companion object { | ||||||
|  |         fun getType(t: String): TvType { | ||||||
|  |             return if (t.contains("OVA") || t.contains("Special")) TvType.ONA | ||||||
|  |             else if (t.contains("Movie")) TvType.Movie | ||||||
|  |             else TvType.Anime | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override val mainUrl: String | ||||||
|  |         get() = "https://wcostream.cc" | ||||||
|  |     override val name: String | ||||||
|  |         get() = "WCO Stream" | ||||||
|  |     override val hasQuickSearch: Boolean | ||||||
|  |         get() = true | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     private fun getSlug(href: String): String { | ||||||
|  |         return href.replace("$mainUrl/anime/", "").replace("/", "") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun fixAnimeLink(url: String): String { | ||||||
|  |         val regex = "watch/([a-zA-Z\\-0-9]*)-episode".toRegex() | ||||||
|  |         val (aniId) = regex.find(url)!!.destructured | ||||||
|  |         return "$mainUrl/anime/$aniId" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun parseSearchPage(soup: Document): ArrayList<SearchResponse> { | ||||||
|  |         val items = soup.select(".film_list-wrap > .flw-item") | ||||||
|  |         if (items.isEmpty()) return ArrayList() | ||||||
|  |         val returnValue = ArrayList<SearchResponse>() | ||||||
|  |         for (i in items) { | ||||||
|  |             val href = fixAnimeLink(i.selectFirst("a").attr("href")) | ||||||
|  |             val img = fixUrl(i.selectFirst("img").attr("data-src")) | ||||||
|  |             val title = i.selectFirst("img").attr("title") | ||||||
|  |             val isDub = !i.select(".pick.film-poster-quality").isEmpty() | ||||||
|  |             val year = i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(1)").text().toIntOrNull() | ||||||
|  |             val type = i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(3)").text() | ||||||
|  | 
 | ||||||
|  |             returnValue.add( | ||||||
|  |                 if (getType(type) == TvType.Movie) { | ||||||
|  |                     MovieSearchResponse( | ||||||
|  |                         title, href, getSlug(href), this.name, TvType.Movie, img, year | ||||||
|  |                     ) | ||||||
|  |                 } else { | ||||||
|  |                     AnimeSearchResponse( | ||||||
|  |                         title, | ||||||
|  |                         href, | ||||||
|  |                         getSlug(href), | ||||||
|  |                         this.name, | ||||||
|  |                         TvType.Anime, | ||||||
|  |                         img, | ||||||
|  |                         year, | ||||||
|  |                         null, | ||||||
|  |                         EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed), | ||||||
|  |                         null, | ||||||
|  |                         null | ||||||
|  |                     ) | ||||||
|  |                 } | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |         return returnValue | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun search(query: String): ArrayList<SearchResponse> { | ||||||
|  |         val url = "$mainUrl/search" | ||||||
|  |         val response = khttp.get(url, params=mapOf("keyword" to query)) | ||||||
|  |         var document = Jsoup.parse(response.text) | ||||||
|  |         val returnValue = parseSearchPage(document) | ||||||
|  | 
 | ||||||
|  |         while (!document.select(".pagination").isEmpty()) { | ||||||
|  |             val link = document.select("a.page-link[rel=\"next\"]") | ||||||
|  |             if (!link.isEmpty()) { | ||||||
|  |                 val extraResponse = khttp.get(fixUrl(link[0].attr("href"))) | ||||||
|  |                 document = Jsoup.parse(extraResponse.text) | ||||||
|  |                 returnValue.addAll(parseSearchPage(document)) | ||||||
|  |             } else { | ||||||
|  |                 break | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnValue | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun quickSearch(query: String): ArrayList<SearchResponse> { | ||||||
|  |         val returnValue: ArrayList<SearchResponse> = ArrayList() | ||||||
|  | 
 | ||||||
|  |         val response = khttp.post( | ||||||
|  |             "https://wcostream.cc/ajax/search", | ||||||
|  |             data=mapOf("keyword" to query) | ||||||
|  |         ).jsonObject.getString("html") // I won't make a dataclass for this shit | ||||||
|  |         val document = Jsoup.parse(response) | ||||||
|  | 
 | ||||||
|  |         document.select("a.nav-item").forEach { | ||||||
|  |             val title = it.selectFirst("img")?.attr("title").toString() | ||||||
|  |             val img = it?.selectFirst("img")?.attr("src") | ||||||
|  |             val href = it?.attr("href").toString() | ||||||
|  |             val isDub = title.contains("(Dub)") | ||||||
|  |             val filmInfo = it?.selectFirst(".film-infor") | ||||||
|  |             val year = filmInfo?.select("span")?.get(0)?.text()?.toIntOrNull() | ||||||
|  |             val type = filmInfo?.select("span")?.get(1)?.text().toString() | ||||||
|  |             if (title != "null") { | ||||||
|  |                 returnValue.add( | ||||||
|  |                     if (getType(type) == TvType.Movie) { | ||||||
|  |                         MovieSearchResponse( | ||||||
|  |                             title, href, getSlug(href), this.name, TvType.Movie, img, year | ||||||
|  |                         ) | ||||||
|  |                     } else { | ||||||
|  |                         AnimeSearchResponse( | ||||||
|  |                             title, | ||||||
|  |                             href, | ||||||
|  |                             getSlug(href), | ||||||
|  |                             this.name, | ||||||
|  |                             TvType.Anime, | ||||||
|  |                             img, | ||||||
|  |                             year, | ||||||
|  |                             null, | ||||||
|  |                             EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed), | ||||||
|  |                             null, | ||||||
|  |                             null | ||||||
|  |                         ) | ||||||
|  |                     } | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnValue | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun load(slug: String): LoadResponse { | ||||||
|  |         val url = "$mainUrl/anime/${slug}" | ||||||
|  | 
 | ||||||
|  |         val response = khttp.get(url, timeout = 120.0) | ||||||
|  |         val document = Jsoup.parse(response.text) | ||||||
|  | 
 | ||||||
|  |         val japaneseTitle = document.selectFirst("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(1)") | ||||||
|  |             ?.text()?.trim()?.replace("Other names:", "")?.trim() | ||||||
|  | 
 | ||||||
|  |         val canonicalTitle = document.selectFirst("meta[name=\"title\"]") | ||||||
|  |             ?.attr("content")?.split("| W")?.get(0).toString() | ||||||
|  | 
 | ||||||
|  |         val isDubbed = canonicalTitle.contains("Dub") | ||||||
|  |         val episodeNodes = document.select(".tab-content .nav-item > a") | ||||||
|  | 
 | ||||||
|  |         val episodes = ArrayList<AnimeEpisode>(episodeNodes?.map { | ||||||
|  |             AnimeEpisode(it.attr("href")) | ||||||
|  |         } | ||||||
|  |             ?: ArrayList<AnimeEpisode>()) | ||||||
|  |         val statusElem = document.selectFirst("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(2)") | ||||||
|  |         val status = when (statusElem?.text()?.replace("Status:", "")?.trim()) { | ||||||
|  |             "Ongoing" -> ShowStatus.Ongoing | ||||||
|  |             "Completed" -> ShowStatus.Completed | ||||||
|  |             else -> null | ||||||
|  |         } | ||||||
|  |         val yearText = document.selectFirst("div.elements div.row > div:nth-child(2) > div.row-line:nth-child(4)")?.text() | ||||||
|  |         val year = yearText?.replace("Date release:", "")?.trim()?.split("-")?.get(0)?.toIntOrNull() | ||||||
|  | 
 | ||||||
|  |         val poster = document.selectFirst(".film-poster-img")?.attr("src") | ||||||
|  |         val type = document.selectFirst("span.item.mr-1 > a")?.text()?.trim() | ||||||
|  | 
 | ||||||
|  |         val synopsis = document.selectFirst(".description > p")?.text()?.trim() | ||||||
|  |         val genre = document.select("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(5) > a").map { it?.text()?.trim().toString() } | ||||||
|  | 
 | ||||||
|  |         return AnimeLoadResponse( | ||||||
|  |             canonicalTitle, | ||||||
|  |             japaneseTitle, | ||||||
|  |             canonicalTitle, | ||||||
|  |             "$mainUrl/anime/${slug}", | ||||||
|  |             this.name, | ||||||
|  |             getType(type ?: ""), | ||||||
|  |             poster, | ||||||
|  |             year, | ||||||
|  |             if(isDubbed) episodes else null, | ||||||
|  |             if(!isDubbed) episodes else null, | ||||||
|  |             status, | ||||||
|  |             synopsis, | ||||||
|  |             ArrayList(genre), | ||||||
|  |             ArrayList(), | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun loadLinks( | ||||||
|  |         data: String, | ||||||
|  |         isCasting: Boolean, | ||||||
|  |         subtitleCallback: (SubtitleFile) -> Unit, | ||||||
|  |         callback: (ExtractorLink) -> Unit | ||||||
|  |     ): Boolean { | ||||||
|  |         val response = khttp.get(data) | ||||||
|  |         val servers = Jsoup.parse(response.text).select("#servers-list > ul > li").map { | ||||||
|  |             mapOf( | ||||||
|  |                 "link" to it?.selectFirst("a")?.attr("data-embed"), | ||||||
|  |                 "title" to it?.selectFirst("span")?.text()?.trim() | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (server in servers) { | ||||||
|  |             WcoStream().getSafeUrl(server["link"].toString(), "")?.forEach { | ||||||
|  |                 callback.invoke(it) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,10 +1,7 @@ | ||||||
| package com.lagradost.cloudstream3.utils | package com.lagradost.cloudstream3.utils | ||||||
| 
 | 
 | ||||||
| import com.lagradost.cloudstream3.utils.extractors.MixDrop | import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||||
| import com.lagradost.cloudstream3.utils.extractors.Mp4Upload | import com.lagradost.cloudstream3.utils.extractors.* | ||||||
| import com.lagradost.cloudstream3.utils.extractors.Shiro |  | ||||||
| import com.lagradost.cloudstream3.utils.extractors.StreamTape |  | ||||||
| import com.lagradost.cloudstream3.utils.extractors.XStreamCdn |  | ||||||
| 
 | 
 | ||||||
| data class ExtractorLink( | data class ExtractorLink( | ||||||
|     val source: String, |     val source: String, | ||||||
|  | @ -54,10 +51,12 @@ fun getAndUnpack(string: String): String? { | ||||||
| val extractorApis: Array<ExtractorApi> = arrayOf( | val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
|     //AllProvider(), |     //AllProvider(), | ||||||
|     Shiro(), |     Shiro(), | ||||||
|  |     WcoStream(), | ||||||
|     Mp4Upload(), |     Mp4Upload(), | ||||||
|     StreamTape(), |     StreamTape(), | ||||||
|     MixDrop(), |     MixDrop(), | ||||||
|     XStreamCdn() |     XStreamCdn(), | ||||||
|  |     StreamSB(), | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| fun getExtractorApiFromName(name: String): ExtractorApi { | fun getExtractorApiFromName(name: String): ExtractorApi { | ||||||
|  | @ -80,6 +79,13 @@ abstract class ExtractorApi { | ||||||
|     abstract val mainUrl: String |     abstract val mainUrl: String | ||||||
|     abstract val requiresReferer: Boolean |     abstract val requiresReferer: Boolean | ||||||
| 
 | 
 | ||||||
|  |     fun getSafeUrl(url: String, referer: String? = null): List<ExtractorLink>? { | ||||||
|  |         return normalSafeApiCall { getUrl(url, referer) } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Will throw errors, use getSafeUrl if you don't want to handle the exception yourself | ||||||
|  |      */ | ||||||
|     abstract fun getUrl(url: String, referer: String? = null): List<ExtractorLink>? |     abstract fun getUrl(url: String, referer: String? = null): List<ExtractorLink>? | ||||||
| 
 | 
 | ||||||
|     open fun getExtractorUrl(id: String): String { |     open fun getExtractorUrl(id: String): String { | ||||||
|  |  | ||||||
|  | @ -13,25 +13,21 @@ class MixDrop : ExtractorApi() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|         try { |         with(khttp.get(url)) { | ||||||
|             with(khttp.get(url)) { |             getAndUnpack(this.text)?.let { unpackedText -> | ||||||
|                 getAndUnpack(this.text)?.let { unpackedText -> |                 srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> | ||||||
|                     srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> |                     return listOf( | ||||||
|                         return listOf( |                         ExtractorLink( | ||||||
|                             ExtractorLink( |                             name, | ||||||
|                                 name, |                             name, | ||||||
|                                 name, |                             httpsify(link), | ||||||
|                                 httpsify(link), |                             url, | ||||||
|                                 url, |                             Qualities.Unknown.value, | ||||||
|                                 Qualities.Unknown.value, |  | ||||||
|                             ) |  | ||||||
|                         ) |                         ) | ||||||
|                     } |                     ) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return null |  | ||||||
|         } catch (e: Exception) { |  | ||||||
|             return null |  | ||||||
|         } |         } | ||||||
|  |         return null | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -9,25 +9,21 @@ class Mp4Upload : ExtractorApi() { | ||||||
|     override val requiresReferer = true |     override val requiresReferer = true | ||||||
| 
 | 
 | ||||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|         try { |         with(khttp.get(url)) { | ||||||
|             with(khttp.get(url)) { |             getAndUnpack(this.text)?.let { unpackedText -> | ||||||
|                 getAndUnpack(this.text)?.let { unpackedText -> |                 srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> | ||||||
|                     srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> |                     return listOf( | ||||||
|                         return listOf( |                         ExtractorLink( | ||||||
|                             ExtractorLink( |                             name, | ||||||
|                                 name, |                             name, | ||||||
|                                 name, |                             link, | ||||||
|                                 link, |                             url, | ||||||
|                                 url, |                             Qualities.Unknown.value, | ||||||
|                                 Qualities.Unknown.value, |  | ||||||
|                             ) |  | ||||||
|                         ) |                         ) | ||||||
|                     } |                     ) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return null |  | ||||||
|         } catch (e: Exception) { |  | ||||||
|             return null |  | ||||||
|         } |         } | ||||||
|  |         return null | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -27,44 +27,40 @@ class MultiQuality : ExtractorApi() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|         try { |         val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||||
|             val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() |         with(khttp.get(url)) { | ||||||
|             with(khttp.get(url)) { |             sourceRegex.findAll(this.text).forEach { sourceMatch -> | ||||||
|                 sourceRegex.findAll(this.text).forEach { sourceMatch -> |                 val extractedUrl = sourceMatch.groupValues[1] | ||||||
|                     val extractedUrl = sourceMatch.groupValues[1] |                 // Trusting this isn't mp4, may fuck up stuff | ||||||
|                     // Trusting this isn't mp4, may fuck up stuff |                 if (extractedUrl.endsWith(".m3u8")) { | ||||||
|                     if (extractedUrl.endsWith(".m3u8")) { |                     with(khttp.get(extractedUrl)) { | ||||||
|                         with(khttp.get(extractedUrl)) { |                         m3u8Regex.findAll(this.text).forEach { match -> | ||||||
|                             m3u8Regex.findAll(this.text).forEach { match -> |                             extractedLinksList.add( | ||||||
|                                 extractedLinksList.add( |                                 ExtractorLink( | ||||||
|                                     ExtractorLink( |                                     name, | ||||||
|                                         name, |                                     "$name ${match.groupValues[1]}p", | ||||||
|                                         "$name ${match.groupValues[1]}p", |                                     urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[0], | ||||||
|                                         urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[0], |                                     url, | ||||||
|                                         url, |                                     getQuality(match.groupValues[1]), | ||||||
|                                         getQuality(match.groupValues[1]), |                                     isM3u8 = true | ||||||
|                                         isM3u8 = true |  | ||||||
|                                     ) |  | ||||||
|                                 ) |                                 ) | ||||||
|                             } |  | ||||||
| 
 |  | ||||||
|                         } |  | ||||||
|                     } else if (extractedUrl.endsWith(".mp4")) { |  | ||||||
|                         extractedLinksList.add( |  | ||||||
|                             ExtractorLink( |  | ||||||
|                                 name, |  | ||||||
|                                 "$name ${sourceMatch.groupValues[2]}", |  | ||||||
|                                 extractedUrl, |  | ||||||
|                                 url.replace(" ", "%20"), |  | ||||||
|                                 Qualities.Unknown.value, |  | ||||||
|                             ) |                             ) | ||||||
|                         ) |                         } | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 return extractedLinksList |  | ||||||
|             } |  | ||||||
|         } catch (e: Exception) { |  | ||||||
| 
 | 
 | ||||||
|  |                     } | ||||||
|  |                 } else if (extractedUrl.endsWith(".mp4")) { | ||||||
|  |                     extractedLinksList.add( | ||||||
|  |                         ExtractorLink( | ||||||
|  |                             name, | ||||||
|  |                             "$name ${sourceMatch.groupValues[2]}", | ||||||
|  |                             extractedUrl, | ||||||
|  |                             url.replace(" ", "%20"), | ||||||
|  |                             Qualities.Unknown.value, | ||||||
|  |                         ) | ||||||
|  |                     ) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return extractedLinksList | ||||||
|         } |         } | ||||||
|         return null |         return null | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,51 @@ | ||||||
|  | package com.lagradost.cloudstream3.utils.extractors | ||||||
|  | 
 | ||||||
|  | import com.lagradost.cloudstream3.utils.ExtractorApi | ||||||
|  | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.getAndUnpack | ||||||
|  | import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
|  | 
 | ||||||
|  | class StreamSB : ExtractorApi() { | ||||||
|  |     override val name: String = "StreamSB" | ||||||
|  |     override val mainUrl: String = "https://sbplay.org" | ||||||
|  |     private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*"(.*?)"""") | ||||||
|  | 
 | ||||||
|  |     //private val m3u8Regex = Regex(""".*?(\d*).m3u8""") | ||||||
|  |     //private val urlRegex = Regex("""(.*?)([^/]+$)""") | ||||||
|  | 
 | ||||||
|  |     // 1: Resolution 2: url | ||||||
|  |     private val m3u8UrlRegex = Regex("""RESOLUTION=\d*x(\d*).*\n(http.*.m3u8)""") | ||||||
|  |     override val requiresReferer = false | ||||||
|  | 
 | ||||||
|  |     // 	https://sbembed.com/embed-ns50b0cukf9j.html   ->   https://sbvideo.net/play/ns50b0cukf9j | ||||||
|  |     override fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||||
|  |         val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||||
|  |         val newUrl = url.replace("sbplay.org/embed-", "sbplay.org/play/").removeSuffix(".html") | ||||||
|  |         with(khttp.get(newUrl, timeout = 10.0)) { | ||||||
|  |             getAndUnpack(this.text)?.let { | ||||||
|  |                 sourceRegex.findAll(it).forEach { sourceMatch -> | ||||||
|  |                     val extractedUrl = sourceMatch.groupValues[1] | ||||||
|  |                     if (extractedUrl.contains(".m3u8")) { | ||||||
|  |                         with(khttp.get(extractedUrl)) { | ||||||
|  |                             m3u8UrlRegex.findAll(this.text).forEach { match -> | ||||||
|  |                                 val extractedUrlM3u8 = match.groupValues[2] | ||||||
|  |                                 val extractedRes = match.groupValues[1] | ||||||
|  |                                 extractedLinksList.add( | ||||||
|  |                                     ExtractorLink( | ||||||
|  |                                         name, | ||||||
|  |                                         "$name ${extractedRes}p", | ||||||
|  |                                         extractedUrlM3u8, | ||||||
|  |                                         extractedUrl, | ||||||
|  |                                         getQualityFromName(extractedRes), | ||||||
|  |                                         true | ||||||
|  |                                     ) | ||||||
|  |                                 ) | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return extractedLinksList | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -14,22 +14,19 @@ class StreamTape : ExtractorApi() { | ||||||
|         Regex("""(i(|" \+ ')d(|" \+ ')=.*?&(|" \+ ')e(|" \+ ')x(|" \+ ')p(|" \+ ')i(|" \+ ')r(|" \+ ')e(|" \+ ')s(|" \+ ')=.*?&(|" \+ ')i(|" \+ ')p(|" \+ ')=.*?&(|" \+ ')t(|" \+ ')o(|" \+ ')k(|" \+ ')e(|" \+ ')n(|" \+ ')=.*)'""") |         Regex("""(i(|" \+ ')d(|" \+ ')=.*?&(|" \+ ')e(|" \+ ')x(|" \+ ')p(|" \+ ')i(|" \+ ')r(|" \+ ')e(|" \+ ')s(|" \+ ')=.*?&(|" \+ ')i(|" \+ ')p(|" \+ ')=.*?&(|" \+ ')t(|" \+ ')o(|" \+ ')k(|" \+ ')e(|" \+ ')n(|" \+ ')=.*)'""") | ||||||
| 
 | 
 | ||||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|         try { |         with(khttp.get(url)) { | ||||||
|             with(khttp.get(url)) { |             linkRegex.find(this.text)?.let { | ||||||
|                 linkRegex.find(this.text)?.let { |                 val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "") | ||||||
|                     val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "") |                 return listOf( | ||||||
|                     return listOf( |                     ExtractorLink( | ||||||
|                         ExtractorLink( |                         name, | ||||||
|                             name, |                         name, | ||||||
|                             name, |                         extractedUrl, | ||||||
|                             extractedUrl, |                         url, | ||||||
|                             url, |                         Qualities.Unknown.value, | ||||||
|                             Qualities.Unknown.value, |  | ||||||
|                         ) |  | ||||||
|                     ) |                     ) | ||||||
|                 } |                 ) | ||||||
|             } |             } | ||||||
|         } catch (e: Exception) { |  | ||||||
|         } |         } | ||||||
|         return null |         return null | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ class Vidstream { | ||||||
|         try { |         try { | ||||||
|             normalApis.pmap { api -> |             normalApis.pmap { api -> | ||||||
|                 val url = api.getExtractorUrl(id) |                 val url = api.getExtractorUrl(id) | ||||||
|                 val source = api.getUrl(url) |                 val source = api.getSafeUrl(url) | ||||||
|                 source?.forEach { callback.invoke(it) } |                 source?.forEach { callback.invoke(it) } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -38,7 +38,7 @@ class Vidstream { | ||||||
|                     // Matches vidstream links with extractors |                     // Matches vidstream links with extractors | ||||||
|                     extractorApis.filter { !it.requiresReferer || !isCasting }.pmap { api -> |                     extractorApis.filter { !it.requiresReferer || !isCasting }.pmap { api -> | ||||||
|                         if (link.startsWith(api.mainUrl)) { |                         if (link.startsWith(api.mainUrl)) { | ||||||
|                             val extractedLinks = api.getUrl(link, url) |                             val extractedLinks = api.getSafeUrl(link, url) | ||||||
|                             if (extractedLinks?.isNotEmpty() == true) { |                             if (extractedLinks?.isNotEmpty() == true) { | ||||||
|                                 extractedLinks.forEach { |                                 extractedLinks.forEach { | ||||||
|                                     callback.invoke(it) |                                     callback.invoke(it) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,58 @@ | ||||||
|  | package com.lagradost.cloudstream3.utils.extractors | ||||||
|  | 
 | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
|  | import com.fasterxml.jackson.module.kotlin.readValue | ||||||
|  | import com.lagradost.cloudstream3.utils.* | ||||||
|  | import com.lagradost.cloudstream3.mapper | ||||||
|  | 
 | ||||||
|  | class WcoStream : ExtractorApi() { | ||||||
|  |     override val name: String = "WcoStream" | ||||||
|  |     override val mainUrl: String = "https://vidstream.pro" | ||||||
|  |     override val requiresReferer = false | ||||||
|  | 
 | ||||||
|  |     override fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||||
|  |         val baseUrl = url.split("/e/")[0] | ||||||
|  | 
 | ||||||
|  |         val html = khttp.get(url, headers = mapOf("Referer" to "https://wcostream.cc/")).text | ||||||
|  |         val (Id) = "/e/(.*?)?domain".toRegex().find(url)!!.destructured | ||||||
|  |         val (skey) = """skey\s=\s['\"](.*?)['\"];""".toRegex().find(html)!!.destructured | ||||||
|  | 
 | ||||||
|  |         val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey" | ||||||
|  |         val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" | ||||||
|  | 
 | ||||||
|  |         val response = khttp.get(apiLink, headers = mapOf("Referer" to referrer)).text | ||||||
|  | 
 | ||||||
|  |         data class Sources( | ||||||
|  |             @JsonProperty("file") val file: String, | ||||||
|  |             @JsonProperty("label") val label: String? | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         data class Media( | ||||||
|  |             @JsonProperty("sources") val sources: List<Sources> | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         data class WcoResponse( | ||||||
|  |             @JsonProperty("success") val success: Boolean, | ||||||
|  |             @JsonProperty("media") val media: Media | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         val mapped = response.let { mapper.readValue<WcoResponse>(it) } | ||||||
|  |         val sources = mutableListOf<ExtractorLink>() | ||||||
|  | 
 | ||||||
|  |         if (mapped.success) { | ||||||
|  |             mapped.media.sources.forEach { | ||||||
|  |                 sources.add( | ||||||
|  |                     ExtractorLink( | ||||||
|  |                         name, | ||||||
|  |                         name + if (it.label != null) "- ${it.label}" else "", | ||||||
|  |                         it.file, | ||||||
|  |                         "", | ||||||
|  |                         Qualities.HD.value, | ||||||
|  |                         it.file.contains(".m3u8") | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return sources | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -38,34 +38,29 @@ class XStreamCdn : ExtractorApi() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|         try { |         val headers = mapOf( | ||||||
|             val headers = mapOf( |             "Referer" to url, | ||||||
|                 "Referer" to url, |             "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0", | ||||||
|                 "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0", |         ) | ||||||
|             ) |         val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/") | ||||||
|             val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/") |         val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||||
|             val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() |         with(khttp.post(newUrl, headers = headers)) { | ||||||
|             with(khttp.post(newUrl, headers = headers)) { |             mapper.readValue<ResponseJson?>(this.text)?.let { | ||||||
|                 mapper.readValue<ResponseJson?>(this.text)?.let { |                 if (it.success && it.data != null) { | ||||||
|                     if (it.success && it.data != null) { |                     it.data.forEach { data -> | ||||||
|                         it.data.forEach { data -> |                         extractedLinksList.add( | ||||||
|                             extractedLinksList.add( |                             ExtractorLink( | ||||||
|                                 ExtractorLink( |                                 name, | ||||||
|                                     name, |                                 "$name ${data.label}", | ||||||
|                                     "$name ${data.label}", |                                 data.file, | ||||||
|                                     data.file, |                                 url, | ||||||
|                                     url, |                                 getQuality(data.label), | ||||||
|                                     getQuality(data.label), |  | ||||||
|                                 ) |  | ||||||
|                             ) |                             ) | ||||||
|                         } |                         ) | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return extractedLinksList |  | ||||||
|         } catch (e: Exception) { |  | ||||||
|         } |         } | ||||||
|         return null |         return extractedLinksList | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| } | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue