diff --git a/README.md b/README.md index 1c9ca358..e7221440 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # CloudStream **⚠️ Warning: By default this app doesn't provide any video sources, you have to install extensions in order to add functionality to the app.** -You can find the list of community-maintained extension repositories [here -](https://recloudstream.github.io/repos/) [![Discord](https://invidget.switchblade.xyz/5Hus6fM)](https://discord.gg/5Hus6fM) diff --git a/app/build.gradle b/app/build.gradle index 735f5dd8..a30ca2e3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -194,7 +194,7 @@ dependencies { //implementation 'com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT' // newpipe yt - implementation 'com.github.recloudstream:NewPipeExtractor:master-SNAPSHOT' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:dev-SNAPSHOT' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' // Library/extensions searching with Levenshtein distance diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Evolaod.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Evolaod.kt index 4a9f2f52..eddbf6df 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Evolaod.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Evolaod.kt @@ -26,7 +26,7 @@ open class Evoload : ExtractorApi() { } else { "" } - + val cleaned_url = if (lang == "ht") { // if url doesn't contain a flag and the url starts with http:// url } else { diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/GuardareStream.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/GuardareStream.kt index 57435161..f25cb5ba 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/GuardareStream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/GuardareStream.kt @@ -1,36 +1,83 @@ package com.lagradost.cloudstream3.extractors + import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.utils.* +class CineGrabber : GuardareStream() { + override var name = "CineGrabber" + override var mainUrl = "https://cinegrabber.com" +} + open class GuardareStream : ExtractorApi() { override var name = "Guardare" override var mainUrl = "https://guardare.stream" override val requiresReferer = false - data class GuardareJsonData ( - @JsonProperty("data") val data : List, + data class GuardareJsonData( + @JsonProperty("data") val data: List, + @JsonProperty("captions") val captions: List?, ) - data class GuardareData ( - @JsonProperty("file") val file : String, - @JsonProperty("label") val label : String, - @JsonProperty("type") val type : String + data class GuardareData( + @JsonProperty("file") val file: String, + @JsonProperty("label") val label: String, + @JsonProperty("type") val type: String ) - override suspend fun getUrl(url: String, referer: String?): List? { - val response = app.post(url.replace("/v/","/api/source/"), data = mapOf("d" to mainUrl)).text - val jsonvideodata = AppUtils.parseJson(response) - return jsonvideodata.data.map { - ExtractorLink( - it.file+".${it.type}", - this.name, - it.file+".${it.type}", - mainUrl, - it.label.filter{ it.isDigit() }.toInt(), - false + + // https://cinegrabber.com/asset/userdata/224879/caption/gqdmzh-71ez76z8/876438.srt + data class GuardareCaptions( + @JsonProperty("id") val id: String, + @JsonProperty("hash") val hash: String, + @JsonProperty("language") val language: String?, + @JsonProperty("extension") val extension: String + ) { + fun getUrl(mainUrl: String, userId: String): String { + return "$mainUrl/asset/userdata/$userId/caption/$hash/$id.$extension" + } + } + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val response = + app.post(url.replace("/v/", "/api/source/"), data = mapOf("d" to mainUrl)).text + + val jsonVideoData = AppUtils.parseJson(response) + jsonVideoData.data.forEach { + callback.invoke( + ExtractorLink( + it.file + ".${it.type}", + this.name, + it.file + ".${it.type}", + mainUrl, + it.label.filter { it.isDigit() }.toInt(), + false + ) ) } + + if (!jsonVideoData.captions.isNullOrEmpty()){ + val iframe = app.get(url) + // var USER_ID = '224879'; + val userIdRegex = Regex("""USER_ID.*?(\d+)""") + val userId = userIdRegex.find(iframe.text)?.groupValues?.getOrNull(1) ?: return + jsonVideoData.captions.forEach { + if (it == null) return@forEach + val subUrl = it.getUrl(mainUrl, userId) + subtitleCallback.invoke( + SubtitleFile( + it.language ?: "", + subUrl + ) + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Uqload.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Uqload.kt index e5d2875f..5109acc3 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Uqload.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Uqload.kt @@ -25,7 +25,7 @@ open class Uqload : ExtractorApi() { } else { "" } - + val cleaned_url = if (lang == "ht") { // if url doesn't contain a flag and the url starts with http:// url } else { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 520b6b99..0d571b76 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -23,6 +23,7 @@ import androidx.preference.PreferenceManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearSnapHelper import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.button.MaterialButton import com.lagradost.cloudstream3.* @@ -280,6 +281,7 @@ class HomeFragment : Fragment() { val builder = BottomSheetDialog(this) + builder.behavior.state = BottomSheetBehavior.STATE_EXPANDED builder.setContentView(R.layout.home_select_mainpage) builder.show() builder.let { dialog -> diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index 69f8a274..5f108cd1 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -17,6 +17,7 @@ import androidx.fragment.app.activityViewModels import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.button.MaterialButton import com.lagradost.cloudstream3.* @@ -232,6 +233,7 @@ class SearchFragment : Fragment() { val builder = BottomSheetDialog(ctx) + builder.behavior.state = BottomSheetBehavior.STATE_EXPANDED builder.setContentView(R.layout.home_select_mainpage) builder.show() builder.let { dialog -> diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsFragment.kt index e4435fff..aa302c5a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsFragment.kt @@ -1,27 +1,22 @@ package com.lagradost.cloudstream3.ui.settings.extensions import android.os.Bundle -import android.view.* -import android.widget.SearchView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.widget.SearchView import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import androidx.lifecycle.map -import com.lagradost.cloudstream3.AcraApplication -import com.lagradost.cloudstream3.CommonActivity import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.getPairList import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar import com.lagradost.cloudstream3.ui.settings.appLanguages -import com.lagradost.cloudstream3.ui.settings.getCurrentLocale -import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog import com.lagradost.cloudstream3.utils.SubtitleHelper import com.lagradost.cloudstream3.utils.UIHelper.toPx -import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import kotlinx.android.synthetic.main.fragment_plugins.* const val PLUGINS_BUNDLE_NAME = "name" diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt index b0e253be..536dc33b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt @@ -210,7 +210,7 @@ class PluginsViewModel : ViewModel() { // Return list to base state if no query this.sortedBy { it.plugin.second.name } } else { - this.sortedBy { -FuzzySearch.ratio(it.plugin.second.name, query) } + this.sortedBy { -FuzzySearch.partialRatio(it.plugin.second.name.lowercase(), query.lowercase()) } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index ebaaa12b..8d6b1b82 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -283,6 +283,7 @@ val extractorApis: MutableList = arrayListOf( Userload(), Supervideo(), GuardareStream(), + CineGrabber(), // StreamSB.kt works // SBPlay(), diff --git a/app/src/main/res/layout/home_select_mainpage.xml b/app/src/main/res/layout/home_select_mainpage.xml index ca9fa517..8546d9b1 100644 --- a/app/src/main/res/layout/home_select_mainpage.xml +++ b/app/src/main/res/layout/home_select_mainpage.xml @@ -10,7 +10,7 @@ android:id="@+id/listview1" android:layout_width="match_parent" android:layout_height="wrap_content" - + android:nestedScrollingEnabled="true" android:layout_rowWeight="1" android:layout_marginTop="10dp" android:layout_marginBottom="60dp" diff --git a/app/src/main/res/menu/repository.xml b/app/src/main/res/menu/repository.xml index d44c9764..be99b1a8 100644 --- a/app/src/main/res/menu/repository.xml +++ b/app/src/main/res/menu/repository.xml @@ -1,13 +1,17 @@ - + + + android:icon="@drawable/search_icon" + android:searchIcon="@drawable/search_icon" + app:actionViewClass="androidx.appcompat.widget.SearchView" + app:showAsAction="always|collapseActionView" + tools:ignore="AppCompatResource" /> %.1f/10.0 %d %s 共 %d 集 - 演员: %s + 演员:%s 第 %d 集将发布于 %dd %dh %dm %dh %dm %dm - 海报 + 封面 @string/result_poster_img_des - 剧集海报 - 主海报 + 剧集封面 + 主封面 随机下一个 @string/play_episode 返回 @string/home_change_provider_img_des - 更改内容提供者 + 更改片源 预览背景 - 速度 (%.2fx) - 评分: %.1f + 速度(%.2fx) + 评分:%.1f 发现新版本!\n%s -> %s 填充 %d 分钟 @@ -55,7 +55,7 @@ 分享 在浏览器中打开 跳过加载 - 正在加载… + 加载中… 正在观看 暂时搁置 @@ -77,16 +77,16 @@ 下载 已下载 - 正在下载 + 下载中 下载暂停 下载开始 下载失败 下载取消 下载完毕 %s - %s - 流媒体 + 播放 - 加载链接时出错 + 加载链接错误 内部存储 配音 @@ -125,33 +125,33 @@ 字体 字体大小 - 按内容提供者搜索 + 按片源搜索 按类型搜索 - 送给开发者 %d 根香蕉 + 给开发者送 %d 根香蕉 不送香蕉 自动选择语言 下载语言 字幕语言 按住重置为默认值 - 将字体置于 %s 导入 + 将字体导入到 %s 继续观看 移除 更多信息 @string/home_play - 此内容提供者可能需要 VPN 才能正常工作 - 此内容提供者是一个种子 ,建议使用 VPN + 此片源可能需要 VPN 才能正常使用 + 此片源是种子,建议使用 VPN 站点不提供元数据,如果站点上不存在元数据,视频加载将失败。 简介 - 没有找到简介 - 没有找到简介 + 未找到简介 + 未找到简介 - 显示日志 + 显示日志 🐈 画中画 在其他应用之上的迷你播放器中继续播放 @@ -162,24 +162,24 @@ 投屏字幕 投屏字幕设置 - 本征模式 + 倍速模式 在播放器中添加播放速度选项 滑动控制进度 - 向屏幕左侧或右侧滑动来控制播放进度 + 左右滑动控制播放进度 滑动更改设置 - 在屏幕左侧或右侧滑动来更改亮度或音量 + 上下滑动修改亮度或音量 自动播放下一集 - 当前一集结束时开始下一集 + 播放完毕后播放下一集 双击控制进度 双击暂停 - 播放器快进或快退时间 - 在屏幕左侧或右侧双击来快进或快退 + 双击控制进度时间 + 在左右侧双击快进或快退 - 双击屏幕中间暂停 + 双击中间暂停 使用系统亮度 - 在应用播放器中使用系统亮度,而不是黑色遮罩 + 在应用播放器中使用系统亮度替代黑色遮罩 更新观看进度 @@ -189,48 +189,49 @@ 备份数据 已加载备份文件 - 无法从文件 %s 中还原数据 - 成功存储数据 + 无法从 %s 文件中还原数据 + 成功保存数据 缺少存储权限,请重试 - 备份 %s 时出错 + 备份 %s 出错 搜索 账户 - 更新和备份 - + 更新与备份 + 信息 高级搜索 - 给出按内容提供者分隔的搜索结果 - 只发送关于崩溃的数据 + 按片源分割搜索结果 + 仅发送关于崩溃的数据 不发送数据 - 为动画显示下一集 + 显示动画外传 显示预告片 - 显示来自 Kitsu 的海报 - 在搜索结果中隐藏选中视频质量 + 显示来自 Kitsu 的封面 + 在搜索结果中隐藏选中视频画质 自动更新插件 显示应用更新 启动时自动搜索更新 更新至预览版 - 搜索预览版更新,而不是仅搜索完整版本 + 搜索预览版更新替代仅搜索完整版本 Github - 由同一开发者开发的轻小说应用 - 由同一开发者开发的动漫应用 + 由相同开发者开发的轻小说应用 + 由相同开发者开发的动漫应用 加入 Discord - 送给开发者一根香蕉 + 给开发者送一根香蕉 送香蕉 应用语言 - 此内容提供者不支持投屏 + 此片源不支持投屏 未找到链接 - 链接已复制到剪贴板 + 连接已复制到剪贴板 播放剧集 重置为默认值 - 抱歉,应用崩溃了,将向开发人员发送一份匿名错误报告 + 抱歉,应用崩溃了,将发送一份匿名错误报告给开发者 + %s %d%s 无季 @@ -247,8 +248,8 @@ 继续 -30 +30 - 这将永久删除 %s\n确定吗? - 剩余 %dm 分钟\n + 这将永久删除 %s\n您确定吗? + 剩余 %d 分钟 连载中 @@ -256,11 +257,11 @@ 状态 年份 评分 - 持续时间 + 时间 网站 简介 - 队列 + 已加入队列 无字幕 默认 @@ -270,29 +271,29 @@ 电影 - 剧集 + 电视剧 卡通 动漫 种子 纪录片 - 原创影像动画 + OVA 亚洲剧 直播 - 工作场所不宜 - 视频 + NSFW + 其他 电影 - 剧集 + 电视剧 卡通 - 动漫 - 原创影像动画 + @string/anime + @string/ova 种子 纪录片 亚洲剧 直播 - 工作场所不宜 - 视频 + NSFW + 其他 来源错误 远程错误 @@ -308,10 +309,10 @@ 复制链接 自动下载 下载镜像 - 重新加载镜像 + 重新加载链接 下载字幕 - 质量标签 + 画质标签 配音标签 字幕标签 标题 @@ -319,7 +320,7 @@ show_dub_key show_sub_key show_title_key - 开关海报上的 UI 元素 + 封面内容 未找到更新 检查更新 @@ -327,37 +328,37 @@ 锁定 调整画面 来源 - 跳过片头曲 + 跳过片头 不再显示 跳过此更新 更新 - 首选播放质量 - 视频播放器标题最大字符数 - 视频播放器分辨率 + 首选播放画质 + 视频播放器标题最多字符 + 视频播放器标题 视频缓冲大小 - 视频缓冲时长 - 磁盘上的视频缓存 - 清除视频和图像缓存 + 视频缓冲长度 + 视频缓存存储 + 清除视频与图像缓存 - 如果设置太高,可能会在内存较低的系统(如 Android TV 设备或旧手机)上导致问题 - 如果将存储空间设置得太高,可能会导致 Android TV 设备等存储空间不足的系统出现问题 + 设置过高可能导致崩溃。如果您使用如 Android TV 或旧手机此类低内存设备,请勿修改 + 设置过高可能导致如 Android TV 此类低存储空间设备出现系统问题 DNS over HTTPS - 用于绕过 ISP 的封锁 + 防止 DNS 劫持 - 克隆网站 - 移除网站 - 添加现有站点具有不同的 URL 的克隆 + 复制片源 + 移除片源 + 添加不同链接的已有片源复制 下载路径 - Nginx 服务器 URL + Nginx 服务器链接 - 显示有配音或字幕的动画 + 显示有配音/字幕的动漫 - 适应屏幕 + 适应 拉伸 缩放 @@ -379,15 +380,15 @@ responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use CloudStream 3 at your own risk. - 全局 + 通用 随机按钮 在主页中显示随机按钮 - 内容提供者语言 + 片源语言 应用布局 - 首选媒体 - 在支持的内容提供者中开启工作场所不宜内容 + 首选类型 + 在支持的片源中启用 NSFW 内容 字幕编码 - 内容提供者 + 片源 布局 自动 @@ -397,8 +398,8 @@ 主题色 应用主题 - 海报标题位置 - 将标题置于海报下方 + 封面标题位置 + 将标题移至封面下方 @@ -411,7 +412,7 @@ 邮箱 IP 网站名称 - 网站 URL + 网站链接 语言代码 (zh)