├── .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 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
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 | 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
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 | }
--------------------------------------------------------------------------------