├── .gitignore ├── .idea ├── .gitignore ├── .name ├── appInsightsSettings.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── deploymentTargetDropDown.xml ├── deploymentTargetSelector.xml ├── gradle.xml ├── kotlinc.xml ├── migrations.xml ├── misc.xml └── vcs.xml ├── NETWORK.http ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── azamovhudstc │ │ └── scarpingtutorial │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── azamovhudstc │ │ │ └── scarpingtutorial │ │ │ ├── AnimeParseddata.kt │ │ │ ├── MainActivity.kt │ │ │ ├── ParsedData.kt │ │ │ ├── anibla │ │ │ ├── AmediaSearchData.kt │ │ │ ├── Category.kt │ │ │ ├── Data.kt │ │ │ ├── Main.kt │ │ │ ├── Name.kt │ │ │ └── detail │ │ │ │ ├── Category.kt │ │ │ │ ├── Data.kt │ │ │ │ ├── Description.kt │ │ │ │ ├── DetailData.kt │ │ │ │ ├── Janr.kt │ │ │ │ ├── Name.kt │ │ │ │ ├── Screens.kt │ │ │ │ ├── Seria.kt │ │ │ │ ├── Tarjimon.kt │ │ │ │ └── Translator.kt │ │ │ ├── aniwave │ │ │ ├── AnimeDetails.kt │ │ │ ├── AnimePlayingDetails.kt │ │ │ ├── Main.kt │ │ │ └── SimpleAnime.kt │ │ │ ├── aniworld │ │ │ ├── AniworldSearchData.kt │ │ │ ├── AniworldSearchDataItem.kt │ │ │ ├── EpisodeData.kt │ │ │ ├── EpisodeFullData.kt │ │ │ └── Main.kt │ │ │ ├── asilmedia │ │ │ ├── Main.kt │ │ │ └── model │ │ │ │ ├── FullMovieData.kt │ │ │ │ ├── MainData.kt │ │ │ │ └── MovieInfo.kt │ │ │ ├── findingJson │ │ │ └── main.kt │ │ │ ├── idub │ │ │ ├── Main.kt │ │ │ ├── TVShow.kt │ │ │ └── VideoInfo.kt │ │ │ ├── imdb.kt │ │ │ └── Imdb.kt │ │ │ ├── itv │ │ │ ├── ChannelResponse.kt │ │ │ ├── Data.kt │ │ │ ├── DataX.kt │ │ │ ├── Files.kt │ │ │ ├── FilesX.kt │ │ │ ├── Main.kt │ │ │ ├── Meta.kt │ │ │ ├── Params.kt │ │ │ ├── ParamsX.kt │ │ │ ├── PaymentParams.kt │ │ │ ├── PaymentParamsX.kt │ │ │ └── TvResponse.kt │ │ │ ├── ktor_http │ │ │ └── Main.kt │ │ │ ├── main │ │ │ └── Main.kt │ │ │ ├── med_home │ │ │ └── MedHome.kt │ │ │ ├── moviefone │ │ │ └── MovieFone.kt │ │ │ ├── shared │ │ │ ├── SharedPreference.kt │ │ │ └── gsonConverters.kt │ │ │ ├── socket │ │ │ └── Main.kt │ │ │ ├── theflixer │ │ │ ├── Episode.kt │ │ │ ├── EpisodeData.kt │ │ │ ├── Film.kt │ │ │ ├── Functions.kt │ │ │ ├── Main.kt │ │ │ ├── RatingInfo.kt │ │ │ └── TVShow.kt │ │ │ ├── themoviedb │ │ │ └── TheMovieDB.kt │ │ │ ├── tv_online │ │ │ ├── Main.kt │ │ │ └── parsed │ │ │ │ └── Movie.kt │ │ │ ├── utils │ │ │ ├── SharedPreference.kt │ │ │ ├── Utils.kt │ │ │ ├── banner.kt │ │ │ ├── displayLoadingAnimation.kt │ │ │ ├── parser.kt │ │ │ └── removeEmTagsWithRegex.kt │ │ │ └── uzmovi │ │ │ ├── CustomXMLHttpRequest.kt │ │ │ ├── JsHunter.kt │ │ │ ├── JsUnpacker.kt │ │ │ ├── Main.kt │ │ │ └── movie │ │ │ └── ParsedMovie.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── azamovhudstc │ └── scarpingtutorial │ └── ExampleUnitTest.kt ├── build.gradle ├── cacheDir └── http_cache │ ├── 2b1224a03a7535f0c5970fad62e68a04.0 │ ├── 2b1224a03a7535f0c5970fad62e68a04.1 │ ├── 5e4087c3189675fda2f4a1d7f58e56dd.0 │ ├── 5e4087c3189675fda2f4a1d7f58e56dd.1 │ ├── 9cb50cb1271552bead409a9b12e28ccc.0 │ ├── 9cb50cb1271552bead409a9b12e28ccc.1 │ ├── eb3f92a87779a0e3bb56097846dd3a13.0 │ ├── eb3f92a87779a0e3bb56097846dd3a13.1 │ └── journal ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── tonconsole ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── azamovhudstc │ └── tonconsole │ └── ExampleInstrumentedTest.kt ├── main ├── AndroidManifest.xml └── java │ └── com │ └── azamovhudstc │ └── tonconsole │ └── Main.kt └── test └── java └── com └── azamovhudstc └── tonconsole └── ExampleUnitTest.kt /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | ScarpingTutorial -------------------------------------------------------------------------------- /.idea/appInsightsSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 25 | 26 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/deploymentTargetSelector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /NETWORK.http: -------------------------------------------------------------------------------- 1 | GET 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Setup 2 | 3 | In build.gradle repositories: 4 | 5 | ```groovy 6 | maven { url 'https://jitpack.io' } 7 | ``` 8 | 9 | In app/build.gradle dependencies: 10 | 11 | 12 | ```groovy 13 | implementation 'com.github.Blatzar:NiceHttp:0.4.4' 14 | ``` 15 | 16 | ## Video tutorial 17 | https://t.me/azamovme/124 18 | 19 | ### Scraping a document with Nice Http 20 | 21 | ```kotlin 22 | suspend fun main() { 23 | val scannerForNext = Scanner(System.`in`) 24 | coroutineScope { 25 | val uzmoviBase = UzmoviBase() 26 | print("Enter Movie Name :") 27 | val movieName = scanner.nextLine() 28 | displayLoadingAnimation("Searching for movies", Color.GREEN) 29 | val list = uzmoviBase.searchMovie(movieName) 30 | printlnColored(" Selected Movie: ${list[0].title}", Color.GREEN) 31 | displayLoadingAnimation("Loading Episodes", Color.GREEN) 32 | uzmoviBase.movieDetails(list[0]) // Get Movie Details Scraping by href 33 | 34 | } 35 | } 36 | 37 | ``` 38 | 39 | ## _Thanks For_ [Blatzar](https://github.com/Blatzar) 40 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | android { 7 | compileSdk 32 8 | 9 | defaultConfig { 10 | applicationId "com.azamovhudstc.scarpingtutorial" 11 | minSdk 23 12 | targetSdk 32 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | 18 | // 19 | /// 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | kotlinOptions { 33 | jvmTarget = '1.8' 34 | } 35 | } 36 | 37 | dependencies { 38 | 39 | /// 40 | implementation 'androidx.core:core-ktx:1.7.0' 41 | implementation 'androidx.appcompat:appcompat:1.5.1' 42 | implementation 'com.google.android.material:material:1.7.0' 43 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 44 | testImplementation 'junit:junit:4.13.2' 45 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 46 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 47 | implementation "org.jsoup:jsoup:1.15.1" 48 | implementation 'com.github.Blatzar:NiceHttp:0.4.4'// So wee Need this Libraries 49 | api "com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1" 50 | implementation 'com.google.code.gson:gson:2.10.1' 51 | implementation 'com.squareup.okhttp3:okhttp:3.5.0' 52 | implementation 'org.java-websocket:Java-WebSocket:1.4.0' 53 | 54 | implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1" 55 | implementation 'io.apisense:rhino-android:1.0' 56 | 57 | //and we need FireFox browser because this browser run away debug mode 58 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/azamovhudstc/scarpingtutorial/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.azamovhudstc.scarpingtutorial", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/AnimeParseddata.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial 2 | 3 | data class AnimeParseData( 4 | val title: String, 5 | val href: String, 6 | val image: String 7 | ) { 8 | override fun toString(): String { 9 | return "Title=$title\nHref=$href,\nImage=$image" 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial 2 | 3 | import android.os.Bundle 4 | import com.azamovhudstc.scarpingtutorial.shared.LocalStorage 5 | import com.azamovhudstc.scarpingtutorial.shared.parseJson 6 | import com.azamovhudstc.scarpingtutorial.shared.saveGson 7 | import com.azamovhudstc.scarpingtutorial.utils.Utils 8 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 9 | import com.azamovhudstc.scarpingtutorial.utils.Utils.postJson 10 | import kotlinx.coroutines.async 11 | import kotlinx.coroutines.coroutineScope 12 | import kotlinx.coroutines.runBlocking 13 | 14 | 15 | 16 | private val mainUrl = "https://yugenanime.tv" //GET MAIN URL 17 | private lateinit var epList: MutableList 18 | suspend fun main() { 19 | coroutineScope { 20 | val parseData = searchAnime("One Piece").get(0) 21 | val animeEpisodesMap = returnEpMap(parseData) 22 | val epType = "SUB" 23 | epList = animeEpisodesMap[epType]!!.keys.toMutableList() 24 | val animeUrl = parseData.href 25 | val epIndex = epList[0]!!.toString() 26 | val animeEpisodeMap2 = animeEpisodesMap["SUB"]!! 27 | val animeTotalEpisode = animeEpisodesMap[epType]!!.size.toString() 28 | 29 | streamLink(animeUrl, epIndex.toString(), listOf("SUB")) 30 | 31 | } 32 | } 33 | 34 | suspend fun streamLink( 35 | animeUrl: String, 36 | animeEpCode: String, 37 | extras: List? 38 | ) { 39 | val watchLink = animeUrl.replace("anime", "watch") 40 | val animeEpUrl = "$mainUrl$watchLink$animeEpCode" 41 | var yugenEmbedLink = getJsoup(animeEpUrl).getElementById("main-embed")!!.attr("src") 42 | if (!yugenEmbedLink.contains("https:")) yugenEmbedLink = "https:$yugenEmbedLink" 43 | println(yugenEmbedLink) 44 | val mapOfHeaders = mutableMapOf( 45 | "X-Requested-With" to "XMLHttpRequest", 46 | "content-type" to "application/x-www-form-urlencoded; charset=UTF-8" 47 | ) 48 | val apiRequest = "$mainUrl/api/embed/" 49 | val id = yugenEmbedLink.split("/") 50 | val dataMap = mapOf("id" to id[id.size - 2], "ac" to "0") 51 | println(dataMap) 52 | val linkDetails = postJson(apiRequest, mapOfHeaders, dataMap)!!.asJsonObject 53 | val link = linkDetails["hls"].asJsonArray.first().asString 54 | 55 | println(link) 56 | } 57 | 58 | suspend fun returnEpMap(parseData: AnimeParseData): Map> { 59 | val url = "$mainUrl${parseData.href}watch/?sort=episode" //GET ANIME DETAIL URL 60 | val doc = getJsoup(url) //REQUEST ANIME DETAIL 61 | println(doc.getElementsByClass("p-10-t").first()!!.text()) // get anime name 62 | val subsEpCount = doc.getElementsByClass("box p-10 p-15 m-15-b anime-metadetails") 63 | .select("div:nth-child(6)").select("span").text() /// get episode count 64 | val epMapSub = 65 | (1..subsEpCount.toInt()).associate { it.toString() to it.toString() } /// generate map from 1 to epCount 66 | 67 | println(epMapSub) 68 | 69 | val epMap = mutableMapOf("SUB" to epMapSub) 70 | 71 | return epMap 72 | } 73 | 74 | 75 | suspend fun searchAnime(query: String): ArrayList { 76 | val animeList = arrayListOf() 77 | val url = "$mainUrl/discover/?q=$query" //GET SEARCH URL 78 | val doc = getJsoup(url) //REQUEST SEARCH 79 | val animeContent = doc.getElementsByClass("anime-meta") //GET ANIME LIST 80 | for (item in animeContent) { 81 | val animeName = item.getElementsByClass("anime-name").text() //GET ANIME NAME 82 | val animeCover = item.getElementsByTag("img").attr("data-src") // GET ANIME COVER 83 | val href = item.attr("href") //GET DETAIL URL 84 | val animeParseData = AnimeParseData(animeName, href, animeCover) //PARSE DATA 85 | animeList.add(animeParseData) //ADD DATA 86 | } 87 | 88 | return animeList //RETURN DATA 89 | } 90 | 91 | 92 | fun List.asyncMap(f: suspend (A) -> B): List = runBlocking { 93 | map { async { f(it) } }.map { it.await() } 94 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/ParsedData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial 2 | 3 | data class ParsedData( 4 | val climate: String, 5 | val created: String, 6 | val diameter: String, 7 | val edited: String, 8 | val films: List, 9 | val gravity: String, 10 | val name: String, 11 | val orbital_period: String, 12 | val population: String, 13 | val residents: List, 14 | val rotation_period: String, 15 | val surface_water: String, 16 | val terrain: String, 17 | val url: String 18 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/AmediaSearchData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla 2 | 3 | data class AmediaSearchData( 4 | val `data`: List, 5 | val success: Boolean 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/Category.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla 2 | 3 | data class Category( 4 | val __v: Int, 5 | val _id: String, 6 | val createdAt: String, 7 | val isRestricted: Boolean, 8 | val nameru: String, 9 | val nameuz: String 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/Data.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla 2 | 3 | data class Data( 4 | val _id: String, 5 | val category: List, 6 | val image: String, 7 | val name: Name 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla 2 | 3 | import com.azamovhudstc.scarpingtutorial.anibla.detail.DetailData 4 | import com.azamovhudstc.scarpingtutorial.utils.* 5 | import com.lagradost.nicehttp.Requests 6 | import kotlinx.coroutines.runBlocking 7 | 8 | private const val hostUrl = "https://amediatv.uz/" 9 | private const val imageHostUrl = "https://cdn.amediatv.uz/" 10 | 11 | fun main(args: Array) { 12 | val amediaTvBase = AmediaTvBase() 13 | 14 | runBlocking { 15 | val data = amediaTvBase.searchByQuery("Doktor") 16 | showData(data) 17 | 18 | printlnColored("Selected Anime ${data.data.get(0).name.uz}", Color.GREEN) 19 | val detailData = amediaTvBase.getFullDataById(data.data.get(0)) 20 | println("Anime Name : ${detailData.data.name.uz}") 21 | println("Anime Created : ${detailData.data.createdAt}") 22 | println("Anime Studios : ${detailData.data.studia}") 23 | printlnColored("================= Episodes ================", Color.GREEN) 24 | 25 | detailData.seria.reversed().forEach { 26 | printColored("Episode Name : ", Color.BLUE) 27 | printColored(it.name.uz + "\n", Color.GREEN) 28 | printColored("Episode Length : ", Color.BLUE) 29 | printColored("${it.length} min\n", Color.GREEN) 30 | } 31 | 32 | printlnColored("Selected 1-Episode", Color.GREEN) 33 | 34 | val episode = detailData.seria.reversed().get(0) 35 | amediaTvBase.getM3u8File(episode.video, episode._id) 36 | } 37 | } 38 | 39 | 40 | class AmediaTvBase { 41 | 42 | private val requests = Requests(baseClient = Utils.httpClient, responseParser = parser) 43 | 44 | suspend fun getFullDataById(data: Data): DetailData { 45 | displayLoadingAnimation("Paring Detail...", Color.GREEN) 46 | val responseData = 47 | requests.get("https://cdn.amediatv.uz/api/season/v2/${data._id}").parsed() 48 | 49 | return responseData 50 | } 51 | 52 | 53 | suspend fun getM3u8File(href: String, dataId: String) { 54 | displayLoadingAnimation("Parsing File....", Color.GREEN) 55 | val document = Utils.getJsoup(href) 56 | 57 | val fileAttributeValue = extractFileAttributeValue(document!!.html()) 58 | println("File Attribute Value: $fileAttributeValue") 59 | 60 | } 61 | 62 | private fun extractFileAttributeValue(scriptContent: String): String { 63 | val regex = """file\s*:\s*['"]([^'"]+)['"]""".toRegex() 64 | val matchResult = regex.find(scriptContent) 65 | return matchResult?.groupValues?.get(1)!! 66 | } 67 | 68 | suspend fun searchByQuery(query: String): AmediaSearchData { 69 | displayLoadingAnimation("Searching Anime", Color.GREEN) 70 | 71 | val data = requests.get("https://cdn.amediatv.uz/api/season/search?text=$query") 72 | .parsed() 73 | 74 | return data 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/Name.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla 2 | 3 | data class Name( 4 | val ru: String, 5 | val uz: String 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Category.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Category( 4 | val __v: Int, 5 | val _id: String, 6 | val createdAt: String, 7 | val isRestricted: Boolean, 8 | val nameru: String, 9 | val nameuz: String 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Data.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Data( 4 | val __v: Int, 5 | val _id: String, 6 | val category: List, 7 | val country: String, 8 | val createdAt: String, 9 | val date: String, 10 | val description: Description, 11 | val image: String, 12 | val janr: List, 13 | val length: String, 14 | val name: Name, 15 | val num: String, 16 | val price: String, 17 | val rating: Int, 18 | val rejissor: String, 19 | val screens: Screens, 20 | val slug: String, 21 | val status: Boolean, 22 | val studia: String, 23 | val tags: List, 24 | val tarjimon: List, 25 | val tayming: List, 26 | val tip: String, 27 | val translator: List, 28 | val type: Int, 29 | val updatedAt: String, 30 | val url: String, 31 | val video: String, 32 | val view: Int, 33 | val year: String 34 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Description.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Description( 4 | val ru: String, 5 | val uz: String 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/DetailData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class DetailData( 4 | val comment: List, 5 | val `data`: Data, 6 | val seria: List, 7 | val status: Int, 8 | val success: Boolean 9 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Janr.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Janr( 4 | val __v: Int, 5 | val _id: String, 6 | val createdAt: String, 7 | val nameru: String, 8 | val nameuz: String, 9 | val status: Boolean 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Name.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Name( 4 | val ru: String, 5 | val uz: String 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Screens.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Screens( 4 | val original: List, 5 | val thumb: List 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Seria.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Seria( 4 | val __v: Int, 5 | val _id: String, 6 | val createdAt: String, 7 | val date: String, 8 | val length: String, 9 | val name: Name, 10 | val season: String, 11 | val slug: String, 12 | val updatedAt: String, 13 | val url: String, 14 | val video: String 15 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Tarjimon.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Tarjimon( 4 | val __v: Int, 5 | val _id: String, 6 | val createdAt: String, 7 | val image: String, 8 | val name: String, 9 | val status: Boolean 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/anibla/detail/Translator.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.anibla.detail 2 | 3 | data class Translator( 4 | val __v: Int, 5 | val _id: String, 6 | val createdAt: String, 7 | val image: String, 8 | val name: String, 9 | val status: Boolean 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniwave/AnimeDetails.kt: -------------------------------------------------------------------------------- 1 | package com.talent.animescrap_common.model 2 | 3 | data class AnimeDetails( 4 | val animeName: String, 5 | val animeDesc: String, 6 | val animeCover: String, 7 | val animeEpisodes: Map> 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniwave/AnimePlayingDetails.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniwave 2 | 3 | import android.os.Parcelable 4 | import androidx.annotation.Keep 5 | 6 | @Keep 7 | data class AnimePlayingDetails( 8 | val animeName: String, 9 | val animeUrl: String, 10 | var animeEpisodeIndex: String, 11 | val animeEpisodeMap: HashMap, 12 | val animeTotalEpisode: String, 13 | val epType: String 14 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniwave/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniwave 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJson 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 5 | import com.talent.animescrap_common.model.AnimeDetails 6 | import org.jsoup.Jsoup 7 | 8 | private val mainUrl = "https://aniwave.to" 9 | //private val url = "https://vidplay.site/" 10 | private val apiUrl = "https://9anime.eltik.net/" 11 | 12 | suspend fun main(args: Array) { 13 | val simpleAnime = searchAnime("One Piece").get(0) 14 | println(simpleAnime.animeName) 15 | println(simpleAnime.animeLink) 16 | println(animeDetails(simpleAnime.animeLink).animeCover) 17 | 18 | animeDetails(simpleAnime.animeLink).animeEpisodes["Sub"]!!.toList().onEach { 19 | println(it.first) 20 | println(it.second) 21 | } 22 | } 23 | 24 | suspend fun searchAnime(query: String): ArrayList { 25 | val animeList = getAnimeList("$mainUrl/filter?keyword=$query") 26 | 27 | return animeList 28 | 29 | } 30 | 31 | suspend fun animeDetails(contentLink: String): AnimeDetails { 32 | val doc = getJsoup("$mainUrl$contentLink") 33 | val cover = doc.select("#w-info").first()!!.getElementsByTag("img").attr("src") 34 | val desc = doc.select("#w-info .info .content").text() 35 | val title = doc.select("#w-info .info .title").attr("data-jp") 36 | 37 | val dataId = doc.getElementsByAttribute("data-id").first()!!.attr("data-id") 38 | println(dataId) 39 | val vrf = getVrf(dataId) 40 | val eps = 41 | Jsoup.parseBodyFragment(getJson("$mainUrl/ajax/episode/list/$dataId?vrf=$vrf")!!.asJsonObject["result"].asString) 42 | .select("li a") 43 | val subMap = mutableMapOf() 44 | val dubMap = mutableMapOf() 45 | eps.forEach { 46 | val epNum = it.attr("data-num") 47 | val epIds = it.attr("data-ids") 48 | val isSub = it.attr("data-sub").toInt() == 1 49 | val isDub = it.attr("data-dub").toInt() == 1 50 | if (isSub) subMap[epNum] = epIds 51 | if (isDub) dubMap[epNum] = epIds 52 | } 53 | 54 | return AnimeDetails(title, desc, cover, mapOf("Sub" to subMap, "Dub" to dubMap)) 55 | } 56 | 57 | private fun getVrf(dataId: String): String { 58 | val json = getJson("$apiUrl/vrf?query=${dataId}&apikey=chayce") 59 | return json!!.asJsonObject["url"].asString 60 | } 61 | 62 | private fun decodeVrf(dataId: String): String { 63 | val json = getJson("$apiUrl/decrypt?query=${dataId}&apikey=chayce") 64 | return json!!.asJsonObject["url"].asString 65 | } 66 | 67 | 68 | private fun getAnimeList(url: String): ArrayList { 69 | val animeList = arrayListOf() 70 | val doc = getJsoup(url) 71 | doc.select("#list-items .item").forEach { item -> 72 | animeList.add( 73 | SimpleAnime( 74 | item.select(".info a").attr("data-jp"), 75 | item.getElementsByTag("img").attr("src"), 76 | item.getElementsByTag("a").attr("href") 77 | ) 78 | ) 79 | } 80 | return animeList 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniwave/SimpleAnime.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniwave 2 | 3 | data class SimpleAnime( 4 | val animeName: String, 5 | val animeImageURL: String, 6 | val animeLink: String 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniworld/AniworldSearchData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniworld 2 | 3 | class AniworldSearchData : ArrayList() -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniworld/AniworldSearchDataItem.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniworld 2 | 3 | data class AniworldSearchDataItem( 4 | val description: String, 5 | val link: String, 6 | val title: String 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniworld/EpisodeData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniworld 2 | 3 | data class EpisodeData(private val number: String, val link: String) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniworld/EpisodeFullData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniworld 2 | 3 | data class EpisodeFullData( val hostName: String, val hostUrl: String, val host: String) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/aniworld/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.aniworld 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils.httpClient 5 | import com.azamovhudstc.scarpingtutorial.utils.parser 6 | import com.lagradost.nicehttp.Requests 7 | import okhttp3.MultipartBody 8 | import okhttp3.RequestBody 9 | 10 | 11 | private const val mainUrl = "https://aniworld.to" 12 | 13 | suspend fun main(args: Array) { 14 | val data = searchAnimeInAniWord("One Piece") 15 | val epData = animeDetails(data.get(0)).get(0) 16 | val epFullData = setLink(epData.link) 17 | println("$mainUrl${epFullData.hostUrl}") 18 | val redirectLink = getAnimeRedirectLink(epFullData.hostUrl) 19 | println(redirectLink) 20 | 21 | } 22 | 23 | suspend fun getAnimeRedirectLink(redirectLink: String): String { 24 | val document = getJsoup("$mainUrl/$redirectLink") 25 | val scriptTags = document.select("script") 26 | 27 | for (scriptTag in scriptTags) { 28 | val scriptCode = scriptTag.html() 29 | if (scriptCode.contains("var sources")) { 30 | val hlsUrl = extractValue(scriptCode, "'hls': '(.*?)'") 31 | return hlsUrl 32 | } 33 | } 34 | return "" 35 | } 36 | 37 | fun extractValue(input: String, regex: String): String { 38 | val matchResult = Regex(regex).find(input) 39 | return matchResult?.groupValues?.get(1) ?: "" 40 | } 41 | 42 | 43 | suspend fun animeDetails(parsedData: AniworldSearchDataItem): ArrayList { 44 | val epList = arrayListOf() 45 | val doc = getJsoup("$mainUrl/${parsedData.link}") 46 | val animeList = doc.getElementsByClass("hosterSiteDirectNav") 47 | val episodeElements = animeList.select("ul:has(li a[data-episode-id]) li a[data-episode-id]") 48 | for (episodeElement in episodeElements) { 49 | val number = episodeElement.text() 50 | val url = episodeElement.attr("href") 51 | epList.add(EpisodeData(number, url)) 52 | println(url) 53 | } 54 | return epList 55 | } 56 | 57 | 58 | suspend fun setLink(url: String): EpisodeFullData { 59 | var episodeFullData = EpisodeFullData("", "", "") 60 | val document = getJsoup("$mainUrl/$url") 61 | val firstDataLinkId = document.select("li[data-link-id]").firstOrNull()?.attr("data-link-id") 62 | val hosterElements = document.getElementsByClass("watchEpisode") 63 | for (element in hosterElements) { 64 | val hoster = element.select("i").attr("title") 65 | val hosterName = element.select("h4").text() 66 | if (hosterName == "VOE") { 67 | episodeFullData = 68 | EpisodeFullData(hosterName, "/redirect/${firstDataLinkId.toString()}", hoster) 69 | } 70 | } 71 | 72 | return episodeFullData 73 | } 74 | 75 | suspend fun searchAnimeInAniWord(keyWord: String): AniworldSearchData { 76 | val request = Requests(baseClient = httpClient) 77 | val requestBody: RequestBody = MultipartBody.Builder() 78 | .setType(MultipartBody.FORM) 79 | .addFormDataPart( 80 | "keyword", 81 | keyWord, 82 | ) 83 | .build() 84 | 85 | val data = request.post( 86 | "https://aniworld.to/ajax/search", 87 | requestBody = requestBody, 88 | responseParser = parser 89 | ) 90 | val parsedData = data.parsed() 91 | return parsedData 92 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/asilmedia/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.asilmedia 2 | 3 | import com.azamovhudstc.scarpingtutorial.asilmedia.model.Media 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils 5 | import org.jsoup.select.Elements 6 | 7 | private const val mainUrl = "http://asilmedia.org" 8 | 9 | 10 | class AsilMediaBase { 11 | 12 | fun main(args: Array) { 13 | val homeList = getMovieList() 14 | 15 | val data = homeList.get(homeList.lastIndex - 1) 16 | getMovieDetails(data.url) 17 | } 18 | 19 | fun getMovieList(): ArrayList { 20 | val list = arrayListOf() 21 | val doc = Utils.getJsoup("$mainUrl/films/tarjima_kinolar/") 22 | val elements = doc.getElementById("dle-content") 23 | 24 | val articleElements = elements!!.select("article") 25 | for (document in articleElements) { 26 | val titleElement = document.select("h2.is-6.txt-ellipsis.mb-2").first() 27 | val linkElement: Elements = document.select("a.flx.flx-column.flx-column-reverse") 28 | val titleText = titleElement?.text() 29 | val linkHref: String? = linkElement.attr("href") 30 | val imageLink = document.select("div.poster picture.poster-img img").attr("data-src") 31 | list.add(Media(titleText!!, linkHref!!, imageLink)) 32 | println("---------------------------------------") 33 | println("Title -> $titleText") 34 | println("Link -> $linkHref") 35 | println("Image Link -> $mainUrl$imageLink") 36 | println("---------------------------------------") 37 | } 38 | return list 39 | } 40 | 41 | fun getMovieDetails(href: String) { 42 | val document = Utils.getJsoup(href) 43 | val downloadList: Elements = document.select("#download1 .downlist-inner a[href]") 44 | 45 | // Iterate through download links and print the URLs 46 | downloadList.forEachIndexed { index, element -> 47 | val fileUrl = element.attr("href") 48 | val parsedUrl = parseUrl(fileUrl) 49 | println("Download URL $index: $parsedUrl") 50 | } 51 | 52 | 53 | // Extract the video URL from the iframe inside the "cn-content" div 54 | val videoDiv = document.selectFirst("#cn-content") 55 | val iframeElement = videoDiv?.selectFirst("iframe") 56 | val videoUrl = iframeElement?.attr("src") 57 | val parsedUrl = parseUrl(videoUrl!!) 58 | 59 | // Print the extracted video URL 60 | println("Video URL: $parsedUrl") 61 | } 62 | 63 | fun parseUrl(url: String): String? { 64 | // Split the URL using "?" as the delimiter 65 | val parts = url.split("?") 66 | 67 | // Check if there are two parts (base URL and parameters) 68 | if (parts.size == 2) { 69 | // Split the parameters using "&" as the delimiter 70 | val parameters = parts[1].split("&") 71 | 72 | // Find the parameter with "file=" prefix 73 | val fileParameter = parameters.find { it.startsWith("file=") } 74 | 75 | // Extract the value after "file=" prefix 76 | return fileParameter?.substringAfter("file=") 77 | } 78 | 79 | return null 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/asilmedia/model/FullMovieData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.asilmedia.model 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils 4 | 5 | data class FullMovieData( 6 | val year: String, 7 | val country: String, 8 | val duration: String, 9 | val posterImageSrc: String, 10 | val genres: List>, 11 | val directors: List>, 12 | val actors: List>, 13 | val options: List>, 14 | val imageUrls: List, 15 | val description: String, 16 | val videoUrl: String, 17 | val IMDB_rating:String, 18 | ) 19 | 20 | { 21 | override fun toString(): String { 22 | return """ 23 | Year: $year 24 | Country: $country 25 | Duration: $duration 26 | Poster Image Src: $posterImageSrc 27 | 28 | Genres: 29 | ${genres.joinToString("\n") { "${it.first} - ${it.second}" }} 30 | 31 | Directors: 32 | ${directors.joinToString("\n") { "${it.first} - ${it.second}" }} 33 | 34 | Actors: 35 | ${actors.joinToString("\n") { "${it.first} - ${it.second}" }} 36 | 37 | Options: 38 | ${options.joinToString("\n") { "${it.first} - ${it.second}" }} 39 | 40 | Image URLs: 41 | ${imageUrls.joinToString("\n")} 42 | 43 | Description: $description 44 | 45 | Video URL: $videoUrl 46 | 47 | IMDB_rating: $IMDB_rating 48 | """.trimIndent() 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/asilmedia/model/MainData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.asilmedia.model 2 | 3 | data class Media( 4 | val name: String, 5 | val url: String, 6 | val cover: String 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/asilmedia/model/MovieInfo.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.asilmedia.model 2 | data class MovieInfo( 3 | val genre: String, 4 | val rating: String, 5 | val title: String, 6 | val image: String, 7 | val href: String, 8 | val quality: List, 9 | val year: String 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/findingJson/main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.findingJson 2 | 3 | import com.azamovhudstc.scarpingtutorial.ParsedData 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils 5 | import com.azamovhudstc.scarpingtutorial.utils.parser 6 | import com.lagradost.nicehttp.Requests 7 | import kotlinx.coroutines.coroutineScope 8 | 9 | suspend fun main() { 10 | coroutineScope { 11 | //So this sample Json is from https://swapi.dev/api/planets/1/ 12 | //I am using this sample Json for testing 13 | // You can use Kotlin json converter and parse it to ParsedData 14 | val requests = Requests(baseClient = Utils.httpClient, responseParser = parser) 15 | val jsonString = requests.get("https://swapi.dev/api/planets/1/").parsed() //Like this 16 | //so okay i will run 17 | println(jsonString.films) 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/idub/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.idub 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils.httpClient 5 | import com.azamovhudstc.scarpingtutorial.utils.parser 6 | import com.lagradost.nicehttp.Requests 7 | import kotlinx.coroutines.Dispatchers 8 | import kotlinx.coroutines.runBlocking 9 | import kotlinx.coroutines.withContext 10 | import org.jsoup.Jsoup 11 | 12 | private const val mainUrl = "https://idub.tv/" 13 | 14 | class IdubBase{ 15 | 16 | fun main(args: Array) { 17 | runBlocking { 18 | val list = searchKdramma("Baxt") 19 | val selectedData = list.get(0) 20 | movieDetailByHref(href = selectedData.href) 21 | 22 | } 23 | } 24 | fun movieDetailByHref(href: String) { 25 | println("Parsing Detail....") 26 | println("====================================") 27 | val episodeList = parseEpisodesByHref(href)/// 28 | println("========== Selected 1-Episode ==========") 29 | 30 | println(parseVideoTrailer(episodeList.get(0))) 31 | 32 | 33 | } 34 | 35 | fun parseEpisodesByHref(href: String): ArrayList { 36 | val document = getJsoup(href) 37 | 38 | 39 | // Extracting episode URLs 40 | val episodeUrls: List = 41 | document.select("section.buttttons div.kontaiher a.BatcoH").map { element -> 42 | element.attr("href") 43 | } 44 | 45 | // Print the list of episode URLs 46 | episodeUrls.forEach { println(it) } 47 | 48 | return episodeUrls as ArrayList 49 | } 50 | 51 | 52 | fun parseVideoTrailer(href: String): VideoInfo { 53 | 54 | val document = getJsoup(href) 55 | val title: String = document.selectFirst("h2.fs__stitle")!!.text() 56 | 57 | val playerUrl: String = 58 | document.selectFirst("div.tabs__content.tabs__content_1.active iframe")!!.attr("src") 59 | 60 | val trailerUrl: String = 61 | document.selectFirst("div.tabs__content.tabs__content_2 iframe")?.attr("data-src")?:"empty :)" 62 | 63 | return VideoInfo(title, playerUrl, trailerUrl) 64 | 65 | } 66 | 67 | suspend fun searchKdramma(query: String): List = withContext(Dispatchers.IO) { 68 | println("Searching ... $query ") 69 | val requests = Requests(httpClient, responseParser = parser) 70 | val response = requests.get( 71 | mainUrl, 72 | params = mapOf("story" to query, "do" to "search", "subaction" to "search") 73 | ) 74 | 75 | val document = Jsoup.parse(response.body!!.string()) 76 | 77 | 78 | // Extracting information from the parsed HTML 79 | val tvShows: List = document.select("article.new-short").map { element -> 80 | val title: String = element.select("h3.new-short__title").text() 81 | val date: String = element.select("span.info__date").text() 82 | val year: String = element.select("span.info__xf--text:contains(год) + b a").text() 83 | val country: String = 84 | element.select("span.info__xf--text:contains(страна) + b a").text() 85 | val age: String = element.select("span.info__xf--text:contains(возраст) + b a").text() 86 | val description: String = element.select("div.info__descr").text() 87 | val ratingKP: String = element.select("div.kp__value").text() 88 | val ratingIMDb: String = element.select("div.imdb__value").text() 89 | val episodeCount: String = 90 | element.select("div.new-short__episode span.episode__value").first()?.text() ?: "" 91 | val seasonCount: String = 92 | element.select("div.new-short__episode span.episode__value + span.episode__text") 93 | .text() 94 | val href: String = element.select("a.new-short__title--link").attr("href") 95 | val imageLink: String = element.select("img.new-short__poster--img").attr("data-src") 96 | 97 | TVShow( 98 | title = title, 99 | date = date, 100 | year = year, 101 | country = country, 102 | age = age, 103 | description = description, 104 | ratingKP = ratingKP, 105 | ratingIMDb = ratingIMDb, 106 | episodeCount = episodeCount, 107 | seasonCount = seasonCount, 108 | href = href, 109 | imageLink = imageLink 110 | ) 111 | } 112 | 113 | // Print the list of TVShow instances 114 | tvShows.forEach { 115 | println("====================================") 116 | println(it) 117 | println("====================================") 118 | } 119 | 120 | return@withContext tvShows 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/idub/TVShow.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.idub 2 | 3 | data class TVShow( 4 | val title: String, 5 | val date: String, 6 | val year: String, 7 | val country: String, 8 | val age: String, 9 | val description: String, 10 | val ratingKP: String, 11 | val ratingIMDb: String, 12 | val episodeCount: String, 13 | val seasonCount: String, 14 | val href: String, 15 | val imageLink: String 16 | 17 | ) { 18 | override fun toString(): String { 19 | return """ 20 | Title: $title 21 | Date: $date 22 | Year: $year 23 | Country: $country 24 | Age: $age 25 | Description: $description 26 | KP Rating: $ratingKP 27 | IMDb Rating: $ratingIMDb 28 | Episode Count: $episodeCount 29 | Season Count: $seasonCount 30 | Href: $href 31 | Image Link: $imageLink 32 | --------------------- 33 | """.trimIndent() 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/idub/VideoInfo.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.idub 2 | 3 | data class VideoInfo(val title: String, val playerUrl: String, val trailerUrl: String) { 4 | override fun toString(): String { 5 | return """ 6 | Video Title: $title 7 | Player URL: ${convertMoverEmbedToMp4(playerUrl)} 8 | Trailer URL: $trailerUrl 9 | """.trimIndent() 10 | } 11 | } 12 | 13 | 14 | fun convertMoverEmbedToMp4(embedUrl: String): String { 15 | val regex = Regex("https://mover\\.uz/video/embed/(\\w+)") 16 | val matchResult = regex.find(embedUrl) 17 | 18 | return if (matchResult != null) { 19 | val videoEndpoint = matchResult.groupValues[1] 20 | "https://mover.uz/${videoEndpoint}_m.mp4".replace( 21 | "https://mover.uz", "https://v.mover.uz" 22 | ) 23 | } else { 24 | // Return the original URL if it doesn't match the expected pattern 25 | embedUrl 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/imdb.kt/Imdb.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.imdb.kt 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils 4 | import org.json.JSONObject 5 | import org.jsoup.nodes.Document 6 | import org.jsoup.select.Elements 7 | import org.slf4j.helpers.Util 8 | import kotlin.time.DurationUnit 9 | import kotlin.time.toDuration 10 | 11 | const val BASE_URL = "https://www.imdb.com/" 12 | 13 | fun main(args: Array) { 14 | val url = "never let go" 15 | val response = searchMovie(url) 16 | 17 | println(System.currentTimeMillis().toDuration(DurationUnit.SECONDS)) 18 | println(getDetails(response)) 19 | println(System.currentTimeMillis().toDuration(DurationUnit.SECONDS)) 20 | } 21 | 22 | fun String.extractViId(): String? { 23 | // Regex: URL ichida '/' bilan boshlangan "vi" va undan keyin raqamlar, keyin yana '/' 24 | val regex = Regex("""/(vi\d+)/""") 25 | val match = regex.find(this) 26 | return match?.groupValues?.get(1) 27 | } 28 | 29 | fun getTrailerLink(trailerUrl: String): String { 30 | 31 | val document = Utils.getJsoup( 32 | BASE_URL + "video/$trailerUrl", 33 | mapOf( 34 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 35 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8" 36 | ) 37 | ) 38 | 39 | // __NEXT_DATA__ IDli script tagidagi matnni olamiz 40 | val scriptData = 41 | document.select("script#__NEXT_DATA__").first()?.html() ?: return "master.m3u8 URL notfound" 42 | 43 | // Regex: "url": " ... hls-...-master.m3u8 ..." formatidagi URLni izlaydi 44 | val regex = Regex(""""url"\s*:\s*"([^"]*hls-[^"]*?-master\.m3u8[^"]*)"""") 45 | val matchResult = regex.find(scriptData) 46 | 47 | return if (matchResult != null) { 48 | val masterUrl = matchResult.groupValues[1] 49 | println("Found master.m3u8 URL: $masterUrl") 50 | masterUrl 51 | } else { 52 | println("master.m3u8 URL notfound") 53 | "master.m3u8 URL notfound" 54 | } 55 | } 56 | 57 | fun getTrailer(item: SearchItem): String { 58 | val document = Utils.getJsoup( 59 | item.detailsUrl, 60 | mapOf( 61 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 62 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8" 63 | ) 64 | ) 65 | 66 | // __NEXT_DATA__ identifikatorli script tagini tanlaymiz va uning ichidagi matnni olamiz 67 | val scriptData = 68 | document.select("script#__NEXT_DATA__").first()?.html() ?: return "m3u8 URL notfound" 69 | 70 | // Regex: "url": "https://... .m3u8 ... " formatidagi linklarni izlaymiz 71 | val regex = Regex(""""url"\s*:\s*"([^"]+\.m3u8[^"]*)"""") 72 | 73 | // Barcha mos keladigan natijalarni ro'yxatga to'playmiz 74 | val matches = regex.findAll(scriptData).toList() 75 | 76 | return if (matches.isNotEmpty()) { 77 | // Oxirgi mos kelgan elementni qaytaramiz 78 | val lastUrl = matches.last().groupValues[1] 79 | println(lastUrl) 80 | println("Last m3u8 URL: ${lastUrl.extractViId()}") 81 | return lastUrl.extractViId().toString() 82 | } else { 83 | println("m3u8 URL notfound") 84 | "m3u8 URL notfound" 85 | } 86 | } 87 | fun extractImdbId(url: String): String? { 88 | val regex = """title/(tt\d+)/""".toRegex() 89 | return regex.find(url)?.groupValues?.get(1) 90 | } 91 | 92 | fun getDetails(item: SearchItem): DetailResponse { 93 | println("Details url:${item.detailsUrl}") 94 | val doc = Utils.getJsoup( 95 | item.detailsUrl, 96 | mapOf( 97 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 98 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 99 | ) 100 | ) 101 | 102 | println(extractImdbId(item.detailsUrl)) 103 | 104 | val photoData = getPhotos(doc) 105 | val castData = getCasts(doc) 106 | val quoteItem = getSomeDetailData(doc) 107 | val trailer = getTrailerLink(getTrailer(item)) 108 | val getPrincipalCredits = getPrincipalCast(doc) 109 | return DetailResponse( 110 | photoData.photos, 111 | castData.cast, 112 | quoteItem, 113 | getPrincipalCredits 114 | ) 115 | } 116 | 117 | fun getPhotos(item: Document): PhotosResponse { 118 | val doc = item 119 | val photos = mutableListOf() 120 | 121 | // Rasm ma'lumotlarini yig'ish 122 | val elements: Elements = doc.select("a.sc-180dfae3-0.hDscSA") 123 | for (element in elements) { 124 | val imageUrl = element.select("img.ipc-image").attr("src") 125 | val altText = element.select("img.ipc-image").attr("alt") 126 | val detailsUrl = "https://www.imdb.com" + element.attr("href") 127 | 128 | photos.add(PhotoItem(imageUrl.replace(Regex("UX\\d+"), "UX920"), altText, detailsUrl)) 129 | } 130 | println("Pthotosssss $photos") 131 | 132 | return PhotosResponse(photos) 133 | } 134 | 135 | fun getCasts(item: Document): CastResponse { 136 | val doc = item 137 | val castList = mutableListOf() 138 | 139 | val elements: Elements = doc.select("div[data-testid='title-cast-item']") 140 | for (element in elements) { 141 | val name = element.select("a[data-testid='title-cast-item__actor']").text() 142 | 143 | val character = element.select("span.sc-cd7dc4b7-4.zVTic").text() 144 | 145 | var imageUrl = element.select("img.ipc-image").attr("src") 146 | imageUrl = imageUrl.ifEmpty { 147 | "https://example.com/default_avatar.jpg" 148 | } 149 | 150 | val detailsUrl = 151 | "https://www.imdb.com" + element.select("a.ipc-lockup-overlay").attr("href") 152 | 153 | castList.add( 154 | CastItem( 155 | name, character, ImageUrlFormatter.formatImageUrl(imageUrl), detailsUrl 156 | ) 157 | ) 158 | } 159 | 160 | return CastResponse(castList) 161 | } 162 | 163 | fun getSomeDetailData(document: Document): QuoteItem { 164 | val doc = document 165 | val elements: Elements = doc.select("li[data-testid='didyouknow-quote']") 166 | for (element in elements) { 167 | val character = element.select("a.ipc-link").text() 168 | val quote = element.select("div.ipc-html-content-inner-div p").text() 169 | val detailsUrl = 170 | "https://www.imdb.com" + element.select("a.ipc-metadata-list-item__label").attr("href") 171 | return QuoteItem(character.toString(), quote.toString(), detailsUrl.toString()) 172 | } 173 | return QuoteItem("", "", "") 174 | } 175 | 176 | fun getPrincipalCast(document: Document): PrincipalCredits { 177 | val doc = document 178 | // Directors 179 | val directorElements: Elements = 180 | doc.select("li[data-testid='title-pc-principal-credit']:has(span:contains(Director)) a") 181 | val directors = directorElements.map { 182 | DirectorItem( 183 | name = it.text(), 184 | profileUrl = "https://www.imdb.com" + it.attr("href") 185 | ) 186 | } 187 | 188 | // Writers 189 | val writerElements: Elements = 190 | doc.select("li[data-testid='title-pc-principal-credit']:has(span:contains(Writers)) a") 191 | val writers = writerElements.map { 192 | WriterItem( 193 | name = it.text(), 194 | profileUrl = "https://www.imdb.com" + it.attr("href") 195 | ) 196 | } 197 | 198 | // Stars 199 | val starElements: Elements = 200 | doc.select("li[data-testid='title-pc-principal-credit']:has(a:contains(Stars)) a.ipc-metadata-list-item__list-content-item") 201 | val stars = starElements.map { 202 | StarItem( 203 | name = it.text(), 204 | profileUrl = "https://www.imdb.com" + it.attr("href") 205 | ) 206 | } 207 | 208 | return PrincipalCredits(directors, writers, stars) 209 | } 210 | 211 | fun searchMovie(query: String): SearchItem { 212 | val request = Utils.getJsoup( 213 | "$BASE_URL/find/?q=$query", mapOf( 214 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 215 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 216 | ) 217 | ) 218 | 219 | val doc = request.body() 220 | 221 | val elements: Elements = doc.select("li.find-title-result") 222 | for (element in elements) { 223 | val title = element.select("a.ipc-metadata-list-summary-item__t").text() 224 | val year = element.select("ul.ipc-metadata-list-summary-item__tl li").text() 225 | val cast = element.select("ul.ipc-metadata-list-summary-item__stl li").text() 226 | val imageUrl = element.select("img.ipc-image").attr("src") 227 | val detailsUrl = 228 | "https://www.imdb.com" + element.select("a.ipc-metadata-list-summary-item__t") 229 | .attr("href") 230 | println(detailsUrl) 231 | return SearchItem(title, year, cast, imageUrl, detailsUrl) 232 | } 233 | return SearchItem("", "", "", "", "") 234 | } 235 | 236 | data class CastResponse( 237 | val cast: List 238 | ) 239 | 240 | data class DetailResponse( 241 | val photos: List, 242 | val cast: List, 243 | val quotes: QuoteItem, 244 | val principalCast: PrincipalCredits 245 | ) 246 | 247 | data class SearchResponse( 248 | val items: List 249 | ) 250 | 251 | data class PhotosResponse( 252 | val photos: List 253 | ) 254 | 255 | data class PrincipalCredits( 256 | val directors: List, 257 | val writers: List, 258 | val stars: List 259 | ) 260 | 261 | data class SearchItem( 262 | val title: String, 263 | val year: String, 264 | val cast: String, 265 | val imageUrl: String, 266 | val detailsUrl: String 267 | ) 268 | 269 | data class DirectorItem( 270 | val name: String, 271 | val profileUrl: String 272 | ) 273 | 274 | data class WriterItem( 275 | val name: String, 276 | val profileUrl: String 277 | ) 278 | 279 | data class StarItem( 280 | val name: String, 281 | val profileUrl: String 282 | ) 283 | 284 | data class QuoteItem( 285 | val character: String, val quote: String, val detailsUrl: String 286 | ) 287 | 288 | data class HeroMediaItem( 289 | val imageUrl: String, 290 | val altText: String, 291 | val videoUrl: String?, 292 | val videoTitle: String?, 293 | val videoDuration: String? 294 | ) 295 | 296 | data class CastItem( 297 | val name: String, val character: String, val imageUrl: String, val detailsUrl: String 298 | ) 299 | 300 | data class PhotoItem( 301 | val imageUrl: String, val altText: String, val detailsUrl: String 302 | ) 303 | 304 | object ImageUrlFormatter { 305 | fun formatImageUrl(imageUrl: String): String { 306 | val updatedUrl = imageUrl.replace(Regex("UX\\d+"), "UX400") 307 | 308 | // CR orqasidagi oxirgi ikki raqamni 400 ga o'zgartirish 309 | return updatedUrl.replace(Regex("CR\\d+,\\d+,\\d+,\\d+"), "CR0,0,400,400") 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/ChannelResponse.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class ChannelResponse( 4 | val code: Int, 5 | val `data`: DataX, 6 | val groupIds: List, 7 | val language: String, 8 | val message: String?=null, 9 | val meta: Any 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/Data.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class Data( 4 | val channelId: Int, 5 | val channelTitle: String, 6 | val files: Files, 7 | val moduleId: Int, 8 | val params: Params, 9 | val paymentParams: PaymentParams 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/DataX.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class DataX( 4 | val channelDescription: String, 5 | val channelId: Int, 6 | val channelTitle: String, 7 | val files: FilesX, 8 | val moduleId: Int, 9 | val params: ParamsX, 10 | val paymentParams: PaymentParamsX, 11 | val recommendedSubscriptions: List, 12 | val shareUrl: String 13 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/Files.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class Files( 4 | val posterUrl: String 5 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/FilesX.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class FilesX( 4 | val posterUrl: String, 5 | val streamUrl: String, 6 | val timeshiftUrl: String 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils 4 | import com.azamovhudstc.scarpingtutorial.utils.parser 5 | import com.lagradost.nicehttp.Requests 6 | import kotlinx.coroutines.runBlocking 7 | 8 | val mainUrl = "https://api.itv.uz" 9 | fun main(args: Array) { 10 | 11 | runBlocking { 12 | val responseList = getFreeTvChannels() 13 | val list = responseList.data.filter { it.params.isFree } 14 | val freeChannel = list.get(2) 15 | getChannelDataByID(freeChannel) 16 | } 17 | 18 | } 19 | 20 | 21 | 22 | suspend fun getFreeTvChannels(): TvResponse { 23 | val niceHttp = Requests(baseClient = Utils.httpClient, responseParser = parser) 24 | val response = 25 | niceHttp.get("$mainUrl/v2/cards/channels/list?categoryId=8&itemsPerPage=0&moduleId=1") 26 | .parsed() 27 | 28 | return response 29 | } 30 | 31 | 32 | suspend fun getChannelDataByID(tvResponse: Data) { 33 | val niceHttp = Requests(baseClient = Utils.httpClient, responseParser = parser) 34 | val currentTimeMillis = System.currentTimeMillis() 35 | 36 | val request = niceHttp.get( 37 | "$mainUrl/v2/cards/channels/show?channelId=${tvResponse.channelId}", 38 | headers = 39 | mapOf( 40 | "Itoken" to "6d7e4735846e243ab46a794e332f9519", 41 | "Referer" to "https://itv.uz/", 42 | "Ilogin" to "itv65869f5e66f28", 43 | "Idevice" to "K60-NEu4XqqucXbyV6aIb", 44 | "lauth" to "true", 45 | "lplatform" to "WebSite", 46 | "Itime" to currentTimeMillis.toString() 47 | ), 48 | ) 49 | println(request.body!!.string()) 50 | /// 51 | 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/Meta.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class Meta( 4 | val currentPage: Int, 5 | val itemsPerPage: Int, 6 | val totalItems: Int, 7 | val totalPages: Int 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/Params.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class Params( 4 | val ageLimit: Int, 5 | val isFree: Boolean, 6 | val qualityLabel: String?=null 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/ParamsX.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class ParamsX( 4 | val ageLimit: Int, 5 | val isFree: Boolean, 6 | val isPurchased: Boolean, 7 | val qualityLabel: String 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/PaymentParams.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class PaymentParams( 4 | val paymentModuleId: Int, 5 | val paymentType: String 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/PaymentParamsX.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class PaymentParamsX( 4 | val paymentModuleId: Int, 5 | val paymentType: String 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/itv/TvResponse.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.itv 2 | 3 | data class TvResponse( 4 | val code: Int, 5 | val `data`: List, 6 | val groupIds: List, 7 | val language: String, 8 | val message: String, 9 | val meta: Meta 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/ktor_http/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.ktor_http 2 | 3 | fun main(args: Array) { 4 | 5 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/main/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.main 2 | 3 | import com.azamovhudstc.scarpingtutorial.anibla.AmediaTvBase 4 | import com.azamovhudstc.scarpingtutorial.asilmedia.AsilMediaBase 5 | import com.azamovhudstc.scarpingtutorial.idub.IdubBase 6 | import com.azamovhudstc.scarpingtutorial.theflixer.TheFlixerBase 7 | import com.azamovhudstc.scarpingtutorial.tv_online.TasixBase 8 | import com.azamovhudstc.scarpingtutorial.utils.Color 9 | import com.azamovhudstc.scarpingtutorial.utils.banner 10 | import com.azamovhudstc.scarpingtutorial.utils.displayLoadingAnimation 11 | import com.azamovhudstc.scarpingtutorial.utils.printlnColored 12 | import com.azamovhudstc.scarpingtutorial.uzmovi.UzmoviBase 13 | import kotlinx.coroutines.runBlocking 14 | import java.util.* 15 | 16 | fun main(args: Array) { 17 | val uzmoviBase = UzmoviBase() 18 | val asilMediaBase = AsilMediaBase() 19 | val amediaTvBase = AmediaTvBase() 20 | val tasixBase = TasixBase() 21 | val idubBase = IdubBase() 22 | val theFlixerBase = TheFlixerBase() 23 | val scanner = Scanner(System.`in`) 24 | printlnColored(banner, Color.DARK_ORANGE) 25 | while (true) { 26 | printlnColored("1 -> Uzmovi", Color.GREEN) 27 | printlnColored("2 -> The Flixer", Color.BLUE) 28 | printlnColored("3 -> Idub", Color.YELLOW) 29 | printlnColored("4 -> Online Tv", Color.CYAN) 30 | printlnColored("5 -> Random Movies List ", Color.MAGENTA) 31 | printlnColored("Select Platform: ", Color.DARK_ORANGE) 32 | val scannerForNext = Scanner(System.`in`) 33 | 34 | val selectType = scannerForNext.nextInt() 35 | scannerForNext.nextLine() // Consume the newline character 36 | 37 | when (selectType) { 38 | 1 -> { 39 | 40 | print("Enter Movie Name :") 41 | val movieName = scanner.nextLine() 42 | displayLoadingAnimation("Searching for movies", Color.GREEN) 43 | val list = uzmoviBase.searchMovie(movieName) 44 | printlnColored(" Selected Movie: ${list[0].title}", Color.GREEN) 45 | displayLoadingAnimation("Loading Episodes", Color.GREEN) 46 | 47 | uzmoviBase.movieDetails(list[0]) // Get Movie Details Scraping by href 48 | } 49 | 2 -> { 50 | 51 | runBlocking { 52 | println("Enter Movie Name :") 53 | val movieName = scanner.nextLine() 54 | val list = theFlixerBase.searchMovieByQuery(movieName) 55 | displayLoadingAnimation("Searching for movies", Color.BLUE) 56 | val searchedMovie = list[0] 57 | val tvShow = theFlixerBase.getDetailFullMovie(searchedMovie.watchUrl) 58 | 59 | printlnColored(" Data ID: ${tvShow.dataId}", Color.BLUE) 60 | printlnColored(" BannerUrl: ${tvShow.bannerUrl}", Color.BLUE) 61 | printlnColored(" Movie Title: ${tvShow.title}", Color.BLUE) 62 | printlnColored(" Movie Duration: ${tvShow.duration}", Color.BLUE) 63 | printlnColored(" Movie Country: ${tvShow.country}", Color.BLUE) 64 | printlnColored(" Movie Year: ${tvShow.year}", Color.BLUE) 65 | 66 | displayLoadingAnimation("Loading Episodes", Color.BLUE) 67 | val map = theFlixerBase.getSeasonList(tvShow.dataId) 68 | val season1Episodes = 69 | theFlixerBase.getEpisodeBySeason(map.get(map.keys.first())!!) 70 | 71 | val episode = season1Episodes.get(0) 72 | displayLoadingAnimation("Loading Sources", Color.BLUE) 73 | val sourceList = theFlixerBase.getEpisodeVideoByLink( 74 | episode.dataId, 75 | theFlixerBase.mainUrl + searchedMovie.watchUrl 76 | ) 77 | 78 | 79 | printlnColored("Server Name : ${sourceList.get(0).serverName}", Color.BLUE) 80 | printlnColored("Server Id : ${sourceList.get(0).dataId}", Color.BLUE) 81 | 82 | displayLoadingAnimation("Get Subtitle", Color.BLUE) 83 | val pairData = theFlixerBase.checkM3u8FileByLink(sourceList.get(0)) 84 | theFlixerBase.getSources(pairData) 85 | 86 | // ... (print other details with colors) 87 | } 88 | } 89 | 3 -> { 90 | 91 | print("Enter Movie Name :") 92 | val movieName = scanner.nextLine() 93 | displayLoadingAnimation("Searching for movies", Color.YELLOW) 94 | runBlocking { 95 | val list = idubBase.searchKdramma(movieName) 96 | val selectedData = list[0] 97 | idubBase.movieDetailByHref(href = selectedData.href) 98 | 99 | // ... (print details with colors) 100 | } 101 | } 102 | 4 -> { 103 | 104 | val list = tasixBase.getListTv() 105 | println("Choose TV by Number :") 106 | val selectedNumber = scanner.nextInt() 107 | 108 | if (selectedNumber in list.indices) { 109 | displayLoadingAnimation("Searching for TV", Color.YELLOW) 110 | 111 | tasixBase.getTvFullDataByHref(href = list[selectedNumber].href) 112 | } else { 113 | printlnColored("Invalid selection!!!", Color.RED) 114 | } 115 | } 116 | 5 -> { 117 | displayLoadingAnimation("Fetching random movies", Color.MAGENTA) 118 | asilMediaBase.getMovieList() 119 | } 120 | else -> { 121 | printlnColored("Invalid selection!!!", Color.RED) 122 | } 123 | } 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/med_home/MedHome.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.med_home 2 | import com.azamovhudstc.scarpingtutorial.utils.Utils 3 | import com.azamovhudstc.scarpingtutorial.utils.parser 4 | import com.lagradost.nicehttp.Requests 5 | 6 | import kotlinx.coroutines.runBlocking 7 | 8 | private val baseUrl ="https://test.jadidlar.uz/api" 9 | 10 | fun main(args: Array) { 11 | val medHome =MedHome() 12 | medHome.postRequest() 13 | } 14 | class MedHome { 15 | fun postRequest(){ 16 | runBlocking { 17 | val niceHttp= Requests(baseClient = Utils.httpClient, responseParser = parser) 18 | val request =niceHttp.post("$baseUrl/accounts/token", data = mapOf("phone" to "+998992803809", "password" to "Azamov2456??") ) 19 | 20 | println(request.body.string()) 21 | println(request.code) 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/moviefone/MovieFone.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.moviefone 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 5 | import org.jsoup.nodes.Document 6 | 7 | fun main() { 8 | val selectedTrailer = searchMovieByVideoFon("absolution")[0] 9 | println(getMovieVideoLink(selectedTrailer)) 10 | } 11 | 12 | fun getMovieVideoLink(data: SearchItem): String { 13 | var m3u8Link = "https://cdn.jwplayer.com/manifests/" 14 | val doc = getJsoup( 15 | data.url, mapOf( 16 | "authority" to "www.moviefone.com", 17 | "accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 18 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 19 | ) 20 | ) 21 | val mediaVideoLink = doc.select("#mf-trailer-jwplayer") 22 | .firstOrNull()?.attr("data-media-id")?.let { 23 | "https://cdn.jwplayer.com/v2/media/$it" 24 | } 25 | 26 | if (mediaVideoLink != null) { 27 | val videoData = VideoData(mediaVideoLink = mediaVideoLink) 28 | println("1-ko'rinishdan topildi: $videoData") 29 | m3u8Link += mediaVideoLink.substringAfterLast("/") + ".m3u8" 30 | return m3u8Link 31 | } 32 | 33 | return "" 34 | } 35 | 36 | fun searchMovieByVideoFon(query: String): List { 37 | val doc: Document = Utils.getJsoup( 38 | "https://www.moviefone.com/search/?q=${query}", mapOfHeaders = 39 | mapOf( 40 | "authority" to "www.moviefone.com", 41 | "accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 42 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 43 | // "Cookie" to "_ga=GA1.1.1163975711.1740377515; cto_bundle=nZXLDV9CUG0zRnBwUHBjcHhCd0EzQ1pPVDNzVXV0QWRnMWpmNlpGQ0dxN1NCcjk5YkdUYXlBdE4lMkI4UFRTTjEyODE1Z3dDbFY3WFY2c3ZnUFhSaXJNdG1DQzM4blVhJTJGdmxidEhzQm9NdGtEWXVsckdEY3g2TmZDeExGQTZUZHFqWXFGWiUyQmI1YlhjM3ZJR25KajcyQkxUUDV6cXclM0QlM0Q; __gads=ID=879fbd3ff115d0cf:T=1740377538:RT=1740377858:S=ALNI_MaYaqhjNZB37hhT-sOPZK4eZ7rkLw; __eoi=ID=9e2019d17d122a1e:T=1740377538:RT=1740377858:S=AA-AfjbGjWmuJ0Jj5BSTkQafTmmR; XSRF-TOKEN=eyJpdiI6IkhuUFZoa2JCbDBQSDRGYmFweWhTa2c9PSIsInZhbHVlIjoiWFJCdStOVTZRakpMcWZZV1JRVENudExVNlRmVVF4Rk9BVzBuQnVCNForeHI1Wk92ckxjdjJWalArZG9jVkttdSIsIm1hYyI6Ijg3ZWRjMzA4YzcyZDQzYzJkNDEzOTRmMThmYmQyMTM4Y2ZjYWM3YjQzZDg2NTc3M2M3MjE5N2Y4NzZlMTIwMjkifQ%3D%3D; moviefone_session=eyJpdiI6IkhoNE9MNFB5UzdlOXdzc0pqdXJ4ekE9PSIsInZhbHVlIjoiZVFFZ285WlNKYmJiVlhBaTFIblJFcUhBYXJOWDBRTHh5Z2lIQmdmNU5vYW5WTGdweGFcL3J5aWhNeFZwWWR3YksiLCJtYWMiOiJjNjZiYzYzYzE2NTE2NWNiYjcwNTE0MWU1MGZiY2NmNTcyNmNiMTQ0Y2RkYjkxM2UzMDA2OTRkZGE3MzNhYTRjIn0%3D; _ga_7V3J010SY0=GS1.1.1740377515.1.1.1740377932.28.0.0" 44 | ) 45 | ) 46 | val searchItems = doc.select(".search-item").map { element -> 47 | val title = element.select(".search-asset-title a").text() 48 | val url = element.select(".search-asset-title a").attr("href") 49 | val imageUrl = element.select(".search-image").attr("data-src") 50 | val description = element.select(".search-desc").text() 51 | val type = element.select(".search-type").text() 52 | SearchItem( 53 | title = title, 54 | url = url, 55 | imageUrl = imageUrl, 56 | description = description, 57 | type = type 58 | ) 59 | } 60 | 61 | // Natijani chiqaramiz 62 | searchItems.forEach { 63 | println(it) 64 | } 65 | 66 | return searchItems 67 | 68 | } 69 | 70 | data class SearchItem( 71 | val title: String, 72 | val url: String, 73 | val imageUrl: String, 74 | val description: String, 75 | val type: String 76 | ) 77 | 78 | data class VideoData( 79 | val mediaVideoLink: String? = null, 80 | val playlistId: String? = null 81 | ) 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/shared/SharedPreference.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.shared 2 | 3 | import android.content.Context 4 | import com.azamovhudstc.scarpingtutorial.utils.SharedPreference 5 | 6 | 7 | class LocalStorage(context: Context) : SharedPreference(context) { 8 | companion object { 9 | @Volatile 10 | lateinit var instance: LocalStorage 11 | fun getInstance(context: Context): LocalStorage { 12 | if (!::instance.isInitialized) { 13 | instance = LocalStorage(context) 14 | } 15 | return instance 16 | } 17 | } 18 | 19 | var token: String by Strings() 20 | var json by Strings() 21 | } 22 | 23 | fun String.saveToken(context: Context) { 24 | val sharedPreference = context.getSharedPreferences("shared", Context.MODE_PRIVATE) 25 | val editor = sharedPreference.edit() 26 | 27 | editor.putString("token", this.toString()) 28 | editor.apply() 29 | println("Token Saqlandi: $this") 30 | } 31 | 32 | fun getToken(context: Context): String { 33 | val sharedPreference = context.getSharedPreferences("shared", Context.MODE_PRIVATE) 34 | return sharedPreference.getString("token", "") ?: "Token Not Found" 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/shared/gsonConverters.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.shared 2 | 3 | import com.google.gson.Gson 4 | 5 | fun String.parseJson(): ArrayList { 6 | val gson = Gson() 7 | var list = ArrayList() 8 | list = gson.fromJson(this, ArrayList::class.java) as ArrayList 9 | 10 | return list 11 | } 12 | 13 | fun ArrayList.saveGson(): String { 14 | val gson = Gson() 15 | return gson.toJson(this) 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/socket/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.socket 2 | 3 | import kotlinx.coroutines.launch 4 | import kotlinx.coroutines.runBlocking 5 | import org.java_websocket.client.WebSocketClient 6 | import org.java_websocket.handshake.ServerHandshake 7 | import java.net.URI 8 | import java.util.* 9 | 10 | private const val URL = "ws://127.0.0.1:8080/chat" 11 | fun main(args: Array) { 12 | runBlocking { 13 | launch { 14 | val serverUri = URI(URL) 15 | val client = ChatWebSocketClient(serverUri) { 16 | println(it) 17 | } 18 | client.connect() 19 | client.setSuccessListener { 20 | println("1 -> Send Message ") 21 | println("Choose :") 22 | val scanner = Scanner(System.`in`) 23 | val str = scanner.nextLine() 24 | when (str) { 25 | "1" -> { 26 | print("Enter Message :") 27 | val text = scanner.next() 28 | client.sendMessage(text.toString()) 29 | } 30 | else -> { 31 | print("Enter Message :") 32 | val text = scanner.next() 33 | client.sendMessage(text.toString()) 34 | println("Nothing") 35 | } 36 | } 37 | 38 | 39 | } 40 | } 41 | 42 | 43 | } 44 | } 45 | 46 | 47 | class ChatWebSocketClient(serverURI: URI, private val messageListener: (String) -> Unit) : 48 | WebSocketClient(serverURI) { 49 | private lateinit var onSuccessListener: (String) -> Unit 50 | fun setSuccessListener(onSuccessListener: (String) -> Unit) { 51 | this.onSuccessListener = onSuccessListener 52 | } 53 | 54 | override fun onOpen(handshakedata: ServerHandshake?) { 55 | println("Chat Connected") 56 | } 57 | 58 | override fun onMessage(message: String?) { 59 | println(message) 60 | messageListener.invoke(message!!) 61 | onSuccessListener.invoke("Chat Connected !") 62 | } 63 | 64 | 65 | override fun onClose(code: Int, reason: String?, remote: Boolean) { 66 | println(code) 67 | } 68 | 69 | override fun onError(ex: Exception?) { 70 | ex!!.printStackTrace() 71 | } 72 | 73 | fun sendMessage(message: String) { 74 | send(message) 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/theflixer/Episode.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.theflixer 2 | 3 | data class Episode(val id: String, val dataId: String, val episodeNumber: String, val title: String, val imageUrl: String) 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/theflixer/EpisodeData.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.theflixer 2 | data class EpisodeData( 3 | val dataId: String, 4 | val serverName: String, 5 | val link: String 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/theflixer/Film.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.theflixer 2 | 3 | data class Film( 4 | val title: String, 5 | val year: String, 6 | val type: String, 7 | val posterUrl: String, 8 | val watchUrl: String 9 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/theflixer/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.theflixer 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Utils 4 | 5 | fun updateEndpoint(url: String): String { 6 | val baseUrl = "https://theflixertv.to" 7 | val path = url.removePrefix(baseUrl) 8 | 9 | return when { 10 | path.startsWith("/movie/") -> baseUrl + path.replace("/movie/", "/watch-movie/") 11 | path.startsWith("/tv/") -> baseUrl + path.replace("/tv/", "/watch-tv/") 12 | else -> url 13 | } 14 | } 15 | 16 | fun mapToFilm(map: Map): Film { 17 | return Film( 18 | title = map["title"] ?: "", 19 | year = map["year"] ?: "", 20 | type = map["type"] ?: "", 21 | posterUrl = map["posterUrl"] ?: "", 22 | watchUrl = map["watchUrl"] ?: "" 23 | ) 24 | } 25 | 26 | 27 | fun addLineBetweenWords(text: String, line: String): String { 28 | val words = text.split(" ") 29 | val newText = words.joinToString(line) 30 | return newText 31 | } 32 | 33 | fun parseRatingInfo(id: String,mainUrl:String): RatingInfo? { 34 | val document = Utils.getJsoup("$mainUrl/ajax/vote_info/$id") 35 | 36 | return try { 37 | val title = document.select(".rs-title").text() 38 | val totalVotes = document.select(".rr-mark").text().split(" ")[0].toInt() 39 | val ratingPercentage = document.select(".progress-bar").attr("style") 40 | .split("width: ")[1] 41 | .split("%;")[0] 42 | .toDouble() 43 | 44 | RatingInfo(title, totalVotes, ratingPercentage) 45 | } catch (e: Exception) { 46 | e.printStackTrace() 47 | null 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/theflixer/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.theflixer 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Color 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 5 | import com.azamovhudstc.scarpingtutorial.utils.Utils.httpClient 6 | import com.azamovhudstc.scarpingtutorial.utils.parser 7 | import com.azamovhudstc.scarpingtutorial.utils.printlnColored 8 | import com.lagradost.nicehttp.Requests 9 | import kotlinx.coroutines.Dispatchers 10 | import kotlinx.coroutines.runBlocking 11 | import kotlinx.coroutines.withContext 12 | import org.jsoup.nodes.Element 13 | 14 | 15 | 16 | class TheFlixerBase() { 17 | val mainUrl = "https://theflixertv.to" 18 | suspend fun getSources(pairData: Pair) { 19 | 20 | val requests = Requests(baseClient = httpClient, responseParser = parser) 21 | val response = requests.get( 22 | url = "https://rabbitstream.net/ajax/embed-4/getSources?id=${pairData.second}", 23 | headers = mapOf( 24 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", 25 | "Sec-Fetch-Dest" to "iframe", 26 | "Sec-GPC" to "1", 27 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0", 28 | "Sec-Fetch-Mode" to "navigate", 29 | "Sec-Fetch-Site" to "cross-site", 30 | "Upgrade-Insecure-Requests" to "1", 31 | "Referer" to "https://rabbitstream.net/embed-4/BI6Zv2yJxZBq?z=", 32 | "X-Requested-With" to "XMLHttpRequest" 33 | ) 34 | ) 35 | 36 | println(response.body.string()) 37 | 38 | } 39 | 40 | 41 | fun main(args: Array) { 42 | runBlocking { 43 | val list = searchMovieByQuery("Stranger things") 44 | val searchedMovie = list.get(0) 45 | val tvShow = getDetailFullMovie(searchedMovie.watchUrl) 46 | println(" Data ID: ${tvShow.dataId}") 47 | println(" Title: ${tvShow.title}") 48 | println(" Year: ${tvShow.year}") 49 | println(" Type: ${tvShow.type}") 50 | println(" Banner URL: ${tvShow.bannerUrl}") 51 | println(" Rating Info: ${tvShow.ratingInfo}") 52 | println(" Poster URL: ${tvShow.posterUrl}") 53 | println(" Released: ${tvShow.released}") 54 | println(" Genres: ${tvShow.genres.joinToString(", ")}") 55 | println(" Casts: ${tvShow.casts.joinToString(", ")}") 56 | println(" Duration: ${tvShow.duration}") 57 | println(" Country: ${tvShow.country}") 58 | println(" Production: ${tvShow.production}") 59 | 60 | val map = getSeasonList(tvShow.dataId) 61 | val season1Episodes = getEpisodeBySeason(map.get(map.keys.first())!!) 62 | 63 | val episode = season1Episodes.get(0) 64 | val sourceList = getEpisodeVideoByLink(episode.dataId, mainUrl + searchedMovie.watchUrl) 65 | 66 | 67 | println("Server Name : ${sourceList.get(0).serverName}") 68 | println("Server Id : ${sourceList.get(0).dataId}") 69 | 70 | val pairData = checkM3u8FileByLink(sourceList.get(0)) 71 | getSources(pairData) 72 | } 73 | } 74 | suspend fun checkM3u8FileByLink(episodeData: EpisodeData): Pair = 75 | withContext(Dispatchers.IO) { 76 | val document = getJsoup("$mainUrl/ajax/episode/sources/${episodeData.dataId}") 77 | val json = document.body().select("body").text() 78 | val regex = """"link"\s*:\s*"([^"]+)"""".toRegex() 79 | val matchResult = regex.find(json) 80 | 81 | val link = matchResult?.groupValues?.get(1) ?: "" 82 | val request = Requests(baseClient = httpClient, responseParser = parser) 83 | 84 | val response = request.get( 85 | link, 86 | headers = mapOf( 87 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", 88 | "Sec-Fetch-Dest" to "iframe", 89 | "Sec-GPC" to "1", 90 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0", 91 | "Sec-Fetch-Mode" to "navigate", 92 | "Sec-Fetch-Site" to "cross-site", 93 | "Upgrade-Insecure-Requests" to "1", 94 | "Referer" to "https://theflixertv.to/", 95 | ) 96 | ) 97 | 98 | val html = response.body.string() 99 | 100 | val realIdRegex = """data-realid="([^"]+)"""".toRegex() 101 | val dataIdRegex = """data-id="([^"]+)"""".toRegex() 102 | 103 | val realIdMatchResult = realIdRegex.find(html) 104 | val dataIdMatchResult = dataIdRegex.find(html) 105 | 106 | val realId = realIdMatchResult?.groupValues?.get(1) ?: "" 107 | val dataId = dataIdMatchResult?.groupValues?.get(1) ?: "" 108 | 109 | println("Real ID: $realId") 110 | println("Data ID: $dataId") 111 | 112 | return@withContext Pair(realId, dataId) 113 | 114 | } 115 | 116 | 117 | fun getEpisodeVideoByLink(id: String, detailFullLink: String): ArrayList { 118 | val sourceList = ArrayList() 119 | 120 | 121 | runBlocking { 122 | val document = getJsoup("https://theflixertv.to/ajax/episode/servers/$id") 123 | val episodeElements: List = document.select(".ulclear .link-item") 124 | for (episodeElement in episodeElements) { 125 | val dataId = episodeElement.attr("data-id") 126 | val serverName = episodeElement.select("span").text() 127 | val updateUrl = updateEndpoint(detailFullLink) + ".$dataId" 128 | val episodeData = EpisodeData(dataId, serverName, updateUrl) 129 | sourceList.add(episodeData) 130 | } 131 | 132 | } 133 | return sourceList 134 | } 135 | 136 | 137 | fun getEpisodeBySeason(seasonId: String): ArrayList { 138 | val document = getJsoup("$mainUrl/ajax/season/episodes/${seasonId}") 139 | val episodesList = arrayListOf() 140 | 141 | // Select all the elements with class "flw-item film_single-item episode-item eps-item" 142 | val episodeItems = document.select(".flw-item.film_single-item.episode-item.eps-item") 143 | 144 | // Iterate through the items and extract episode information 145 | for (episodeItem in episodeItems) { 146 | val id = episodeItem.attr("id") 147 | val dataId = episodeItem.attr("data-id") 148 | val episodeNumber = episodeItem.select(".episode-number").text() 149 | val title = episodeItem.select(".film-name a").attr("title") 150 | val imageUrl = episodeItem.select(".film-poster-img").attr("src") 151 | 152 | // Create an Episode object and add it to the list 153 | episodesList.add(Episode(id, dataId, episodeNumber, title, imageUrl)) 154 | } 155 | 156 | return episodesList 157 | } 158 | 159 | 160 | fun getSeasonList(id: String): Map { 161 | val document = getJsoup("$mainUrl/ajax/season/list/$id") 162 | val seasonsMap = mutableMapOf() 163 | val seasonItems = document.select(".dropdown-item.ss-item") 164 | for (seasonItem in seasonItems) { 165 | val dataId = seasonItem.attr("data-id") 166 | val seasonName = seasonItem.text() 167 | seasonsMap[seasonName] = dataId 168 | } 169 | return seasonsMap 170 | } 171 | 172 | suspend fun getDetailFullMovie(href: String): TVShow { 173 | val document = getJsoup("$mainUrl$href") 174 | val dataId = document.select("div.detail_page-watch").attr("data-id") 175 | val title = document.select("h2.heading-name a").text() 176 | val year = document.select("div.row-line span.type:contains(Released) + span").text() 177 | val type = "TV" // Assuming it's always a TV show based on the provided HTML 178 | val posterUrl = document.select("div.film-poster img.film-poster-img").attr("src") 179 | val overview = document.select("div.description").text() 180 | val released = document.select("div.row-line span.type:contains(Released) + span").text() 181 | val genres = document.select("div.row-line span.type:contains(Genre) + a").eachText() 182 | val casts = document.select("div.row-line span.type:contains(Casts) + a").eachText() 183 | val duration = document.select("div.row-line span.type:contains(Duration) + span").text() 184 | val country = document.select("div.row-line span.type:contains(Country) + a").text() 185 | val production = document.select("div.row-line span.type:contains(Production) + a").text() 186 | val banner = document.select("meta[property=og:image]").attr("content") 187 | return TVShow( 188 | dataId = dataId, 189 | title = title, 190 | year = year, 191 | type = type, 192 | posterUrl = posterUrl, 193 | bannerUrl = banner, 194 | overview = overview, 195 | released = released, 196 | genres = genres, 197 | casts = casts, 198 | duration = duration, 199 | country = country, 200 | production = production, 201 | ratingInfo = parseRatingInfo(dataId, mainUrl)!! 202 | ) 203 | 204 | } 205 | 206 | 207 | fun searchMovieByQuery(query: String): ArrayList { 208 | val list = ArrayList() 209 | printlnColored( 210 | "------------------------------ ${ 211 | addLineBetweenWords( 212 | query, 213 | "-" 214 | ) 215 | }------------------------------\n" 216 | , Color.BLUE ) 217 | 218 | val document = 219 | getJsoup( 220 | "$mainUrl/search/${ 221 | addLineBetweenWords( 222 | query, 223 | "-" 224 | ) 225 | }" 226 | ).getElementsByClass("block_area-content block_area-list film_list film_list-grid") 227 | for (filmItem in document.select("div.film_list-wrap > div.flw-item")) { 228 | val filmData = mapOf( 229 | "title" to filmItem.select("h2.film-name a").attr("title"), 230 | "year" to filmItem.select("span.fdi-item:eq(0)").text(), 231 | "type" to filmItem.select("span.fdi-item strong").text(), 232 | "posterUrl" to filmItem.select("img.film-poster-img").attr("data-src"), 233 | "watchUrl" to filmItem.select("a.film-poster-ahref").attr("href") 234 | ) 235 | val filmDataClass = mapToFilm(filmData) 236 | list.add(filmDataClass) 237 | 238 | } 239 | return list 240 | } 241 | 242 | } 243 | 244 | 245 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/theflixer/RatingInfo.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.theflixer 2 | 3 | data class RatingInfo(val title: String, val totalVotes: Int, val ratingPercentage: Double) 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/theflixer/TVShow.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.theflixer 2 | 3 | data class TVShow( 4 | val dataId: String, 5 | val title: String, 6 | val year: String, 7 | val type: String, 8 | val bannerUrl: String, 9 | val ratingInfo: RatingInfo, 10 | val posterUrl: String, 11 | val overview: String, 12 | val released: String, 13 | val genres: List, 14 | val casts: List, 15 | val duration: String, 16 | val country: String, 17 | val production: String 18 | ) { 19 | override fun toString(): String { 20 | return """ 21 | |TV Show: 22 | | Data ID: $dataId 23 | | Title: $title 24 | | Year: $year 25 | | Type: $type 26 | | Banner URL: $bannerUrl 27 | | Rating Info: $ratingInfo 28 | | Poster URL: $posterUrl 29 | | Overview: $overview 30 | | Released: $released 31 | | Genres: $genres 32 | | Casts: $casts 33 | | Duration: $duration 34 | | Country: $country 35 | | Production: $production 36 | """.trimMargin() 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/themoviedb/TheMovieDB.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.themoviedb 2 | 3 | import com.azamovhudstc.scarpingtutorial.imdb.kt.BASE_URL 4 | import com.azamovhudstc.scarpingtutorial.imdb.kt.DetailResponse 5 | import com.azamovhudstc.scarpingtutorial.imdb.kt.ImageUrlFormatter 6 | import com.azamovhudstc.scarpingtutorial.imdb.kt.SearchItem 7 | import com.azamovhudstc.scarpingtutorial.imdb.kt.extractImdbId 8 | import com.azamovhudstc.scarpingtutorial.utils.Utils 9 | import org.jsoup.nodes.Document 10 | import org.jsoup.nodes.Element 11 | import org.jsoup.select.Elements 12 | import org.slf4j.helpers.Util 13 | 14 | fun main(args: Array) { 15 | val searchItem = searchMovie("Transformers one") 16 | val getDetail = getDetails(searchItem) 17 | } 18 | 19 | fun searchMovie(query: String): SearchItem { 20 | val request = Utils.getJsoup( 21 | "$BASE_URL/find/?q=$query", mapOf( 22 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 23 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 24 | ) 25 | ) 26 | 27 | val doc = request.body() 28 | 29 | val elements: Elements = doc.select("li.find-title-result") 30 | for (element in elements) { 31 | val title = element.select("a.ipc-metadata-list-summary-item__t").text() 32 | val year = element.select("ul.ipc-metadata-list-summary-item__tl li").text() 33 | val cast = element.select("ul.ipc-metadata-list-summary-item__stl li").text() 34 | val imageUrl = element.select("img.ipc-image").attr("src") 35 | val detailsUrl = 36 | "https://www.imdb.com" + element.select("a.ipc-metadata-list-summary-item__t") 37 | .attr("href") 38 | println(detailsUrl) 39 | return SearchItem(title, year, cast, imageUrl, detailsUrl) 40 | } 41 | return SearchItem("", "", "", "", "") 42 | } 43 | 44 | 45 | fun getDetails(item: SearchItem): ArrayList { 46 | val backdrops = ArrayList() 47 | println() 48 | val imdbId = extractImdbId(item.detailsUrl) 49 | val doc = Utils.getJsoup( 50 | "https://imdb.com/title/${imdbId}/mediaindex/?ref_=mv_sm", 51 | mapOf( 52 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", 53 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 54 | 55 | ) 56 | ) 57 | println("Details url :https://imdb.com/title/${imdbId}/mediaindex/?ref_=mv_sm") 58 | println("Details url :${doc}") 59 | 60 | val images = doc.select("img.ipc-image") 61 | 62 | for (image in images) { 63 | val srcSet = image.attr("srcSet") 64 | val links = srcSet.split(",") 65 | 66 | // Siz so'ragan 1230px o'lchamli rasm URLlarini olish 67 | val link1230 = links.firstOrNull { it.contains("UX1230") }?.trim()?.split(" ")?.first() 68 | 69 | // Agar 1230 o'lchamli rasm topilmasa, asl src linkni olish 70 | val finalLink = link1230 ?: image.attr("src") 71 | backdrops.add(Backdrop(ImageUrlFormatter.formatImageUrl(finalLink))) 72 | } 73 | 74 | return backdrops 75 | } 76 | 77 | 78 | //val id = element.attr("data-object-id") 79 | //val title = element.select("div.title h2").text() 80 | //val releaseDate = element.select("span.release_date").text() 81 | //val imageUrl = element.select("div.poster img").attr("src") 82 | //val detailsUrl = element.select("div.poster a").attr("href") 83 | //val description = element.select("div.overview p").text() 84 | 85 | data class SearchItem( 86 | val title: String, 87 | val imageUrl: String, 88 | val detailsUrl: String, 89 | ) 90 | 91 | data class Backdrop( 92 | val originalUrl: String, 93 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/tv_online/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.tv_online 2 | 3 | import com.azamovhudstc.scarpingtutorial.tv_online.parsed.Movie 4 | import com.azamovhudstc.scarpingtutorial.utils.Color 5 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 6 | import com.azamovhudstc.scarpingtutorial.utils.Utils.httpClient 7 | import com.azamovhudstc.scarpingtutorial.utils.displayLoadingAnimation 8 | import com.azamovhudstc.scarpingtutorial.utils.parser 9 | import com.azamovhudstc.scarpingtutorial.utils.printlnColored 10 | import com.lagradost.nicehttp.Requests 11 | import kotlinx.coroutines.runBlocking 12 | import org.jsoup.nodes.Element 13 | import org.jsoup.select.Elements 14 | 15 | 16 | private const val mainURL = "https://tas-ix.tv" 17 | fun main(args: Array) { 18 | 19 | var tasixBase = TasixBase() 20 | val list = tasixBase.getListTv() 21 | tasixBase.getTvFullDataByHref(list.get(list.lastIndex).href) 22 | 23 | } 24 | 25 | class TasixBase { 26 | 27 | fun main() { 28 | val list = getListTv() 29 | 30 | getTvFullDataByHref(list.get(list.lastIndex).href) 31 | } 32 | 33 | 34 | 35 | fun getTvFullDataByHref(href: String) { 36 | try { 37 | val doc = getJsoup(href) 38 | val iframeElement = doc.select("iframe").first() 39 | val srcAttributeValue = iframeElement?.attr("src") 40 | val pattern = Regex("""file=([^&]+)""") 41 | 42 | if (iframeElement != null) { 43 | val matchResult = pattern.find(srcAttributeValue.toString()) 44 | 45 | // Extract the value of the file parameter if a match is found 46 | val fileParameterValue = matchResult?.groups?.get(1)?.value 47 | 48 | if (fileParameterValue != null) { 49 | println("Link ::"+fileParameterValue) 50 | } else { 51 | println("File parameter not found.") 52 | } 53 | } 54 | 55 | } catch (e: Exception) { 56 | printlnColored("SSL ERROR (Do`nt Worry)", Color.DARK_ORANGE) 57 | } 58 | } 59 | 60 | 61 | 62 | 63 | 64 | fun getListTv(): List { 65 | displayLoadingAnimation("Loading Tv list", Color.YELLOW) 66 | val doc = getJsoup(mainURL) 67 | val movieElements: Elements = doc.select(".tcarusel-item.main-news") 68 | if (movieElements != null) { 69 | // Select all links within the hidden-menu 70 | movieElements 71 | .map { 72 | val href = it.select("a[href]").attr("href") 73 | val title = it.select("a[href]").text() 74 | val image = it.select("img.xfieldimage").attr("src") 75 | val rating = it.select(".current-rating").text().toInt() 76 | printlnColored(" Text: ${removeNumbers(title)}", Color.YELLOW) 77 | printlnColored(" Image: $image", Color.DARK_ORANGE) 78 | printlnColored(" Href: $href", Color.CYAN) 79 | printlnColored(" Rating: $rating", Color.GREEN) 80 | printlnColored("-----------------------------", Color.YELLOW) 81 | 82 | } 83 | } else { 84 | printlnColored("Uzbek channels not found.", Color.YELLOW) 85 | } 86 | return movieElements.map { 87 | val href = it.select("a[href]").attr("href") 88 | val title = it.select("a[href]").text() 89 | val image = it.select("img.xfieldimage").attr("src") 90 | val rating = it.select(".current-rating").text().toInt() 91 | 92 | Movie(href, title, image, rating) 93 | } 94 | 95 | } 96 | 97 | fun removeNumbers(input: String): String { 98 | return input.replace(Regex("\\d+"), "").trim() 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/tv_online/parsed/Movie.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.tv_online.parsed 2 | 3 | data class Movie(val href: String, val title: String, val image: String, val rating: Int) 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/utils/SharedPreference.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.utils 2 | import android.content.Context 3 | import android.content.SharedPreferences 4 | import androidx.core.content.edit 5 | import kotlin.properties.ReadWriteProperty 6 | import kotlin.reflect.KProperty 7 | 8 | 9 | abstract class SharedPreference(context: Context, preferences: SharedPreferences? = null) { 10 | private val pref = 11 | preferences ?: context.getSharedPreferences(javaClass.canonicalName, Context.MODE_PRIVATE) 12 | 13 | inner class Booleans(private val init: Boolean = false) : 14 | ReadWriteProperty { 15 | override fun getValue(thisRef: SharedPreference, property: KProperty<*>) = 16 | pref.getBoolean(property.name, init) 17 | 18 | override fun setValue(thisRef: SharedPreference, property: KProperty<*>, value: Boolean) = 19 | pref.edit { putBoolean(property.name, value).apply() } 20 | } 21 | 22 | inner class Ints(private val defValue: Int = -1) : ReadWriteProperty { 23 | override fun getValue(thisRef: Any, property: KProperty<*>) = 24 | pref.getInt(property.name, defValue) 25 | 26 | override fun setValue(thisRef: Any, property: KProperty<*>, value: Int) = 27 | pref.edit { putInt(property.name, value).apply() } 28 | } 29 | 30 | inner class Longs(private val defValue: Long = 0L) : ReadWriteProperty { 31 | override fun getValue(thisRef: Any, property: KProperty<*>) = 32 | pref.getLong(property.name, defValue) 33 | 34 | override fun setValue(thisRef: Any, property: KProperty<*>, value: Long) = 35 | pref.edit { putLong(property.name, value).apply() } 36 | } 37 | 38 | inner class Strings(private val defValue: String = "") : ReadWriteProperty { 39 | override fun getValue(thisRef: Any, property: KProperty<*>): String = 40 | pref.getString(property.name, defValue) ?: "" 41 | 42 | override fun setValue(thisRef: Any, property: KProperty<*>, value: String) = 43 | pref.edit { putString(property.name, value).apply() } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/utils/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.utils 2 | 3 | import com.google.gson.JsonElement 4 | import com.google.gson.JsonParser 5 | import okhttp3.FormBody 6 | import okhttp3.HttpUrl 7 | import okhttp3.OkHttpClient 8 | import okhttp3.Request 9 | import org.jsoup.Jsoup 10 | import org.jsoup.nodes.Document 11 | import java.util.concurrent.TimeUnit 12 | 13 | object Utils { 14 | 15 | var httpClient = OkHttpClient.Builder() 16 | .connectTimeout(30, TimeUnit.SECONDS) 17 | .readTimeout(30, TimeUnit.SECONDS) 18 | .callTimeout(2, TimeUnit.MINUTES) 19 | .build() 20 | 21 | fun getAsilMedia( 22 | host: String? = null, 23 | pathSegment: ArrayList? = null, 24 | mapOfHeaders: Map? = null, 25 | params: Map? = null, 26 | ): String { 27 | val urlBuilder = HttpUrl.Builder() 28 | .scheme("http") // Replace with your scheme (http or https) 29 | .host(host!!) // Replace with your actual host 30 | pathSegment?.forEach { 31 | urlBuilder.addPathSegment(it) 32 | } 33 | 34 | 35 | if (!params.isNullOrEmpty()) { 36 | params.forEach { 37 | urlBuilder.addQueryParameter(it.key, it.value) 38 | } 39 | } 40 | 41 | val requestBuilder = Request.Builder().url(urlBuilder.build()) 42 | if (!mapOfHeaders.isNullOrEmpty()) { 43 | mapOfHeaders.forEach { 44 | requestBuilder.addHeader(it.key, it.value) 45 | } 46 | } 47 | var data = httpClient.newCall(requestBuilder.build()) 48 | .execute() 49 | 50 | println(data.body?.string()) 51 | return data.body.string() 52 | } 53 | 54 | fun get( 55 | url: String, 56 | mapOfHeaders: Map? = null 57 | ): String { 58 | val requestBuilder = Request.Builder().url(url) 59 | if (!mapOfHeaders.isNullOrEmpty()) { 60 | mapOfHeaders.forEach { 61 | requestBuilder.addHeader(it.key, it.value) 62 | } 63 | } 64 | return httpClient.newCall(requestBuilder.build()) 65 | .execute().body!!.string() 66 | } 67 | 68 | fun post( 69 | url: String, 70 | mapOfHeaders: Map? = null, 71 | payload: Map? = null 72 | ): String { 73 | val requestBuilder = Request.Builder().url(url) 74 | 75 | if (!mapOfHeaders.isNullOrEmpty()) { 76 | mapOfHeaders.forEach { 77 | requestBuilder.addHeader(it.key, it.value) 78 | } 79 | } 80 | 81 | val requestBody = payload?.let { 82 | FormBody.Builder().apply { 83 | it.forEach { (key, value) -> 84 | add(key, value) 85 | } 86 | }.build() 87 | } 88 | 89 | if (requestBody != null) { 90 | requestBuilder.post(requestBody) 91 | } 92 | 93 | val response = httpClient.newCall(requestBuilder.build()).execute() 94 | return response.body?.string() ?: "" 95 | } 96 | 97 | fun getJsoup( 98 | url: String, 99 | mapOfHeaders: Map? = null 100 | ): Document { 101 | return Jsoup.parse(get(url, mapOfHeaders)) 102 | } 103 | 104 | fun getJsoupAsilMedia( 105 | host: String, 106 | pathSegment: ArrayList? /* = java.util.ArrayList? */ = null, 107 | params: Map? = null, 108 | mapOfHeaders: Map? = null 109 | ): Document { 110 | return Jsoup.parse( 111 | getAsilMedia( 112 | host = host, 113 | pathSegment = pathSegment, 114 | params = params, 115 | mapOfHeaders = mapOfHeaders 116 | ) 117 | ) 118 | } 119 | 120 | fun getJson( 121 | url: String, 122 | mapOfHeaders: Map? = null 123 | ): JsonElement? { 124 | return JsonParser.parseString(get(url, mapOfHeaders)) 125 | } 126 | 127 | fun postJson( 128 | url: String, 129 | mapOfHeaders: Map? = null, 130 | payload: Map? = null 131 | ): JsonElement? { 132 | val res = post(url, mapOfHeaders, payload) 133 | return JsonParser.parseString(res) 134 | } 135 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/utils/banner.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.utils 2 | 3 | val banner = 4 | """"+---------------------------------------------------------------------------------+ 5 | | | 6 | | _ _ _ _ ______ _ | 7 | | (_)(_)(_) | | / _____) (_) | 8 | | _ _ _ _____ | |__ ( (____ ____ ____ _____ ____ _ ____ ____ | 9 | | | || || || ___ || _ \ \____ \ / ___) / ___)(____ || _ \ | || _ \ / _ | | 10 | | | || || || ____|| |_) ) _____) )( (___ | | / ___ || |_| || || | | |( (_| | | 11 | | \_____/ |_____)|____/ (______/ \____)|_| \_____|| __/ |_||_| |_| \___ | | 12 | | |_| (_____| | 13 | | Telegram : https://t.me/native_applications | 14 | | Github : https://github.com/professorDeveloper | 15 | +---------------------------------------------------------------------------------+""".trimMargin() -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/utils/displayLoadingAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.utils 2 | 3 | // Function to display a simple loading animation with color 4 | fun displayLoadingAnimation(message: String, color: Color) { 5 | val loadingChars = listOf("⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏") 6 | var counter = 0 7 | 8 | val loadingAnimation = Thread { 9 | try { 10 | while (true) { 11 | printColored("\r${loadingChars[counter % loadingChars.size]} $message", color) 12 | counter++ 13 | Thread.sleep(100) // Adjust the delay based on your preference 14 | } 15 | } catch (e: InterruptedException) { 16 | // Restore interrupted status 17 | Thread.currentThread().interrupt() 18 | } 19 | } 20 | 21 | loadingAnimation.start() 22 | 23 | // Run the loading animation for a few seconds (you can adjust the duration) 24 | Thread.sleep(3000) 25 | 26 | loadingAnimation.interrupt() 27 | 28 | // Clear the loading line 29 | printColored("\r${" ".repeat(message.length + 3)}\r", color) 30 | } 31 | 32 | // Function to print colored text 33 | fun printlnColored(text: String, color: Color) { 34 | val colorCode = when (color) { 35 | Color.RED -> "\u001B[31m" 36 | Color.GREEN -> "\u001B[32m" 37 | Color.YELLOW -> "\u001B[33m" 38 | Color.BLUE -> "\u001B[34m" 39 | Color.MAGENTA -> "\u001B[35m" 40 | Color.CYAN -> "\u001B[36m" 41 | Color.WHITE -> "\u001B[37m" 42 | Color.DARK_ORANGE -> "\u001B[38;2;170;85;0m" 43 | 44 | } 45 | val resetColor = "\u001B[0m" 46 | 47 | println("$colorCode$text$resetColor") 48 | } 49 | 50 | fun printColored(text: String, color: Color) { 51 | val colorCode = when (color) { 52 | Color.RED -> "\u001B[31m" 53 | Color.GREEN -> "\u001B[32m" 54 | Color.YELLOW -> "\u001B[33m" 55 | Color.BLUE -> "\u001B[34m" 56 | Color.MAGENTA -> "\u001B[35m" 57 | Color.CYAN -> "\u001B[36m" 58 | Color.WHITE -> "\u001B[37m" 59 | Color.DARK_ORANGE -> "\u001B[38;2;170;85;0m" 60 | } 61 | val resetColor = "\u001B[0m" 62 | 63 | print("$colorCode$text$resetColor") 64 | } 65 | 66 | // Enum to represent ANSI color codes 67 | enum class Color { 68 | RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, DARK_ORANGE 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/utils/parser.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.utils 2 | 3 | import com.fasterxml.jackson.databind.DeserializationFeature 4 | import com.fasterxml.jackson.databind.ObjectMapper 5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper 6 | import com.lagradost.nicehttp.ResponseParser 7 | import kotlin.reflect.KClass 8 | 9 | val parser = object : ResponseParser { 10 | val mapper: ObjectMapper = jacksonObjectMapper().configure( 11 | DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, 12 | false 13 | ) 14 | 15 | override fun parse(text: String, kClass: KClass): T { 16 | return mapper.readValue(text, kClass.java) 17 | } 18 | 19 | override fun parseSafe(text: String, kClass: KClass): T? { 20 | return try { 21 | mapper.readValue(text, kClass.java) 22 | } catch (e: Exception) { 23 | null 24 | } 25 | } 26 | 27 | override fun writeValueAsString(obj: Any): String { 28 | return mapper.writeValueAsString(obj) 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/utils/removeEmTagsWithRegex.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.utils 2 | 3 | import com.azamovhudstc.scarpingtutorial.anibla.AmediaSearchData 4 | 5 | fun String.removeEmTagsWithRegex(): String { 6 | val regex = Regex("(.*?)") 7 | return regex.replace(this, "$1") 8 | } 9 | fun showData(data: AmediaSearchData) { 10 | printlnColored("=================================", Color.GREEN) 11 | data.data.forEach { 12 | printlnColored(it.name.uz, Color.YELLOW) 13 | } 14 | printlnColored("=================================", Color.GREEN) 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/uzmovi/CustomXMLHttpRequest.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.uzmovi 2 | 3 | import android.annotation.SuppressLint 4 | import java.net.URL 5 | import java.util.Base64 6 | 7 | class CustomXMLHttpRequest { 8 | var origOpen: ((String, String, Boolean, String?, String?, String?) -> Unit)? = null 9 | 10 | fun open(method: String, url: String, async: Boolean, user: String?, password: String?, vararg args: String?) { 11 | val _0x500e36 = URL(url) 12 | if (_0x500e36.host.contains("uzdown.space")) { 13 | val origin = URL(url).protocol + "://" + URL(url).host 14 | val urlObj = URL(url) 15 | // args[1] = "${urlObj.protocol}://${urlObj.host}/" + 16 | // "${generateRandomString(30)}/" + 17 | // "${generateRandomString(10)}.mpd" 18 | 19 | // origOpen?.invoke(method, args.joinToString("/"), async, user, password) 20 | 21 | // Replace these placeholder functions with your actual logic 22 | val xAttDeviceId = generateRandomString(16) 23 | val xMatch = btoa(generateRandomString(16)) 24 | val xPath = generateRandomString(40) 25 | 26 | println("Modified URL: ${args[1]}") 27 | println("X-ATT-DeviceId: $xAttDeviceId") 28 | println("X-Match: $xMatch") 29 | println("X-Path: $xPath") 30 | } else { 31 | // origOpen?.invoke(method, url, async, user, password, *args.toString()) 32 | } 33 | } 34 | 35 | // Placeholder functions, replace with your actual logic 36 | private fun generateRandomString(length: Int): String { 37 | val characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 38 | return (1..length) 39 | .map { characters.random() } 40 | .joinToString("") 41 | } 42 | 43 | @SuppressLint("NewApi") 44 | private fun btoa(data: String): String { 45 | return Base64.getEncoder().encodeToString(data.toByteArray()) 46 | } 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | fun main() { 57 | // Asl URL 58 | val originalURL = "https://srv416.uzdown.space/ghtj21e75mbfa72sh94gocpq0ids2q/65da7d6th2.mpd" 59 | 60 | // Modified URL generatsiyasi 61 | val modifiedURL = generateSimilarURL(originalURL) 62 | println("Original URL: $originalURL") 63 | println("Generated URL: $modifiedURL") 64 | 65 | // X-ATT-DeviceId, X-Match, va X-Path generatsiyasi 66 | val xAttDeviceId = generateRandomString(16) 67 | val xMatch = btoa(generateRandomString(16)) 68 | val xPath = generateRandomString(40) 69 | 70 | // Natijalarni chiqarish 71 | println("X-ATT-DeviceId: $xAttDeviceId") 72 | println("X-Match: $xMatch") 73 | println("X-Path: $xPath") 74 | } 75 | 76 | fun generateSimilarURL(baseURL: String): String { 77 | val url = URL(baseURL) 78 | val generatedPath = "/${generateRandomString(30)}/${generateRandomString(10)}.mpd" 79 | return "${url.protocol}://${url.host}$generatedPath" 80 | } 81 | 82 | fun generateRandomString(length: Int): String { 83 | val characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 84 | return (1..length) 85 | .map { characters.random() } 86 | .joinToString("") 87 | } 88 | 89 | fun btoa(data: String): String { 90 | return Base64.getEncoder().encodeToString(data.toByteArray()) 91 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/uzmovi/JsHunter.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.uzmovi 2 | 3 | import java.util.regex.Matcher 4 | import java.util.regex.Pattern 5 | import kotlin.math.pow 6 | 7 | //author: https://github.com/daarkdemon 8 | class JsHunter(private val hunterJS: String) { 9 | 10 | /** 11 | * Detects whether the javascript is H.U.N.T.E.R coded. 12 | * 13 | * @return true if it's H.U.N.T.E.R coded. 14 | */ 15 | fun detect(): Boolean { 16 | val p = Pattern.compile("eval\\(function\\(h,u,n,t,e,r\\)") 17 | val searchResults = p.matcher(hunterJS) 18 | return searchResults.find() 19 | } 20 | 21 | /** 22 | * Unpack the javascript 23 | * 24 | * @return the javascript unhunt or null. 25 | */ 26 | 27 | fun dehunt(): String? { 28 | try { 29 | val p: Pattern = 30 | Pattern.compile( 31 | """}\("([^"]+)",[^,]+,\s*"([^"]+)",\s*(\d+),\s*(\d+)""", 32 | Pattern.DOTALL 33 | ) 34 | val searchResults: Matcher = p.matcher(hunterJS) 35 | if (searchResults.find() && searchResults.groupCount() == 4) { 36 | val h = searchResults.group(1)!!.toString() 37 | val n = searchResults.group(2)!!.toString() 38 | val t = searchResults.group(3)!!.toInt() 39 | val e = searchResults.group(4)!!.toInt() 40 | return hunter(h, n, t, e) 41 | } 42 | } catch (e: Exception) { 43 | println(e) 44 | } 45 | return null 46 | } 47 | 48 | private fun duf(d: String, e: Int, f: Int = 10): Int { 49 | val str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/" 50 | val g = str.toList() 51 | val h = g.take(e) 52 | val i = g.take(f) 53 | val dList = d.reversed().toList() 54 | var j = 0.0 55 | for ((c, b) in dList.withIndex()) { 56 | if (b in h) { 57 | j += h.indexOf(b) * e.toDouble().pow(c) 58 | } 59 | } 60 | var k = "" 61 | while (j > 0) { 62 | k = i[(j % f).toInt()] + k 63 | j = (j - j % f) / f 64 | } 65 | return k.toIntOrNull() ?: 0 66 | } 67 | 68 | private fun hunter(h: String, n: String, t: Int, e: Int): String { 69 | var result = "" 70 | var i = 0 71 | while (i < h.length) { 72 | var j = 0 73 | var s = "" 74 | while (h[i] != n[e]) { 75 | s += h[i] 76 | i++ 77 | } 78 | while (j < n.length) { 79 | s = s.replace(n[j], j.digitToChar()) 80 | j++ 81 | } 82 | result += (duf(s, e) - t).toChar() 83 | i++ 84 | } 85 | return result 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/uzmovi/JsUnpacker.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.uzmovi 2 | 3 | import java.util.regex.Pattern 4 | import kotlin.math.pow 5 | 6 | // https://github.com/cylonu87/JsUnpacker 7 | class JsUnpacker(packedJS: String?) { 8 | private var packedJS: String? = null 9 | 10 | /** 11 | * Detects whether the javascript is P.A.C.K.E.R. coded. 12 | * 13 | * @return true if it's P.A.C.K.E.R. coded. 14 | */ 15 | fun detect(): Boolean { 16 | val js = packedJS!!.replace(" ", "") 17 | val p = Pattern.compile("eval\\(function\\(p,a,c,k,e,[rd]") 18 | val m = p.matcher(js) 19 | return m.find() 20 | } 21 | 22 | /** 23 | * Unpack the javascript 24 | * 25 | * @return the javascript unpacked or null. 26 | */ 27 | fun unpack(): String? { 28 | val js = packedJS 29 | try { 30 | var p = 31 | Pattern.compile("""\}\s*\('(.*)',\s*(.*?),\s*(\d+),\s*'(.*?)'\.split\('\|'\)""", Pattern.DOTALL) 32 | var m = p.matcher(js) 33 | if (m.find() && m.groupCount() == 4) { 34 | val payload = m.group(1).replace("\\'", "'") 35 | val radixStr = m.group(2) 36 | val countStr = m.group(3) 37 | val symtab = m.group(4).split("\\|".toRegex()).toTypedArray() 38 | var radix = 36 39 | var count = 0 40 | try { 41 | radix = radixStr.toInt() 42 | } catch (e: Exception) { 43 | } 44 | try { 45 | count = countStr.toInt() 46 | } catch (e: Exception) { 47 | } 48 | if (symtab.size != count) { 49 | throw Exception("Unknown p.a.c.k.e.r. encoding") 50 | } 51 | val unbase = Unbase(radix) 52 | p = Pattern.compile("\\b\\w+\\b") 53 | m = p.matcher(payload) 54 | val decoded = StringBuilder(payload) 55 | var replaceOffset = 0 56 | while (m.find()) { 57 | val word = m.group(0) 58 | val x = unbase.unbase(word) 59 | var value: String? = null 60 | if (x < symtab.size && x >= 0) { 61 | value = symtab[x] 62 | } 63 | if (value != null && value.isNotEmpty()) { 64 | decoded.replace(m.start() + replaceOffset, m.end() + replaceOffset, value) 65 | replaceOffset += value.length - word.length 66 | } 67 | } 68 | return decoded.toString() 69 | } 70 | } catch (e: Exception) { 71 | println(e) 72 | } 73 | return null 74 | } 75 | 76 | private inner class Unbase(private val radix: Int) { 77 | private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 78 | private val ALPHABET_95 = 79 | " !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 80 | private var alphabet: String? = null 81 | private var dictionary: HashMap? = null 82 | fun unbase(str: String): Int { 83 | var ret = 0 84 | if (alphabet == null) { 85 | ret = str.toInt(radix) 86 | } else { 87 | val tmp = StringBuilder(str).reverse().toString() 88 | for (i in tmp.indices) { 89 | ret += (radix.toDouble().pow(i.toDouble()) * dictionary!![tmp.substring(i, i + 1)]!!).toInt() 90 | } 91 | } 92 | return ret 93 | } 94 | 95 | init { 96 | if (radix > 36) { 97 | when { 98 | radix < 62 -> { 99 | alphabet = ALPHABET_62.substring(0, radix) 100 | } 101 | radix in 63..94 -> { 102 | alphabet = ALPHABET_95.substring(0, radix) 103 | } 104 | radix == 62 -> { 105 | alphabet = ALPHABET_62 106 | } 107 | radix == 95 -> { 108 | alphabet = ALPHABET_95 109 | } 110 | } 111 | dictionary = HashMap(95) 112 | for (i in 0 until alphabet!!.length) { 113 | dictionary!![alphabet!!.substring(i, i + 1)] = i 114 | } 115 | } 116 | } 117 | } 118 | 119 | /** 120 | * @param packedJS javascript P.A.C.K.E.R. coded. 121 | */ 122 | init { 123 | this.packedJS = packedJS 124 | } 125 | 126 | 127 | companion object { 128 | val c = 129 | listOf( 130 | 0x63, 131 | 0x6f, 132 | 0x6d, 133 | 0x2e, 134 | 0x67, 135 | 0x6f, 136 | 0x6f, 137 | 0x67, 138 | 0x6c, 139 | 0x65, 140 | 0x2e, 141 | 0x61, 142 | 0x6e, 143 | 0x64, 144 | 0x72, 145 | 0x6f, 146 | 0x69, 147 | 0x64, 148 | 0x2e, 149 | 0x67, 150 | 0x6d, 151 | 0x73, 152 | 0x2e, 153 | 0x61, 154 | 0x64, 155 | 0x73, 156 | 0x2e, 157 | 0x4d, 158 | 0x6f, 159 | 0x62, 160 | 0x69, 161 | 0x6c, 162 | 0x65, 163 | 0x41, 164 | 0x64, 165 | 0x73 166 | ) 167 | val z = 168 | listOf( 169 | 0x63, 170 | 0x6f, 171 | 0x6d, 172 | 0x2e, 173 | 0x66, 174 | 0x61, 175 | 0x63, 176 | 0x65, 177 | 0x62, 178 | 0x6f, 179 | 0x6f, 180 | 0x6b, 181 | 0x2e, 182 | 0x61, 183 | 0x64, 184 | 0x73, 185 | 0x2e, 186 | 0x41, 187 | 0x64 188 | ) 189 | 190 | fun String.load(): String? { 191 | return try { 192 | var load = this 193 | 194 | for (q in c.indices) { 195 | if (c[q % 4] > 270) { 196 | load += c[q % 3] 197 | } else { 198 | load += c[q].toChar() 199 | } 200 | } 201 | 202 | Class.forName(load.substring(load.length - c.size, load.length)).name 203 | } catch (_: Exception) { 204 | try { 205 | var f = c[2].toChar().toString() 206 | for (w in z.indices) { 207 | f += z[w].toChar() 208 | } 209 | return Class.forName(f.substring(0b001, f.length)).name 210 | } catch (_: Exception) { 211 | null 212 | } 213 | } 214 | } 215 | } 216 | } -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/uzmovi/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.uzmovi 2 | 3 | import com.azamovhudstc.scarpingtutorial.utils.Color 4 | import com.azamovhudstc.scarpingtutorial.utils.Utils 5 | import com.azamovhudstc.scarpingtutorial.utils.Utils.getJsoup 6 | import com.azamovhudstc.scarpingtutorial.utils.parser 7 | import com.azamovhudstc.scarpingtutorial.utils.printlnColored 8 | import com.azamovhudstc.scarpingtutorial.uzmovi.movie.ParsedMovie 9 | import com.lagradost.nicehttp.Requests 10 | import kotlinx.coroutines.runBlocking 11 | 12 | private val mainUrl = "http://uzmovi.com/" 13 | 14 | class UzmoviBase() { 15 | 16 | suspend fun getM3u8LocationFile(mainUrl: String) { 17 | val requests = Requests(Utils.httpClient, responseParser = parser) 18 | 19 | val data = requests.get( 20 | mainUrl, 21 | 22 | headers = mapOf( 23 | "Cookie" to "_ym_uid=1664171290829008916; \"_pubcid\"=439b1e7c-eab3-4392-a9a7-19b1e53fe9f3; _ym_d=1696009917; __gads=ID=47342de96a689496-224c06c4fbdd00d6:T=1685651803:RT=1699104092:S=ALNI_Mb2ZhtSMyfS5P7PZrwc7eQv5t2WRg; __gpi=UID=00000c2ace922f58:T=1685651803:RT=1699104092:S=ALNI_MZzapclV2KKmb9oTHGcM6MVmi-EBg; comment_name=Foydalanuvchi; _pbjs_userid_consent_data=3524755945110770; _gid=GA1.2.704416453.1705347575; adrcid=ACr-r0sIPrgrh7iAg-Dg5rQ; adrcid_cd=1705407018194; _ym_isad=1; ci_session=rku1vq97bd4cdr8e1piekobjspkeuedl; _ga_XVBVMVW651=GS1.1.1705431478.202.1.1705433781.0.0.0; _ga=GA1.2.504275464.1685651802", 24 | "Connection" to "keep-alive", 25 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/237.84.2.178 Safari/537.36", 26 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", 27 | ), referer = "http://uzmovi.com/", 28 | allowRedirects = true, 29 | verify = true 30 | 31 | ) 32 | 33 | 34 | println(data.url + "index.m3u8") 35 | 36 | 37 | val nextRequestForM3u8 = requests.post( 38 | data.url, headers = mapOf( 39 | "Cookie" to "_ym_uid=1664171290829008916; \"_pubcid\"=439b1e7c-eab3-4392-a9a7-19b1e53fe9f3; _ym_d=1696009917; __gads=ID=47342de96a689496-224c06c4fbdd00d6:T=1685651803:RT=1699104092:S=ALNI_Mb2ZhtSMyfS5P7PZrwc7eQv5t2WRg; __gpi=UID=00000c2ace922f58:T=1685651803:RT=1699104092:S=ALNI_MZzapclV2KKmb9oTHGcM6MVmi-EBg; comment_name=Foydalanuvchi; _pbjs_userid_consent_data=3524755945110770; _gid=GA1.2.704416453.1705347575; adrcid=ACr-r0sIPrgrh7iAg-Dg5rQ; adrcid_cd=1705407018194; _ym_isad=1; ci_session=rku1vq97bd4cdr8e1piekobjspkeuedl; _ga_XVBVMVW651=GS1.1.1705431478.202.1.1705433781.0.0.0; _ga=GA1.2.504275464.1685651802", 40 | "Connection" to "keep-alive", 41 | "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/237.84.2.178 Safari/537.36", 42 | "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", 43 | ), referer = "http://uzmovi.com/", 44 | allowRedirects = true, 45 | verify = true 46 | ) 47 | 48 | 49 | } 50 | 51 | 52 | fun movieDetails(parsedMovie: ParsedMovie) { 53 | val doc = getJsoup(parsedMovie.href) 54 | val tabPaneElement = 55 | doc.select(".tab-pane.fade.in.active").first()// This Code Supported CSS 56 | if (tabPaneElement?.getElementById("online9") != null) { 57 | println(tabPaneElement?.getElementById("online9")) 58 | val scriptContent = tabPaneElement?.select("script")!!.first()!!.html() 59 | val playerConfigStart = scriptContent.indexOf("var playerjsfilm_config = {") 60 | val playerConfigEnd = scriptContent.indexOf("};", playerConfigStart) + 1 61 | val playerConfig = scriptContent.substring(playerConfigStart, playerConfigEnd) 62 | 63 | val fileMatch = Regex("""file:\s*"([^"]+)"""").find(playerConfig) 64 | val titleMatch = Regex("""title:\s*"([^"]+)"""").find(playerConfig) 65 | 66 | val file = fileMatch?.groupValues?.get(1) 67 | val title = titleMatch?.groupValues?.get(1) 68 | 69 | 70 | printlnColored("File: $file" + "" , Color.GREEN) 71 | printlnColored("Title: $title",Color.GREEN) 72 | 73 | 74 | runBlocking { 75 | getM3u8LocationFile(file!!) 76 | } 77 | } else { 78 | val episodeLinks = tabPaneElement!!.select("div#online1 center a") 79 | val epList = arrayListOf() 80 | // Displaying the parsed episode links 81 | episodeLinks.forEachIndexed { index, link -> 82 | val href = link.attr("href") 83 | val text = link.text() 84 | epList.add(href) 85 | println("- $text: $href") 86 | } 87 | 88 | setLink(epList.get(0)) 89 | 90 | } 91 | } 92 | 93 | //http://46.148.234.182/atsspxds/dy8yclFDMVpPMXFWcTJycVVZZlplM3Nkb0YzQUExMUdiRVFTcUkwMnprL28vbFlRWGVRM1I3T0tHZGhwVE0wcA_9pn_9pn/ZVpJNm5kcVRMMjIvUHpsbGtSVzU0YWx6Yi96VGN6bWg3WjF1dndwenhHSVVBRjNnKzNLVnQxb2hnSFB0RzVGQg_5uq_5uq/RGpoRys2NGNVTElzTlBYSVBjK2tTdz09/ 94 | //So this url for Exoplayer if you do`nt know exo Player Just Search hls-player android :D 95 | fun setLink(episodeLink: String) { 96 | val doc = getJsoup(episodeLink) 97 | val tabPaneElement = 98 | doc.select(".tab-pane.fade.in.active").first()// This Code Supported CSS 99 | val scriptContent = tabPaneElement!!.select("div#online1 script").html() 100 | 101 | // Extracting the content of the playerjsserial_config variable 102 | val playerConfigStart = scriptContent.indexOf("var playerjsserial_config = {") 103 | val playerConfigEnd = scriptContent.indexOf("};", playerConfigStart) + 1 104 | val playerConfig = scriptContent.substring(playerConfigStart, playerConfigEnd) 105 | 106 | // Extracting file, title, and poster using regular expressions 107 | val fileMatch = Regex("""file:\s*"([^"]+)""").find(playerConfig) 108 | val titleMatch = Regex("""title:\s*"([^"]+)""").find(playerConfig) 109 | val posterMatch = Regex("""poster:\s*"([^"]+)""").find(playerConfig) 110 | 111 | val file = fileMatch?.groupValues?.get(1) 112 | val title = titleMatch?.groupValues?.get(1) 113 | val poster = posterMatch?.groupValues?.get(1) 114 | 115 | println("File: $file") 116 | println("Title: $title") 117 | println("Poster: $poster") 118 | 119 | runBlocking { 120 | getM3u8LocationFile(convertToHttps(file!!)) 121 | 122 | } 123 | } 124 | 125 | fun convertToHttps(httpString: String): String { 126 | // Check if the string starts with "http://" 127 | if (httpString.startsWith("http://")) { 128 | // Replace "http://" with "https://" 129 | return "https://" + httpString.substring(7) 130 | } else { 131 | // If the string doesn't start with "http://", return it unchanged 132 | return httpString 133 | } 134 | } 135 | 136 | 137 | fun searchMovie(query: String): ArrayList { 138 | val list = arrayListOf() 139 | //this searchUrl is for search in uzmovi 140 | //sample url : http://uzmovi.com/search?q=Sening+Isming 141 | val searchUrl = "$mainUrl/search?q=$query" 142 | val doc = getJsoup(searchUrl) //REQUEST SEARCH 143 | val movieContent = doc.getElementsByClass("shortstory-in categ")//GET Movie LIST 144 | 145 | for (movie in movieContent) { 146 | val movieName = movie.getElementsByClass("short-link").text() //GET Movie NAME 147 | val movieCover = movie.getElementsByTag("img").attr("data-src") // GET Movie COVER 148 | val movieHref = 149 | movie.getElementsByClass("short-link").select("h4.short-link a") 150 | .attr("href") //GET MOVIE DETAIL LINK 151 | list.add(ParsedMovie(movieName, movieHref, movieCover)) 152 | } 153 | 154 | return list 155 | 156 | } 157 | 158 | //sorry my english is not good 159 | //:joy 160 | fun main() { 161 | val list = searchMovie("Wednesday") 162 | 163 | for (movie in list) { 164 | //this loop is for testing 165 | println("-------------------------------") 166 | println(movie.title) 167 | println(movie.href) 168 | println("-------------------------------") 169 | } 170 | println("----------------SELECTED MOVIE ${list.get(0).title}---------------") 171 | movieDetails(list.get(0)) /// Get Movie Details Scarping by href 172 | 173 | // runBlocking { 174 | // getM3u8LocationFile("") 175 | // } 176 | } 177 | } 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /app/src/main/java/com/azamovhudstc/scarpingtutorial/uzmovi/movie/ParsedMovie.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial.uzmovi.movie 2 | 3 | data class ParsedMovie(val title: String, val href: String, val image: String) -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ScarpingTutorial 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/test/java/com/azamovhudstc/scarpingtutorial/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.scarpingtutorial 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'com.android.application' version '7.2.2' apply false 4 | id 'com.android.library' version '7.2.2' apply false 5 | id 'org.jetbrains.kotlin.android' version '1.7.10' apply false 6 | } 7 | // 8 | task clean(type: Delete) { 9 | delete rootProject.buildDir 10 | } -------------------------------------------------------------------------------- /cacheDir/http_cache/2b1224a03a7535f0c5970fad62e68a04.0: -------------------------------------------------------------------------------- 1 | https://swapi.dev/api/planets/1/ 2 | GET 3 | 0 4 | HTTP/1.1 200 5 | 11 6 | server: nginx/1.16.1 7 | date: Fri, 12 Jan 2024 19:35:41 GMT 8 | content-type: application/json 9 | vary: Accept, Cookie 10 | x-frame-options: SAMEORIGIN 11 | etag: "df2ecd17a7953452d4000883f4f97b77" 12 | allow: GET, HEAD, OPTIONS 13 | strict-transport-security: max-age=15768000 14 | Cache-Control: max-stale=2147483647, only-if-cached 15 | OkHttp-Sent-Millis: 1705088142269 16 | OkHttp-Received-Millis: 1705088143308 17 | 18 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 19 | 3 20 | MIIE4DCCA8igAwIBAgISBN+9/rDpU39bBuT1vaAU1C32MA0GCSqGSIb3DQEBCwUAMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJSMzAeFw0yMzEwMjgwNzMzMTZaFw0yNDAxMjYwNzMzMTVaMBQxEjAQBgNVBAMTCXN3YXBpLmRldjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMlm9KCavSk1y/pjFPDc7zGx3jPdbQikvWHbRIzairAAevJZHKVOrA+1zt+rJXkfVsNMGkE0nDIMCG7Y7PfErdfsCP7KnIaEnAs2Q5FBE5Z+wW+i8UH3wtXP1d9toQi7XX5jNZ30GrGF50OHtNQuaw5usveEpLx7UnIt2n9pG+g6Z9W0Q6pUAtcou3FiG7nHl8OPLrSPgSjswdueK6qr0nsrKYEWiAsKCskviCyesNZvctI7BgQwNgOqxab9yRBZZCEwRI0qwGeykO1baPvbgaEDLbOXIlY/GHkVcsaxV0YUqqEstNAkCOlr30/uLm+sJ1cv4gQNdwri1gSfZbKqCSECAwEAAaOCAgwwggIIMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUKgnJuAHq2liyaD+lPZMK3qv2p98wHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8wFAYDVR0RBA0wC4IJc3dhcGkuZGV2MBMGA1UdIAQMMAowCAYGZ4EMAQIBMIIBBQYKKwYBBAHWeQIEAgSB9gSB8wDxAHYA2ra/az+1tiKfm8K7XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGLdWqEjQAABAMARzBFAiEAmCNQfUnIMH7+jiMTmb04lxKfz22na+50hlN4C83zRQgCIBwptKfJS0d8dOS5xCNNIT26t8KVUJv2A0Tcqwb2Zms/AHcAO1N3dT4tuYBOizBbBv5AO2fYT8P0x70ADS1yb+H61BcAAAGLdWqEhAAABAMASDBGAiEAsJF2hUy8ViYHjpqqOTd0ow7yXvUuqGVqUQ0jJaV/dukCIQCkotupgBnSeDol/p3D/OGze0i7aaDRTChbRf5gDy9DVzANBgkqhkiG9w0BAQsFAAOCAQEAJf9zqHxXPIDHPSG2Nn6CocjsU0FpXddGkIXzTFGNdmUNFMYoqKaOLmS4qogfQh48BNjuwnToLFPIPcPUhxPqCnO09HnbLQGK25v5KNm8KgTzqCt1DamQfeUk28FRzeLVxuljqKPa3BFx12RvasOJSiV005ps9VvgB4hbr0RNaRbtv2/BJwCjpUGKzVetUhPrj5DBfCR4Rr2Csz7aPWVbJAfp0xw0Fv1/mGYTLBdNyU7aosz7BBhqLRrCa5KgoXxp73jMfESfuPMZJN+CVo3Rq7k3degDoeQbbVztRlmEMGJgT+sAny4HtDBUYFg6vZYetvv9iuqITWawzGJ3fLTDtg== 21 | MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAwWhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3MgRW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cPR5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdxsxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8ZutmNHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxgZ3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6WPTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wlikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQzCkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BImlJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1OyK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90IdshCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6ZvMldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqXnLRbwHOoq7hHwg== 22 | MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZLubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= 23 | 0 24 | TLSv1.2 25 | -------------------------------------------------------------------------------- /cacheDir/http_cache/2b1224a03a7535f0c5970fad62e68a04.1: -------------------------------------------------------------------------------- 1 | {"name":"Tatooine","rotation_period":"23","orbital_period":"304","diameter":"10465","climate":"arid","gravity":"1 standard","terrain":"desert","surface_water":"1","population":"200000","residents":["https://swapi.dev/api/people/1/","https://swapi.dev/api/people/2/","https://swapi.dev/api/people/4/","https://swapi.dev/api/people/6/","https://swapi.dev/api/people/7/","https://swapi.dev/api/people/8/","https://swapi.dev/api/people/9/","https://swapi.dev/api/people/11/","https://swapi.dev/api/people/43/","https://swapi.dev/api/people/62/"],"films":["https://swapi.dev/api/films/1/","https://swapi.dev/api/films/3/","https://swapi.dev/api/films/4/","https://swapi.dev/api/films/5/","https://swapi.dev/api/films/6/"],"created":"2014-12-09T13:50:49.641000Z","edited":"2014-12-20T20:58:18.411000Z","url":"https://swapi.dev/api/planets/1/"} -------------------------------------------------------------------------------- /cacheDir/http_cache/5e4087c3189675fda2f4a1d7f58e56dd.0: -------------------------------------------------------------------------------- 1 | http://uzmovi.com/ 2 | GET 3 | 0 4 | HTTP/1.1 200 OK 5 | 10 6 | Date: Fri, 12 Jan 2024 19:38:54 GMT 7 | Content-Type: text/html; charset=UTF-8 8 | Transfer-Encoding: chunked 9 | Connection: keep-alive 10 | Set-Cookie: ci_session=623bnsni5nur33hthd4d3ue3ec6kj1dm; expires=Fri, 12-Jan-2024 20:38:54 GMT; Max-Age=3600; path=/; HttpOnly 11 | Expires: Thu, 19 Nov 1981 08:52:00 GMT 12 | Content-Encoding: gzip 13 | Cache-Control: max-stale=2147483647, only-if-cached 14 | OkHttp-Sent-Millis: 1705088336650 15 | OkHttp-Received-Millis: 1705088336791 16 | -------------------------------------------------------------------------------- /cacheDir/http_cache/5e4087c3189675fda2f4a1d7f58e56dd.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/cacheDir/http_cache/5e4087c3189675fda2f4a1d7f58e56dd.1 -------------------------------------------------------------------------------- /cacheDir/http_cache/9cb50cb1271552bead409a9b12e28ccc.0: -------------------------------------------------------------------------------- 1 | https://github.com/professorDeveloper/Kitsune-App 2 | GET 3 | 1 4 | Accept-Encoding: gzip 5 | HTTP/1.1 200 6 | 20 7 | server: GitHub.com 8 | date: Fri, 12 Jan 2024 19:34:54 GMT 9 | content-type: text/html; charset=utf-8 10 | vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Encoding, Accept, X-Requested-With 11 | etag: W/"a22125d58061887329ac8f24775b6bb6" 12 | strict-transport-security: max-age=31536000; includeSubdomains; preload 13 | x-frame-options: deny 14 | x-content-type-options: nosniff 15 | x-xss-protection: 0 16 | referrer-policy: no-referrer-when-downgrade 17 | content-security-policy: default-src 'none'; base-uri 'self'; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events api.githubcopilot.com objects-origin.githubusercontent.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com support.github.com; img-src 'self' data: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/ 18 | content-encoding: gzip 19 | set-cookie: _gh_sess=C8BlEyQPavT%2BZriooFUv5wULipA%2Fut1Y6ukwZc5s9RCm7AOshihk%2BTxKDhbo3UAcxqKxwBlAjBKK54jBeTgz9ju2vWCu0zxiM4PUWTw6p4ev1wxQgaqbOzfKsizQm53oVzpXe%2FstZNdw2wdUlicjoURNFQbS8Y%2FPBoTZm2PbEqlKXw%2FS2s5diN2xZizagImuZCWKGBtn2xGUq2UyPlim7SAPI%2BObUg47xWxdxy9tsCJ9H89Io2w9Z4pfwgAg8fueFgdVxS%2FW2QB7Jr6zFcQsCA%3D%3D--ysLAWoAkHKQ5W3fg--88TOUuDrd5K2W%2BLnc%2FxUWg%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax 20 | set-cookie: _octo=GH1.1.1563333412.1705088094; Path=/; Domain=github.com; Expires=Sun, 12 Jan 2025 19:34:54 GMT; Secure; SameSite=Lax 21 | set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Sun, 12 Jan 2025 19:34:54 GMT; HttpOnly; Secure; SameSite=Lax 22 | accept-ranges: bytes 23 | x-github-request-id: 448F:1D1903:7A4DB9:7BAB2A:65A1945D 24 | Cache-Control: max-stale=2147483647, only-if-cached 25 | OkHttp-Sent-Millis: 1705088095935 26 | OkHttp-Received-Millis: 1705088096670 27 | 28 | TLS_AES_128_GCM_SHA256 29 | 3 30 | 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 33 | 0 34 | TLSv1.3 35 | -------------------------------------------------------------------------------- /cacheDir/http_cache/9cb50cb1271552bead409a9b12e28ccc.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/cacheDir/http_cache/9cb50cb1271552bead409a9b12e28ccc.1 -------------------------------------------------------------------------------- /cacheDir/http_cache/eb3f92a87779a0e3bb56097846dd3a13.0: -------------------------------------------------------------------------------- 1 | https://uzmovi.com/ 2 | GET 3 | 0 4 | HTTP/1.1 301 Moved Permanently 5 | 8 6 | Date: Fri, 12 Jan 2024 19:38:54 GMT 7 | Content-Type: text/html 8 | Content-Length: 162 9 | Connection: keep-alive 10 | Location: http://uzmovi.com/ 11 | Cache-Control: max-stale=2147483647, only-if-cached 12 | OkHttp-Sent-Millis: 1705088336272 13 | OkHttp-Received-Millis: 1705088336507 14 | 15 | TLS_AES_128_GCM_SHA256 16 | 3 17 | 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 20 | 0 21 | TLSv1.3 22 | -------------------------------------------------------------------------------- /cacheDir/http_cache/eb3f92a87779a0e3bb56097846dd3a13.1: -------------------------------------------------------------------------------- 1 | 2 | 301 Moved Permanently 3 | 4 |

301 Moved Permanently

5 |
nginx
6 | 7 | 8 | -------------------------------------------------------------------------------- /cacheDir/http_cache/journal: -------------------------------------------------------------------------------- 1 | libcore.io.DiskLruCache 2 | 1 3 | 201105 4 | 2 5 | 6 | DIRTY 9cb50cb1271552bead409a9b12e28ccc 7 | CLEAN 9cb50cb1271552bead409a9b12e28ccc 8413 38444 8 | DIRTY 008ec4453ff31513f43893cba7aa31c8 9 | DIRTY 2b1224a03a7535f0c5970fad62e68a04 10 | CLEAN 2b1224a03a7535f0c5970fad62e68a04 5754 837 11 | DIRTY eb3f92a87779a0e3bb56097846dd3a13 12 | CLEAN eb3f92a87779a0e3bb56097846dd3a13 5646 162 13 | DIRTY 5e4087c3189675fda2f4a1d7f58e56dd 14 | CLEAN 5e4087c3189675fda2f4a1d7f58e56dd 482 23841 15 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jan 13 00:15:26 UZT 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | jcenter() 7 | maven { url 'https://jitpack.io' } 8 | } 9 | } 10 | dependencyResolutionManagement { 11 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 12 | repositories { 13 | google() 14 | mavenCentral() 15 | jcenter() 16 | maven { url 'https://jitpack.io' } 17 | } 18 | } 19 | rootProject.name = "ScarpingTutorial" 20 | include ':app' 21 | include ':tonconsole' 22 | -------------------------------------------------------------------------------- /tonconsole/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /tonconsole/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | android { 7 | namespace 'com.azamovhudstc.tonconsole' 8 | compileSdk 34 9 | 10 | defaultConfig { 11 | minSdk 24 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles "consumer-rules.pro" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | kotlinOptions { 28 | jvmTarget = '1.8' 29 | } 30 | } 31 | 32 | dependencies { 33 | 34 | implementation 'androidx.core:core-ktx:1.13.1' 35 | implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0') 36 | implementation 'androidx.appcompat:appcompat:1.7.0' 37 | implementation 'com.google.android.material:material:1.12.0' 38 | testImplementation 'junit:junit:4.13.2' 39 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 40 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 41 | implementation 'com.github.Blatzar:NiceHttp:0.4.4'// So wee Need this Libraries 42 | api "com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1" 43 | implementation 'com.google.code.gson:gson:2.10.1' 44 | implementation 'com.squareup.okhttp3:okhttp:3.5.0' 45 | implementation 'org.java-websocket:Java-WebSocket:1.4.0' 46 | 47 | implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1" 48 | implementation 'io.apisense:rhino-android:1.0' 49 | 50 | } -------------------------------------------------------------------------------- /tonconsole/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/professorDeveloper/Scraping-Tutorial/d23f8e8b0fca550483314093c02cc828cbd371d0/tonconsole/consumer-rules.pro -------------------------------------------------------------------------------- /tonconsole/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /tonconsole/src/androidTest/java/com/azamovhudstc/tonconsole/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.tonconsole 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.azamovhudstc.tonconsole.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /tonconsole/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /tonconsole/src/main/java/com/azamovhudstc/tonconsole/Main.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.tonconsole 2 | 3 | class Main { 4 | 5 | //Hellooo 6 | } -------------------------------------------------------------------------------- /tonconsole/src/test/java/com/azamovhudstc/tonconsole/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.azamovhudstc.tonconsole 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } --------------------------------------------------------------------------------