Skip to content

Commit c3f142a

Browse files
committed
[release] 1.0
1 parent 078441d commit c3f142a

File tree

80 files changed

+4475
-27
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+4475
-27
lines changed

.github/workflows/release.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: release
2+
on:
3+
push:
4+
tags:
5+
- '**'
6+
workflow_dispatch:
7+
jobs:
8+
build-and-release:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout
12+
uses: actions/[email protected]
13+
- name: Setup Java JDK
14+
uses: actions/[email protected]
15+
with:
16+
java-version: 17
17+
- name: Build
18+
run: |
19+
chmod +x ./gradlew
20+
./gradlew :app:assemble
21+
- name: sign-apk
22+
uses: r0adkll/sign-android-release@v1
23+
with:
24+
releaseDirectory: app/build/outputs/apk/release
25+
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
26+
alias: ${{ secrets.KEY_ALIAS }}
27+
keyStorePassword: ${{ secrets.KEY_STORE_PWD }}
28+
keyPassword: ${{ secrets.KEY_PWD }}
29+
- name: rename-apk
30+
run: |
31+
mv app/build/outputs/apk/release/extension-app-release-unsigned-signed.apk extension-app-${{ github.ref_name }}.apk
32+
- name: Release
33+
run: |
34+
gh release create -d ${{ github.ref_name }} extension-app-${{ github.ref_name }}.apk
35+
env:
36+
GITHUB_TOKEN: ${{ secrets.TOKEN }}

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
<img alt="license" src="https://img.shields.io/github/license/easybangumiorg/EasyBangumiExtension" />
66
</p>
77

8-
本项目为纯纯看番拓展二次开发模板使用。
8+
本仓库内容均来自互联网投稿,为了代码安全性只收录提交到纯纯看番官方的代码,并由官方编译。
9+
10+
如果使用其他的源,用户需要自己甄别插件安全性,纯纯看番官方无法保证这些插件是否安全。
11+
12+
如果本仓库内容您认为侵犯了你的权益,请提交issue联系我们删除。
913

1014
纯纯看番本体:[https://github.com/easybangumiorg/EasyBangumi](https://github.com/easybangumiorg/EasyBangumi)
11-
12-
13-
开发文档:~~还在写~~
15+

extension-app/build.gradle.kts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ plugins {
44
}
55

66
// 包名
7-
val packageName = ""
7+
val packageName = "org.easybangumi.extension"
88

99
// 库版本,目前 5.0.3 支持的库版本为 3 到 5
10-
val extensionLibVersion = 5
10+
val extensionLibVersion = 6
1111

1212
android {
1313
namespace = packageName
@@ -20,7 +20,7 @@ android {
2020
versionCode = 1
2121
versionName = "1.0"
2222

23-
manifestPlaceholders.put("extensionLibVersion", 4)
23+
manifestPlaceholders.put("extensionLibVersion", extensionLibVersion)
2424

2525
}
2626

@@ -45,5 +45,6 @@ android {
4545

4646

4747
dependencies {
48+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
4849
compileOnly("io.github.easybangumiorg:extension-api:1.${extensionLibVersion}-SNAPSHOT")
4950
}

extension-app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<application
88
android:allowBackup="true"
99
android:icon="@mipmap/app_logo"
10-
android:label="[APP 名称]"
10+
android:label="纯纯看番社区插件"
1111
android:supportsRtl="true">
1212

1313

@@ -19,7 +19,7 @@
1919
<!--source-->
2020
<meta-data
2121
android:name="easybangumi.extension.source"
22-
android:value="com.heyanle.easybangumi_extension.EasySourceFactory"/>
22+
android:value="org.easybangumi.extension.EasySourceFactory"/>
2323

2424
<!--为了让本体能找到需要加-->
2525
<activity android:name="com.heyanle.extension_api.NoneActivity"

extension-app/src/main/java/com/heyanle/easybangumi_extension/EasySourceFactory.kt

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package com.heyanle.easybangumi_extension.anfun
2+
3+
import android.util.Log
4+
import com.heyanle.easybangumi4.source_api.ParserException
5+
import com.heyanle.easybangumi4.source_api.SourceResult
6+
import com.heyanle.easybangumi4.source_api.component.ComponentWrapper
7+
import com.heyanle.easybangumi4.source_api.component.detailed.DetailedComponent
8+
import com.heyanle.easybangumi4.source_api.component.play.PlayComponent
9+
import com.heyanle.easybangumi4.source_api.component.update.UpdateComponent
10+
import com.heyanle.easybangumi4.source_api.entity.Cartoon
11+
import com.heyanle.easybangumi4.source_api.entity.CartoonImpl
12+
import com.heyanle.easybangumi4.source_api.entity.CartoonSummary
13+
import com.heyanle.easybangumi4.source_api.entity.Episode
14+
import com.heyanle.easybangumi4.source_api.entity.PlayLine
15+
import com.heyanle.easybangumi4.source_api.entity.PlayerInfo
16+
import com.heyanle.easybangumi4.source_api.utils.api.OkhttpHelper
17+
import com.heyanle.easybangumi4.source_api.utils.api.WebViewHelper
18+
import com.heyanle.easybangumi4.source_api.utils.core.SourceUtils
19+
import com.heyanle.easybangumi4.source_api.utils.core.network.GET
20+
import com.heyanle.easybangumi4.source_api.withResult
21+
import kotlinx.coroutines.Dispatchers
22+
import kotlinx.coroutines.withTimeoutOrNull
23+
import org.jsoup.Jsoup
24+
import org.jsoup.nodes.Document
25+
26+
/**
27+
* Created by heyanle on 2024/1/29.
28+
* https://github.com/heyanLE
29+
*/
30+
class AnfunDetailedComponent(
31+
private val okhttpHelper: OkhttpHelper,
32+
private val webViewHelper: WebViewHelper
33+
): ComponentWrapper(), DetailedComponent, UpdateComponent, PlayComponent {
34+
35+
36+
override suspend fun getDetailed(summary: CartoonSummary): SourceResult<Cartoon> {
37+
return withResult(Dispatchers.IO) {
38+
detailed(getDoc(summary), summary)
39+
}
40+
}
41+
42+
override suspend fun getPlayLine(summary: CartoonSummary): SourceResult<List<PlayLine>> {
43+
return withResult(Dispatchers.IO) {
44+
playLine(getDoc(summary), summary)
45+
}
46+
}
47+
48+
override suspend fun getAll(summary: CartoonSummary): SourceResult<Pair<Cartoon, List<PlayLine>>> {
49+
return withResult(Dispatchers.IO) {
50+
detailed(getDoc(summary), summary) to playLine(getDoc(summary), summary)
51+
}
52+
}
53+
54+
override suspend fun update(
55+
cartoon: Cartoon,
56+
oldPlayLine: List<PlayLine>
57+
): SourceResult<Cartoon> {
58+
return withResult(Dispatchers.IO) {
59+
60+
when (val n = getAll(CartoonSummary(cartoon.id, cartoon.source))) {
61+
is SourceResult.Complete -> {
62+
n.data.first.apply {
63+
64+
val newPlayLine = n.data.second
65+
66+
if (oldPlayLine.size != newPlayLine.size) {
67+
isUpdate = true
68+
} else {
69+
isUpdate = false
70+
for (i in oldPlayLine.indices) {
71+
if (oldPlayLine[i].episode.size != newPlayLine[i].episode.size) {
72+
isUpdate = true
73+
break
74+
}
75+
}
76+
}
77+
}
78+
}
79+
is SourceResult.Error -> {
80+
throw n.throwable
81+
}
82+
}
83+
}
84+
}
85+
86+
private fun getDoc(summary: CartoonSummary): Document {
87+
val d = okhttpHelper.cloudflareWebViewClient.newCall(GET(SourceUtils.urlParser(AnfunSource.ROOT_URL, "/anime/${summary.id}.html")))
88+
.execute().body?.string() ?: throw NullPointerException()
89+
return Jsoup.parse(d)
90+
}
91+
private fun playLine(document: Document, summary: CartoonSummary): List<PlayLine> {
92+
Log.e("TAG","------->>>>>>>playLine")
93+
val res = arrayListOf<PlayLine>()
94+
val module = document.select(".hl-play-source").first() ?: return res
95+
val playNameList = module.select(".hl-plays-wrap").first()?.select("a") ?: return res
96+
val playEpisodeList = module.select(".hl-tabs-box")
97+
for (index in 0..playNameList.size) {
98+
val playName = playNameList.getOrNull(index)?.text()
99+
val playEpisode = playEpisodeList.getOrNull(index)
100+
if (playName != null && playEpisode != null) {
101+
val results = playEpisode.select("li").select("a")
102+
val es = arrayListOf<Episode>()
103+
104+
for (i in results.indices) {
105+
es.add(Episode((i+1).toString(), results[i].text(), i)) // title
106+
107+
}
108+
val playLine = PlayLine(
109+
id = (index + 1).toString(),
110+
label = playName,
111+
episode = es
112+
)
113+
res.add(playLine)
114+
}
115+
}
116+
return res
117+
}
118+
119+
override suspend fun getPlayInfo(
120+
summary: CartoonSummary,
121+
playLine: PlayLine,
122+
episode: Episode
123+
): SourceResult<PlayerInfo> {
124+
Log.e("TAG","------->>>>>>>开始播放")
125+
return withResult(Dispatchers.IO) {
126+
127+
// Log.e("TAG","${playUrlTemp[playLine.id.toInt()]}") // [/play/632-1-1.html]
128+
val url = SourceUtils.urlParser(AnfunSource.ROOT_URL, "/play/${summary.id}-${playLine.id}-${episode.id}")
129+
// Log.e("TAG", url) // https://www.anfuns.cc/play/632-1-1.html
130+
var videoUrl = webViewHelper.interceptResource(
131+
url, regex = "https://www.anfuns.cc/vapi/AIRA/mui.php?.*"
132+
)
133+
Log.e("TAG", "地址:$videoUrl")
134+
if (videoUrl.isNotEmpty()) {
135+
when {
136+
videoUrl.contains(".m3u8&") -> videoUrl = videoUrl.substringAfter("url=")
137+
.substringBefore("&")
138+
videoUrl.contains(".mp4") -> videoUrl = videoUrl.substringAfter("url=")
139+
.substringBefore("&next=")
140+
}
141+
Log.e("TAG", "解析后url:$videoUrl")
142+
if (videoUrl.indexOf(".mp4") != -1){
143+
PlayerInfo(
144+
decodeType = PlayerInfo.DECODE_TYPE_OTHER,
145+
uri = SourceUtils.urlParser(AnfunSource.ROOT_URL,videoUrl)
146+
)
147+
}else{
148+
PlayerInfo(
149+
decodeType = PlayerInfo.DECODE_TYPE_HLS,
150+
uri = SourceUtils.urlParser(AnfunSource.ROOT_URL,videoUrl)
151+
)
152+
}
153+
}else{
154+
throw ParserException("Unknown")
155+
}
156+
}
157+
}
158+
159+
private fun detailed(document: Document, summary: CartoonSummary): Cartoon {
160+
Log.e("TAG","------->>>>>>>detailed")
161+
162+
var desc = ""
163+
var update = 0
164+
var status = 0
165+
166+
val cover = document.select(".hl-dc-pic").select("span").attr("data-original")
167+
val title = document.select(".hl-dc-headwrap").select(".hl-dc-title").text()
168+
//document.select(".hl-dc-headwrap").select(".hl-dc-sub").text()
169+
// 更新状况
170+
val upStateItems = document.select(".hl-dc-content")
171+
.select(".hl-vod-data").select(".hl-full-box").select("ul").select("li")
172+
for (upStateEm in upStateItems){
173+
val t = upStateEm.text()
174+
when{
175+
t.contains("状态:") -> {
176+
status =
177+
if (t.startsWith("连载")) Cartoon.STATUS_ONGOING
178+
else if (t.startsWith("")) Cartoon.STATUS_COMPLETED
179+
else Cartoon.STATUS_UNKNOWN
180+
val isTheater = title.contains("剧场版")
181+
update =
182+
if (isTheater) {
183+
if (status == Cartoon.STATUS_COMPLETED) {
184+
Cartoon.UPDATE_STRATEGY_NEVER
185+
} else {
186+
Cartoon.UPDATE_STRATEGY_ONLY_STRICT
187+
}
188+
} else {
189+
if (status == Cartoon.STATUS_COMPLETED) {
190+
Cartoon.UPDATE_STRATEGY_ONLY_STRICT
191+
} else {
192+
Cartoon.UPDATE_STRATEGY_ALWAYS
193+
}
194+
}
195+
}
196+
t.contains("简介:") -> desc = t
197+
}
198+
}
199+
200+
return CartoonImpl(
201+
id = summary.id,
202+
url = SourceUtils.urlParser(AnfunSource.ROOT_URL, "/anime/${summary.id}.html"),
203+
source = summary.source,
204+
205+
title = title,
206+
coverUrl = cover,
207+
208+
intro = "",
209+
description = desc,
210+
211+
genre = "",
212+
213+
status = status,
214+
updateStrategy = update,
215+
)
216+
}
217+
218+
219+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.heyanle.easybangumi_extension.anfun
2+
3+
import com.heyanle.easybangumi4.source_api.component.ComponentWrapper
4+
import com.heyanle.easybangumi4.source_api.entity.CartoonCover
5+
import com.heyanle.easybangumi4.source_api.entity.CartoonCoverImpl
6+
import com.heyanle.easybangumi4.source_api.utils.api.OkhttpHelper
7+
import com.heyanle.easybangumi4.source_api.utils.core.SourceUtils
8+
import org.jsoup.select.Elements
9+
10+
/**
11+
* Created by heyanle on 2024/1/28.
12+
* https://github.com/heyanLE
13+
*/
14+
class AnfunListComponent(
15+
private val okhttpHelper: OkhttpHelper,
16+
) : ComponentWrapper() {
17+
18+
companion object {
19+
const val ROOT_URL = "https://www.anfuns.cc"
20+
}
21+
22+
suspend fun listPage(
23+
element: Elements,
24+
): Pair<Int?, List<CartoonCover>> {
25+
val r = arrayListOf<CartoonCover>()
26+
for (video in element) {
27+
video.apply {
28+
val name = select("a").attr("title")
29+
val videoUrl = select("a").attr("href")
30+
val coverUrl = select("a").attr("data-original")
31+
val episode = select(".remarks").text()
32+
val id = videoUrl.subSequence(7, videoUrl.length - 5).toString()
33+
if (!name.isNullOrBlank() && !videoUrl.isNullOrBlank() && !coverUrl.isNullOrBlank()) {
34+
val b = CartoonCoverImpl(
35+
id = id,
36+
source = source.key,
37+
url = videoUrl,
38+
title = name,
39+
intro = episode ?: "",
40+
coverUrl = SourceUtils.urlParser(ROOT_URL, coverUrl)
41+
)
42+
r.add(b)
43+
}
44+
}
45+
}
46+
return Pair(null, r)
47+
}
48+
49+
}

0 commit comments

Comments
 (0)