Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Commit cdd922a

Browse files
authored
add 2ix2 extension (#6)
1 parent c5dae82 commit cdd922a

File tree

8 files changed

+206
-0
lines changed

8 files changed

+206
-0
lines changed

src/de/2ix2/AndroidManifest.xml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest package="eu.kanade.tachiyomi.animeextension" />

src/de/2ix2/build.gradle

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apply plugin: 'com.android.application'
2+
apply plugin: 'kotlin-android'
3+
apply plugin: 'kotlinx-serialization'
4+
5+
ext {
6+
extName = '2ix2'
7+
pkgNameSuffix = 'de.twoixtwo'
8+
extClass = '.twoixtwo'
9+
extVersionCode = 1
10+
libVersion = '13'
11+
}
12+
13+
apply from: "$rootDir/common.gradle"
9.72 KB
Loading
4.85 KB
Loading
15.9 KB
Loading
31.6 KB
Loading
50.7 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package eu.kanade.tachiyomi.animeextension.de.twoixtwo
2+
3+
import android.app.Application
4+
import android.content.SharedPreferences
5+
import androidx.preference.ListPreference
6+
import androidx.preference.MultiSelectListPreference
7+
import androidx.preference.PreferenceScreen
8+
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
9+
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
10+
import eu.kanade.tachiyomi.animesource.model.SAnime
11+
import eu.kanade.tachiyomi.animesource.model.SEpisode
12+
import eu.kanade.tachiyomi.animesource.model.Video
13+
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
14+
import eu.kanade.tachiyomi.network.GET
15+
import eu.kanade.tachiyomi.util.asJsoup
16+
import okhttp3.OkHttpClient
17+
import okhttp3.Request
18+
import okhttp3.Response
19+
import org.jsoup.nodes.Document
20+
import org.jsoup.nodes.Element
21+
import uy.kohesive.injekt.Injekt
22+
import uy.kohesive.injekt.api.get
23+
import java.lang.Exception
24+
25+
class twoixtwo : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
26+
27+
override val name = "2ix2"
28+
29+
override val baseUrl = "https://www.2ix2.com"
30+
31+
override val lang = "de"
32+
33+
override val supportsLatest = false
34+
35+
override val client: OkHttpClient = network.cloudflareClient
36+
37+
private val preferences: SharedPreferences by lazy {
38+
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
39+
}
40+
41+
override fun popularAnimeSelector(): String = "div.filmcontent div.moviefilm"
42+
43+
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/meist-gelikte-tv-sender/")
44+
45+
override fun popularAnimeFromElement(element: Element): SAnime {
46+
val anime = SAnime.create()
47+
anime.setUrlWithoutDomain(element.select("div.movief a").attr("href"))
48+
anime.thumbnail_url = element.select("a img").attr("src")
49+
anime.title = element.select("div.movief a").text()
50+
return anime
51+
}
52+
53+
override fun popularAnimeNextPageSelector(): String? = null
54+
55+
// episodes
56+
57+
override fun episodeListSelector() = throw Exception("not used")
58+
59+
override fun episodeListParse(response: Response): List<SEpisode> {
60+
val document = response.asJsoup()
61+
val episodeList = mutableListOf<SEpisode>()
62+
val episode = SEpisode.create()
63+
episode.name = document.select("div.filmaltiaciklama h2").text()
64+
.substringBefore(" Live")
65+
episode.episode_number = 1F
66+
episode.setUrlWithoutDomain(document.select("link[rel=canonical]").attr("href"))
67+
episodeList.add(episode)
68+
return episodeList.reversed()
69+
}
70+
71+
override fun episodeFromElement(element: Element): SEpisode = throw Exception("not used")
72+
73+
// Video Extractor
74+
75+
override fun videoListParse(response: Response): List<Video> {
76+
val document = response.asJsoup()
77+
return videosFromElement(document)
78+
}
79+
80+
private fun videosFromElement(document: Document): List<Video> {
81+
val videoList = mutableListOf<Video>()
82+
val script = document.select("div.filmicerik script[type]").toString()
83+
val quality = "LIVE"
84+
val videoUrl = script.substringAfter("file: \"").substringBefore("\",")
85+
videoList.add(Video(videoUrl, quality, videoUrl))
86+
return videoList
87+
}
88+
89+
override fun List<Video>.sort(): List<Video> {
90+
val hoster = preferences.getString("preferred_hoster", "Voe")
91+
val hosterList = mutableListOf<Video>()
92+
val otherList = mutableListOf<Video>()
93+
if (hoster != null) {
94+
for (video in this) {
95+
if (video.url.contains(hoster)) {
96+
hosterList.add(video)
97+
} else {
98+
otherList.add(video)
99+
}
100+
}
101+
} else otherList += this
102+
val newList = mutableListOf<Video>()
103+
var preferred = 0
104+
for (video in hosterList) {
105+
if (hoster?.let { video.quality.contains(it) } == true) {
106+
newList.add(preferred, video)
107+
preferred++
108+
} else newList.add(video)
109+
}
110+
for (video in otherList) {
111+
if (hoster?.let { video.quality.contains(it) } == true) {
112+
newList.add(preferred, video)
113+
preferred++
114+
} else newList.add(video)
115+
}
116+
return newList
117+
}
118+
119+
override fun videoListSelector() = throw Exception("not used")
120+
121+
override fun videoFromElement(element: Element) = throw Exception("not used")
122+
123+
override fun videoUrlParse(document: Document) = throw Exception("not used")
124+
125+
// Search
126+
127+
override fun searchAnimeFromElement(element: Element): SAnime = popularAnimeFromElement(element)
128+
129+
override fun searchAnimeNextPageSelector(): String? = null
130+
131+
override fun searchAnimeSelector(): String = popularAnimeSelector()
132+
133+
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = GET("$baseUrl/?s=$query")
134+
135+
// Details
136+
137+
override fun animeDetailsParse(document: Document): SAnime {
138+
val anime = SAnime.create()
139+
anime.thumbnail_url = document.select("div.filmaltiimg img").attr("src")
140+
anime.title = document.select("div.filmaltiaciklama h2").text()
141+
.substringBefore(" Live")
142+
// anime.genre = document.select("#detail-content-list > li:nth-child(2) > span").joinToString(", ") { it.text() }
143+
// anime.description = document.select("#detail-content-list > li:nth-child(3) > span").text()
144+
// anime.author = document.select("#detail-content-list > li:nth-child(4) > span").joinToString(", ") { it.text() }
145+
// anime.status = SAnime.COMPLETED
146+
return anime
147+
}
148+
149+
// Latest
150+
151+
override fun latestUpdatesNextPageSelector(): String = throw Exception("Not used")
152+
153+
override fun latestUpdatesFromElement(element: Element): SAnime = throw Exception("Not used")
154+
155+
override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not used")
156+
157+
override fun latestUpdatesSelector(): String = throw Exception("Not used")
158+
159+
// Preferences
160+
161+
override fun setupPreferenceScreen(screen: PreferenceScreen) {
162+
val hosterPref = ListPreference(screen.context).apply {
163+
key = "preferred_hoster"
164+
title = "Standard-Hoster"
165+
entries = arrayOf("Voe", "Streamtape", "Evoload")
166+
entryValues = arrayOf("https://voe.sx", "https://streamtape.com", "https://evoload.io")
167+
setDefaultValue("https://voe.sx")
168+
summary = "%s"
169+
170+
setOnPreferenceChangeListener { _, newValue ->
171+
val selected = newValue as String
172+
val index = findIndexOfValue(selected)
173+
val entry = entryValues[index] as String
174+
preferences.edit().putString(key, entry).commit()
175+
}
176+
}
177+
val subSelection = MultiSelectListPreference(screen.context).apply {
178+
key = "hoster_selection"
179+
title = "Hoster auswählen"
180+
entries = arrayOf("Voe", "Streamtape", "Evoload")
181+
entryValues = arrayOf("voe", "stape", "evo")
182+
setDefaultValue(setOf("voe", "stape", "evo"))
183+
184+
setOnPreferenceChangeListener { _, newValue ->
185+
preferences.edit().putStringSet(key, newValue as Set<String>).commit()
186+
}
187+
}
188+
screen.addPreference(hosterPref)
189+
screen.addPreference(subSelection)
190+
}
191+
}

0 commit comments

Comments
 (0)