├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_request.yml
└── workflows
│ ├── alpha.yml
│ ├── alpha_build_manually_without_sign.yml
│ ├── auto_close_issues.yml
│ ├── close_inactive_issues.yml
│ ├── features.yml
│ └── release.yml
├── .gitignore
├── .gitmodules
├── .idea
├── .gitignore
├── kotlinc.xml
├── runConfigurations
│ ├── Run_mobile.xml
│ ├── Run_tv.xml
│ └── app.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle.kts
├── compose_compiler_config.conf
├── mobile
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ └── dev
│ │ │ └── aaa1115910
│ │ │ └── bv
│ │ │ └── mobile
│ │ │ ├── activities
│ │ │ ├── DynamicDetailActivity.kt
│ │ │ ├── FavoriteActivity.kt
│ │ │ ├── FollowingSeasonActivity.kt
│ │ │ ├── FollowingUserActivity.kt
│ │ │ ├── HistoryActivity.kt
│ │ │ ├── LoginActivity.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── SettingsActivity.kt
│ │ │ ├── UserSpaceActivity.kt
│ │ │ └── VideoPlayerActivity.kt
│ │ │ ├── component
│ │ │ ├── home
│ │ │ │ ├── SearchBar.kt
│ │ │ │ ├── UserDialog.kt
│ │ │ │ └── dynamic
│ │ │ │ │ ├── DynamicItem.kt
│ │ │ │ │ └── DynamicUserItem.kt
│ │ │ ├── player
│ │ │ │ └── VideoPlayerPages.kt
│ │ │ ├── preferences
│ │ │ │ ├── RadioPreferenceItem.kt
│ │ │ │ ├── SwitchPreferenceItem.kt
│ │ │ │ └── TextPreferenceItem.kt
│ │ │ ├── reply
│ │ │ │ ├── CommentItem.kt
│ │ │ │ ├── Comments.kt
│ │ │ │ ├── Replies.kt
│ │ │ │ └── ReplySheetScaffold.kt
│ │ │ ├── settings
│ │ │ │ └── UpdateDialog.kt
│ │ │ ├── user
│ │ │ │ └── UserAvatar.kt
│ │ │ └── videocard
│ │ │ │ ├── RelatedVideoItem.kt
│ │ │ │ ├── SeasonCard.kt
│ │ │ │ ├── SmallVideoCard.kt
│ │ │ │ ├── UpIcon.kt
│ │ │ │ └── UpSpaceVideoItem.kt
│ │ │ ├── screen
│ │ │ ├── DynamicDetailScreen.kt
│ │ │ ├── FavoriteScreen.kt
│ │ │ ├── FollowingSeasonScreen.kt
│ │ │ ├── FollowingUserScreen.kt
│ │ │ ├── HistoryScreen.kt
│ │ │ ├── LoginScreen.kt
│ │ │ ├── MobileMainScreen.kt
│ │ │ ├── UserSpaceScreen.kt
│ │ │ ├── VideoPlayerScreen.kt
│ │ │ ├── home
│ │ │ │ ├── DynamicScreen.kt
│ │ │ │ ├── HomeScreen.kt
│ │ │ │ └── home
│ │ │ │ │ ├── PopularPage.kt
│ │ │ │ │ └── RcmdPage.kt
│ │ │ └── settings
│ │ │ │ ├── SettingsCategories.kt
│ │ │ │ ├── SettingsDetails.kt
│ │ │ │ ├── SettingsScreen.kt
│ │ │ │ └── details
│ │ │ │ ├── AboutContent.kt
│ │ │ │ ├── AdvanceContent.kt
│ │ │ │ ├── DebugContent.kt
│ │ │ │ └── PlayContent.kt
│ │ │ └── theme
│ │ │ └── Theme.kt
│ │ └── res
│ │ └── values
│ │ ├── strings.xml
│ │ └── themes.xml
├── proguard-rules.pro
├── shared
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ ├── schemas
│ │ └── dev.aaa1115910.bv.dao.AppDatabase
│ │ │ ├── 1.json
│ │ │ ├── 2.json
│ │ │ └── 3.json
│ └── src
│ │ ├── debug
│ │ ├── AndroidManifest.xml
│ │ └── res
│ │ │ └── values
│ │ │ └── strings.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── ic_launcher-playstore.png
│ │ ├── kotlin
│ │ │ ├── coil
│ │ │ │ └── transform
│ │ │ │ │ └── BlurTransformation.kt
│ │ │ ├── com
│ │ │ │ └── origeek
│ │ │ │ │ └── imageViewer
│ │ │ │ │ ├── gallery
│ │ │ │ │ ├── ImageGallery.kt
│ │ │ │ │ └── ImagePager.kt
│ │ │ │ │ ├── previewer
│ │ │ │ │ ├── ImagePreviewer.kt
│ │ │ │ │ ├── ImageTransform.kt
│ │ │ │ │ ├── ImageViewerContainer.kt
│ │ │ │ │ ├── PreviewerPagerState.kt
│ │ │ │ │ ├── PreviewerTransformState.kt
│ │ │ │ │ └── PreviewerVerticalDragState.kt
│ │ │ │ │ ├── util
│ │ │ │ │ └── Ticket.kt
│ │ │ │ │ └── viewer
│ │ │ │ │ ├── ImageComposeCanvas.kt
│ │ │ │ │ ├── ImageComposeOrigin.kt
│ │ │ │ │ └── ImageViewer.kt
│ │ │ ├── de
│ │ │ │ └── schnettler
│ │ │ │ │ └── datastore
│ │ │ │ │ └── manager
│ │ │ │ │ ├── DataStoreManager.kt
│ │ │ │ │ └── PreferenceRequest.kt
│ │ │ └── dev
│ │ │ │ └── aaa1115910
│ │ │ │ └── bv
│ │ │ │ ├── BVApp.kt
│ │ │ │ ├── component
│ │ │ │ ├── BottomTip.kt
│ │ │ │ ├── BvPlayerPreview.kt
│ │ │ │ ├── Carousel.kt
│ │ │ │ ├── DevelopingTip.kt
│ │ │ │ ├── FocusGroup.kt
│ │ │ │ ├── FpsMonitor.kt
│ │ │ │ ├── LibVLCDownloaderDialog.kt
│ │ │ │ ├── LoadingTip.kt
│ │ │ │ ├── RemoteControlPanelDemo.kt
│ │ │ │ ├── TopNav.kt
│ │ │ │ ├── UpIcon.kt
│ │ │ │ ├── UserPanel.kt
│ │ │ │ ├── buttons
│ │ │ │ │ ├── CoinButton.kt
│ │ │ │ │ ├── FavoriteButton.kt
│ │ │ │ │ ├── LikeButton.kt
│ │ │ │ │ └── SeasonInfoButtons.kt
│ │ │ │ ├── pgc
│ │ │ │ │ └── IndexFilter.kt
│ │ │ │ ├── search
│ │ │ │ │ ├── SearchKeyword.kt
│ │ │ │ │ └── SoftKeyboard.kt
│ │ │ │ ├── settings
│ │ │ │ │ ├── CookiesDialog.kt
│ │ │ │ │ ├── SettingListItem.kt
│ │ │ │ │ ├── SettingSwitchListItem.kt
│ │ │ │ │ ├── SettingsMenuSelectItem.kt
│ │ │ │ │ └── UpdateDialog.kt
│ │ │ │ └── videocard
│ │ │ │ │ ├── LargeVideoCard.kt
│ │ │ │ │ ├── SeasonCard.kt
│ │ │ │ │ ├── SmallVideoCard.kt
│ │ │ │ │ └── VideosRow.kt
│ │ │ │ ├── dao
│ │ │ │ ├── AppDatabase.kt
│ │ │ │ ├── SearchHistoryDao.kt
│ │ │ │ └── UserDao.kt
│ │ │ │ ├── entity
│ │ │ │ ├── AuthData.kt
│ │ │ │ ├── PlayerType.kt
│ │ │ │ ├── ThemeType.kt
│ │ │ │ ├── carddata
│ │ │ │ │ ├── SeasonCardData.kt
│ │ │ │ │ └── VideoCardData.kt
│ │ │ │ ├── db
│ │ │ │ │ ├── SearchHistoryDB.kt
│ │ │ │ │ └── UserDB.kt
│ │ │ │ └── proxy
│ │ │ │ │ └── ProxyArea.kt
│ │ │ │ ├── network
│ │ │ │ ├── GithubApi.kt
│ │ │ │ ├── HttpServer.kt
│ │ │ │ ├── VlcLibsApi.kt
│ │ │ │ └── entity
│ │ │ │ │ └── GithubRelease.kt
│ │ │ │ ├── repository
│ │ │ │ ├── UserRepository.kt
│ │ │ │ └── VideoInfoRepository.kt
│ │ │ │ ├── ui
│ │ │ │ └── theme
│ │ │ │ │ ├── Theme.kt
│ │ │ │ │ └── Typography.kt
│ │ │ │ ├── util
│ │ │ │ ├── AbiUtil.kt
│ │ │ │ ├── BlacklistUtil.kt
│ │ │ │ ├── CodecUtil.kt
│ │ │ │ ├── EnumExtends.kt
│ │ │ │ ├── Extends.kt
│ │ │ │ ├── ImageExtends.kt
│ │ │ │ ├── LogCatcherUtil.kt
│ │ │ │ ├── ModifierExtends.kt
│ │ │ │ ├── NetworkUtil.kt
│ │ │ │ ├── NotYetImplemented.kt
│ │ │ │ ├── PartitionUtil.kt
│ │ │ │ ├── PgcIndexParamExtends.kt
│ │ │ │ ├── PgcTypeExtends.kt
│ │ │ │ ├── Prefs.kt
│ │ │ │ ├── UgcTypeExtends.kt
│ │ │ │ ├── UgcTypeV2Extends.kt
│ │ │ │ └── calculateWindowSizeClassInPreview.kt
│ │ │ │ └── viewmodel
│ │ │ │ ├── CommentViewModel.kt
│ │ │ │ ├── DynamicDetailViewModel.kt
│ │ │ │ ├── SeasonViewModel.kt
│ │ │ │ ├── TagViewModel.kt
│ │ │ │ ├── UserSwitchViewModel.kt
│ │ │ │ ├── UserViewModel.kt
│ │ │ │ ├── VideoPlayerV3ViewModel.kt
│ │ │ │ ├── home
│ │ │ │ ├── DynamicViewModel.kt
│ │ │ │ ├── PopularViewModel.kt
│ │ │ │ └── RecommendViewModel.kt
│ │ │ │ ├── index
│ │ │ │ └── PgcIndexViewModel.kt
│ │ │ │ ├── login
│ │ │ │ ├── AppQrLoginViewModel.kt
│ │ │ │ └── SmsLoginViewModel.kt
│ │ │ │ ├── pgc
│ │ │ │ ├── PgcAnimeViewModel.kt
│ │ │ │ ├── PgcDocumentaryViewModel.kt
│ │ │ │ ├── PgcGuoChuangViewModel.kt
│ │ │ │ ├── PgcMovieViewModel.kt
│ │ │ │ ├── PgcTvViewModel.kt
│ │ │ │ ├── PgcVarietyViewModel.kt
│ │ │ │ └── PgcViewModel.kt
│ │ │ │ ├── search
│ │ │ │ ├── SearchInputViewModel.kt
│ │ │ │ └── SearchResultViewModel.kt
│ │ │ │ ├── user
│ │ │ │ ├── FavoriteViewModel.kt
│ │ │ │ ├── FollowViewModel.kt
│ │ │ │ ├── FollowingSeasonViewModel.kt
│ │ │ │ ├── HistoryViewModel.kt
│ │ │ │ ├── ToViewViewModel.kt
│ │ │ │ └── UserSpaceViewModel.kt
│ │ │ │ └── video
│ │ │ │ └── VideoDetailViewModel.kt
│ │ ├── proto
│ │ │ └── blacklist.proto
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── ic_banner.webp
│ │ │ ├── ic_banner_foreground.xml
│ │ │ ├── ic_danmaku_count.xml
│ │ │ ├── ic_gamer_ani.xml
│ │ │ ├── ic_launcher_foreground.xml
│ │ │ ├── ic_play_count.xml
│ │ │ └── ic_up.xml
│ │ │ ├── font
│ │ │ └── noto_sans_math_regular.ttf
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_banner.xml
│ │ │ ├── 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
│ │ │ ├── raw
│ │ │ └── ic_playing.json
│ │ │ ├── values
│ │ │ ├── arrays.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── themes.xml
│ │ │ └── xml
│ │ │ ├── network_security_config.xml
│ │ │ └── provider_paths.xml
│ │ ├── r8Test
│ │ ├── AndroidManifest.xml
│ │ └── res
│ │ │ └── values
│ │ │ └── strings.xml
│ │ └── test
│ │ └── kotlin
│ │ ├── android
│ │ └── util
│ │ │ └── Log.kt
│ │ └── dev
│ │ └── aaa1115910
│ │ └── bv
│ │ └── network
│ │ └── GithubApiTest.kt
├── src
│ └── main
│ │ └── AndroidManifest.xml
└── tv
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── kotlin
│ └── dev
│ │ └── aaa1115910
│ │ └── bv
│ │ └── tv
│ │ ├── activities
│ │ ├── MainActivity.kt
│ │ ├── pgc
│ │ │ ├── PgcIndexActivity.kt
│ │ │ └── anime
│ │ │ │ └── AnimeTimelineActivity.kt
│ │ ├── search
│ │ │ ├── SearchInputActivity.kt
│ │ │ └── SearchResultActivity.kt
│ │ ├── settings
│ │ │ ├── LogsActivity.kt
│ │ │ ├── MediaCodecActivity.kt
│ │ │ ├── SettingsActivity.kt
│ │ │ └── SpeedTestActivity.kt
│ │ ├── user
│ │ │ ├── FavoriteActivity.kt
│ │ │ ├── FollowActivity.kt
│ │ │ ├── FollowingSeasonActivity.kt
│ │ │ ├── HistoryActivity.kt
│ │ │ ├── LoginActivity.kt
│ │ │ ├── ToViewActivity.kt
│ │ │ ├── UserInfoActivity.kt
│ │ │ ├── UserLockSettingsActivity.kt
│ │ │ └── UserSwitchActivity.kt
│ │ └── video
│ │ │ ├── RemoteControllerPanelDemoActivity.kt
│ │ │ ├── SeasonInfoActivity.kt
│ │ │ ├── TagActivity.kt
│ │ │ ├── UpInfoActivity.kt
│ │ │ ├── VideoInfoActivity.kt
│ │ │ └── VideoPlayerV3Activity.kt
│ │ ├── component
│ │ └── settings
│ │ │ └── UpdateDialog.kt
│ │ ├── screens
│ │ ├── HomeScreen.kt
│ │ ├── MainScreen.kt
│ │ ├── RegionBlockScreen.kt
│ │ ├── SeasonInfoScreen.kt
│ │ ├── TagScreen.kt
│ │ ├── VideoInfoScreen.kt
│ │ ├── VideoPlayerV3Screen.kt
│ │ ├── home
│ │ │ └── DynamicsScreen.kt
│ │ ├── login
│ │ │ ├── AppQRLoginContent.kt
│ │ │ ├── LoginScreen.kt
│ │ │ └── SmsLoginContent.kt
│ │ ├── main
│ │ │ ├── DrawerContent.kt
│ │ │ ├── HomeContent.kt
│ │ │ ├── PgcContent.kt
│ │ │ ├── UgcContent.kt
│ │ │ ├── home
│ │ │ │ ├── DynamicsScreen.kt
│ │ │ │ ├── PopularScreen.kt
│ │ │ │ ├── RecommendScreen.kt
│ │ │ │ └── UserScreen.kt
│ │ │ ├── pgc
│ │ │ │ ├── AnimeContent.kt
│ │ │ │ ├── DocumentaryContent.kt
│ │ │ │ ├── GuoChuangContent.kt
│ │ │ │ ├── MovieContent.kt
│ │ │ │ ├── PgcCommon.kt
│ │ │ │ ├── PgcIndexScreen.kt
│ │ │ │ ├── TvContent.kt
│ │ │ │ ├── VarietyContent.kt
│ │ │ │ └── anime
│ │ │ │ │ └── AnimeTimelineScreen.kt
│ │ │ └── ugc
│ │ │ │ ├── AiContent.kt
│ │ │ │ ├── AnimalContent.kt
│ │ │ │ ├── CarContent.kt
│ │ │ │ ├── CinephileContent.kt
│ │ │ │ ├── DanceContent.kt
│ │ │ │ ├── DougaContent.kt
│ │ │ │ ├── EmotionContent.kt
│ │ │ │ ├── EntContent.kt
│ │ │ │ ├── FashionContent.kt
│ │ │ │ ├── FoodContent.kt
│ │ │ │ ├── GameContent.kt
│ │ │ │ ├── GymContent.kt
│ │ │ │ ├── HandmakeContent.kt
│ │ │ │ ├── HomeContent.kt
│ │ │ │ ├── InformationContent.kt
│ │ │ │ ├── KichikuContent.kt
│ │ │ │ ├── KnowledgeContent.kt
│ │ │ │ ├── LifeExperienceContent.kt
│ │ │ │ ├── LifeJoyContent.kt
│ │ │ │ ├── MuiscContent.kt
│ │ │ │ ├── MysticismContent.kt
│ │ │ │ ├── OutdoorsContent.kt
│ │ │ │ ├── PaintingContent.kt
│ │ │ │ ├── ParentingContent.kt
│ │ │ │ ├── RuralContent.kt
│ │ │ │ ├── ShortPlayContent.kt
│ │ │ │ ├── SportsContent.kt
│ │ │ │ ├── TechContent.kt
│ │ │ │ ├── TravelContent.kt
│ │ │ │ ├── UgcChildRegionButtons.kt
│ │ │ │ ├── UgcCommon.kt
│ │ │ │ ├── VlogContent.kt
│ │ │ │ └── healthContent.kt
│ │ ├── search
│ │ │ ├── SearchInputScreen.kt
│ │ │ ├── SearchResultFilter.kt
│ │ │ └── SearchResultScreen.kt
│ │ ├── settings
│ │ │ ├── LogsScreen.kt
│ │ │ ├── MediaCodecScreen.kt
│ │ │ ├── SettingsScreen.kt
│ │ │ ├── SpeedTestScreen.kt
│ │ │ └── content
│ │ │ │ ├── AboutSetting.kt
│ │ │ │ ├── ApiSetting.kt
│ │ │ │ ├── AudioSetting.kt
│ │ │ │ ├── InfoSetting.kt
│ │ │ │ ├── NetworkSetting.kt
│ │ │ │ ├── OtherSetting.kt
│ │ │ │ ├── PlayerTypeSetting.kt
│ │ │ │ ├── ResolutionSetting.kt
│ │ │ │ ├── StorageSetting.kt
│ │ │ │ ├── UISetting.kt
│ │ │ │ └── VideoCodecSetting.kt
│ │ └── user
│ │ │ ├── FavoriteScreen.kt
│ │ │ ├── FollowScreen.kt
│ │ │ ├── FollowingSeasonFilter.kt
│ │ │ ├── FollowingSeasonScreen.kt
│ │ │ ├── HistoryScreen.kt
│ │ │ ├── ToViewScreen.kt
│ │ │ ├── UpInfoScreen.kt
│ │ │ ├── UserInfoScreen.kt
│ │ │ ├── UserSwitchScreen.kt
│ │ │ └── lock
│ │ │ ├── UnlockSwitchUserContent.kt
│ │ │ ├── UnlockUserScreen.kt
│ │ │ └── UserLockSettingsScreen.kt
│ │ └── util
│ │ └── PlayerActivityUtil.kt
│ └── res
│ └── values
│ ├── strings.xml
│ └── themes.xml
├── bili-api-grpc
├── .gitignore
├── build.gradle.kts
└── proto
│ ├── bilibili
│ ├── account
│ │ └── fission
│ │ │ └── v1
│ │ │ └── fission.proto
│ ├── ad
│ │ └── v1
│ │ │ └── ad.proto
│ ├── api
│ │ ├── player
│ │ │ └── v1
│ │ │ │ └── player.proto
│ │ ├── probe
│ │ │ └── v1
│ │ │ │ └── probe.proto
│ │ └── ticket
│ │ │ └── v1
│ │ │ └── ticket.proto
│ ├── app
│ │ ├── archive
│ │ │ ├── middleware
│ │ │ │ └── v1
│ │ │ │ │ └── preload.proto
│ │ │ └── v1
│ │ │ │ └── archive.proto
│ │ ├── card
│ │ │ └── v1
│ │ │ │ ├── ad.proto
│ │ │ │ ├── card.proto
│ │ │ │ ├── common.proto
│ │ │ │ ├── double.proto
│ │ │ │ └── single.proto
│ │ ├── click
│ │ │ └── v1
│ │ │ │ └── heartbeat.proto
│ │ ├── distribution
│ │ │ ├── setting
│ │ │ │ ├── download.proto
│ │ │ │ ├── dynamic.proto
│ │ │ │ ├── experimental.proto
│ │ │ │ ├── internaldevice.proto
│ │ │ │ ├── night.proto
│ │ │ │ ├── other.proto
│ │ │ │ ├── pegasus.proto
│ │ │ │ ├── play.proto
│ │ │ │ ├── privacy.proto
│ │ │ │ └── search.proto
│ │ │ └── v1
│ │ │ │ └── distribution.proto
│ │ ├── dynamic
│ │ │ ├── common
│ │ │ │ └── dynamic.proto
│ │ │ ├── v1
│ │ │ │ └── dynamic.proto
│ │ │ └── v2
│ │ │ │ ├── campus.proto
│ │ │ │ ├── dynamic.proto
│ │ │ │ └── opus.proto
│ │ ├── interfaces
│ │ │ └── v1
│ │ │ │ ├── history.proto
│ │ │ │ ├── media.proto
│ │ │ │ ├── search.proto
│ │ │ │ └── space.proto
│ │ ├── listener
│ │ │ └── v1
│ │ │ │ └── listener.proto
│ │ ├── playeronline
│ │ │ └── v1
│ │ │ │ └── playeronline.proto
│ │ ├── playerunite
│ │ │ ├── pgcanymodel
│ │ │ │ └── PGCAnyModel.proto
│ │ │ ├── ugcanymodel
│ │ │ │ └── UGCAnyModel.proto
│ │ │ └── v1
│ │ │ │ └── playerunite.proto
│ │ ├── playurl
│ │ │ └── v1
│ │ │ │ └── playurl.proto
│ │ ├── resource
│ │ │ ├── privacy
│ │ │ │ └── v1
│ │ │ │ │ └── api.proto
│ │ │ └── v1
│ │ │ │ └── module.proto
│ │ ├── search
│ │ │ └── v2
│ │ │ │ └── search.proto
│ │ ├── show
│ │ │ ├── gateway
│ │ │ │ └── v1
│ │ │ │ │ └── service.proto
│ │ │ ├── mixture
│ │ │ │ └── v1
│ │ │ │ │ └── mixture.proto
│ │ │ ├── popular
│ │ │ │ └── v1
│ │ │ │ │ └── popular.proto
│ │ │ ├── rank
│ │ │ │ └── v1
│ │ │ │ │ └── rank.proto
│ │ │ └── region
│ │ │ │ └── v1
│ │ │ │ └── region.proto
│ │ ├── space
│ │ │ └── v1
│ │ │ │ └── space.proto
│ │ ├── splash
│ │ │ └── v1
│ │ │ │ └── splash.proto
│ │ ├── topic
│ │ │ └── v1
│ │ │ │ └── topic.proto
│ │ ├── view
│ │ │ └── v1
│ │ │ │ └── view.proto
│ │ ├── viewunite
│ │ │ ├── common.proto
│ │ │ ├── pgcanymodel.proto
│ │ │ ├── ugcanymodel.proto
│ │ │ └── v1
│ │ │ │ └── viewunite.proto
│ │ └── wall
│ │ │ └── v1
│ │ │ └── wall.proto
│ ├── broadcast
│ │ ├── message
│ │ │ ├── editor
│ │ │ │ └── notify.proto
│ │ │ ├── esports
│ │ │ │ └── notify.proto
│ │ │ ├── fission
│ │ │ │ └── notify.proto
│ │ │ ├── im
│ │ │ │ └── notify.proto
│ │ │ ├── main
│ │ │ │ ├── dm.proto
│ │ │ │ ├── native.proto
│ │ │ │ ├── resource.proto
│ │ │ │ └── search.proto
│ │ │ ├── note
│ │ │ │ └── sync.proto
│ │ │ ├── ogv
│ │ │ │ ├── freya.proto
│ │ │ │ └── live.proto
│ │ │ ├── ticket
│ │ │ │ └── activitygame.proto
│ │ │ └── tv
│ │ │ │ └── proj.proto
│ │ ├── v1
│ │ │ ├── broadcast.proto
│ │ │ ├── laser.proto
│ │ │ ├── mod.proto
│ │ │ ├── push.proto
│ │ │ ├── room.proto
│ │ │ └── test.proto
│ │ └── v2
│ │ │ └── laser.proto
│ ├── cheese
│ │ └── gateway
│ │ │ └── player
│ │ │ └── v1
│ │ │ └── playurl.proto
│ ├── community
│ │ └── service
│ │ │ ├── dm
│ │ │ └── v1
│ │ │ │ └── dm.proto
│ │ │ └── govern
│ │ │ └── v1
│ │ │ └── govern.proto
│ ├── dagw
│ │ └── component
│ │ │ └── avatar
│ │ │ ├── common
│ │ │ └── common.proto
│ │ │ └── v1
│ │ │ ├── avatar.proto
│ │ │ └── plugin.proto
│ ├── dynamic
│ │ ├── common
│ │ │ └── dynamic.proto
│ │ ├── gw
│ │ │ └── gateway.proto
│ │ └── interfaces
│ │ │ └── feed
│ │ │ └── v1
│ │ │ └── api.proto
│ ├── gaia
│ │ └── gw
│ │ │ └── gw_api.proto
│ ├── im
│ │ ├── interfaces
│ │ │ ├── inner-interface
│ │ │ │ └── v1
│ │ │ │ │ └── api.proto
│ │ │ └── v1
│ │ │ │ └── im.proto
│ │ └── type
│ │ │ └── im.proto
│ ├── live
│ │ ├── app
│ │ │ └── room
│ │ │ │ └── v1
│ │ │ │ └── room.proto
│ │ └── general
│ │ │ └── interfaces
│ │ │ └── v1
│ │ │ └── interfaces.proto
│ ├── main
│ │ ├── common
│ │ │ └── arch
│ │ │ │ └── doll
│ │ │ │ └── v1
│ │ │ │ └── doll.proto
│ │ └── community
│ │ │ └── reply
│ │ │ └── v1
│ │ │ └── reply.proto
│ ├── metadata
│ │ ├── device
│ │ │ └── device.proto
│ │ ├── fawkes
│ │ │ └── fawkes.proto
│ │ ├── locale
│ │ │ └── locale.proto
│ │ ├── metadata.proto
│ │ ├── network
│ │ │ └── network.proto
│ │ ├── parabox
│ │ │ └── parabox.proto
│ │ └── restriction
│ │ │ └── restriction.proto
│ ├── pagination
│ │ └── pagination.proto
│ ├── pangu
│ │ └── gallery
│ │ │ └── v1
│ │ │ └── gallery.proto
│ ├── pgc
│ │ ├── gateway
│ │ │ └── player
│ │ │ │ ├── v1
│ │ │ │ └── playurl.proto
│ │ │ │ └── v2
│ │ │ │ └── playurl.proto
│ │ └── service
│ │ │ └── premiere
│ │ │ └── v1
│ │ │ └── premiere.proto
│ ├── playershared
│ │ └── playershared.proto
│ ├── polymer
│ │ ├── app
│ │ │ └── search
│ │ │ │ └── v1
│ │ │ │ └── search.proto
│ │ ├── community
│ │ │ └── govern
│ │ │ │ └── v1
│ │ │ │ └── govern.proto
│ │ ├── contract
│ │ │ └── v1
│ │ │ │ └── contract.proto
│ │ ├── demo
│ │ │ └── demo.proto
│ │ └── list
│ │ │ └── v1
│ │ │ └── list.proto
│ ├── relation
│ │ └── interfaces
│ │ │ └── api.proto
│ ├── render
│ │ └── render.proto
│ ├── rpc
│ │ └── status.proto
│ ├── tv
│ │ └── interfaces
│ │ │ └── dm
│ │ │ └── v1
│ │ │ └── dm.proto
│ ├── vega
│ │ └── deneb
│ │ │ └── v1
│ │ │ └── deneb.proto
│ └── web
│ │ ├── interfaces
│ │ └── v1
│ │ │ └── interfaces.proto
│ │ └── space
│ │ └── v1
│ │ └── space.proto
│ ├── common
│ └── ErrorProto.proto
│ ├── datacenter
│ └── hakase
│ │ └── protobuf
│ │ └── android_device_info.proto
│ └── pgc
│ ├── biz
│ └── room.proto
│ └── gateway
│ └── vega
│ └── v1
│ └── vega.proto
├── bili-api
├── .gitignore
├── build.gradle.kts
├── example-response
│ └── live-event
│ │ ├── COMBO_SEND.json5
│ │ ├── DANMU_MSG.json5
│ │ ├── ENTRY_EFFECT.json5
│ │ ├── GUARD_BUY.json5
│ │ ├── HOT_RANK_CHANGED.json5
│ │ ├── HOT_RANK_CHANGED_V2.json5
│ │ ├── HOT_RANK_SETTLEMENT.json5
│ │ ├── HOT_RANK_SETTLEMENT_V2.json5
│ │ ├── HOT_ROOM_NOTIFY.json5
│ │ ├── INTERACT_WORD.json5
│ │ ├── LIKE_INFO_V3_CLICK.json5
│ │ ├── LIKE_INFO_V3_UPDATE.json5
│ │ ├── LIVE_INTERACTIVE_GAME.json5
│ │ ├── LIVE_MULTI_VIEW_CHANGE.json5
│ │ ├── NOTICE_MSG.json5
│ │ ├── ONLINE_RANK_COUNT.json5
│ │ ├── ONLINE_RANK_TOP3.json5
│ │ ├── ONLINE_RANK_V2.json5
│ │ ├── PREPARING.json5
│ │ ├── ROOM_REAL_TIME_MESSAGE_UPDATE.json
│ │ ├── SEND_GIFT.json
│ │ ├── STOP_LIVE_ROOM_LIST.json5
│ │ ├── SUPER_CHAT_ENTRANCE.json5
│ │ ├── SUPER_CHAT_MESSAGE.json5
│ │ ├── SUPER_CHAT_MESSAGE_JPN.json5
│ │ ├── USER_TOAST_MSG.json5
│ │ ├── WATCHED_CHANGE.json5
│ │ └── WIDGET_BANNER.json5
└── src
│ ├── main
│ └── kotlin
│ │ ├── com
│ │ └── tfowl
│ │ │ └── ktor
│ │ │ └── client
│ │ │ └── plugins
│ │ │ └── JsoupPlugin.kt
│ │ └── dev
│ │ └── aaa1115910
│ │ └── biliapi
│ │ ├── entity
│ │ ├── ApiType.kt
│ │ ├── CarouselData.kt
│ │ ├── CodeType.kt
│ │ ├── Favorite.kt
│ │ ├── Picture.kt
│ │ ├── PlayData.kt
│ │ ├── danmaku
│ │ │ └── DanmakuMask.kt
│ │ ├── home
│ │ │ └── RecommendData.kt
│ │ ├── login
│ │ │ ├── Captcha.kt
│ │ │ ├── QR.kt
│ │ │ └── Sms.kt
│ │ ├── pgc
│ │ │ ├── PgcFeedData.kt
│ │ │ ├── PgcItem.kt
│ │ │ ├── PgcType.kt
│ │ │ └── index
│ │ │ │ ├── IndexParams.kt
│ │ │ │ └── PgcIndexData.kt
│ │ ├── rank
│ │ │ └── Popular.kt
│ │ ├── reply
│ │ │ ├── Comment.kt
│ │ │ ├── CommentPage.kt
│ │ │ ├── CommentRepliesData.kt
│ │ │ └── CommentSort.kt
│ │ ├── search
│ │ │ └── Hotword.kt
│ │ ├── season
│ │ │ ├── FollowingSeasons.kt
│ │ │ ├── IndexResult.kt
│ │ │ └── Timeline.kt
│ │ ├── ugc
│ │ │ ├── UgcItem.kt
│ │ │ ├── UgcType.kt
│ │ │ ├── UgcTypeV2.kt
│ │ │ └── region
│ │ │ │ ├── UgcFeedData.kt
│ │ │ │ ├── UgcFeedPage.kt
│ │ │ │ ├── UgcRegionData.kt
│ │ │ │ ├── UgcRegionListData.kt
│ │ │ │ └── UgcRegionPage.kt
│ │ ├── user
│ │ │ ├── Author.kt
│ │ │ ├── Dynamic.kt
│ │ │ ├── FollowedUser.kt
│ │ │ ├── History.kt
│ │ │ ├── Space.kt
│ │ │ └── ToView.kt
│ │ └── video
│ │ │ ├── Dimension.kt
│ │ │ ├── Heartbeat.kt
│ │ │ ├── RelatedVideo.kt
│ │ │ ├── Subtitle.kt
│ │ │ ├── Tag.kt
│ │ │ ├── VideoDetail.kt
│ │ │ ├── VideoPage.kt
│ │ │ ├── VideoShot.kt
│ │ │ └── season
│ │ │ ├── Episode.kt
│ │ │ ├── PgcSeason.kt
│ │ │ ├── SeasonDetail.kt
│ │ │ └── Section.kt
│ │ ├── grpc
│ │ └── utils
│ │ │ ├── Channel.kt
│ │ │ └── StatusExtends.kt
│ │ ├── http
│ │ ├── BiliHttpApi.kt
│ │ ├── BiliHttpProxyApi.kt
│ │ ├── BiliLiveHttpApi.kt
│ │ ├── BiliPassportHttpApi.kt
│ │ ├── BiliPlusHttpApi.kt
│ │ ├── entity
│ │ │ ├── BiliResponse.kt
│ │ │ ├── biliplus
│ │ │ │ └── View.kt
│ │ │ ├── danmaku
│ │ │ │ └── DanmakuResponse.kt
│ │ │ ├── dynamic
│ │ │ │ ├── DynamicDetailResponse.kt
│ │ │ │ └── DynamicResponse.kt
│ │ │ ├── history
│ │ │ │ └── HistoryData.kt
│ │ │ ├── home
│ │ │ │ ├── RcmdIndexData.kt
│ │ │ │ └── RcmdTopData.kt
│ │ │ ├── index
│ │ │ │ ├── IndexFilter.kt
│ │ │ │ ├── IndexFilterArea.kt
│ │ │ │ ├── IndexFilterProducerId.kt
│ │ │ │ ├── IndexFilterStyle.kt
│ │ │ │ ├── IndexOrder.kt
│ │ │ │ └── IndexResult.kt
│ │ │ ├── live
│ │ │ │ ├── HistoryDanmaku.kt
│ │ │ │ ├── LiveDanmuInfoResponse.kt
│ │ │ │ ├── LiveEvent.kt
│ │ │ │ ├── LiveFrame.kt
│ │ │ │ └── LiveRoomPlayInfoResponse.kt
│ │ │ ├── login
│ │ │ │ ├── Captcha.kt
│ │ │ │ ├── qr
│ │ │ │ │ ├── AppQR.kt
│ │ │ │ │ └── WebQR.kt
│ │ │ │ └── sms
│ │ │ │ │ ├── SendSmsResponse.kt
│ │ │ │ │ └── SmsLoginResponse.kt
│ │ │ ├── pgc
│ │ │ │ ├── PgcFeed.kt
│ │ │ │ ├── PgcFeedV3.kt
│ │ │ │ └── PgcWebInitialStateData.kt
│ │ │ ├── proxy
│ │ │ │ └── PlayUrl.kt
│ │ │ ├── region
│ │ │ │ ├── RegionBanner.kt
│ │ │ │ ├── RegionDynamic.kt
│ │ │ │ ├── RegionDynamicList.kt
│ │ │ │ ├── RegionFeedRcmd.kt
│ │ │ │ └── RegionLocs.kt
│ │ │ ├── reply
│ │ │ │ ├── Comment.kt
│ │ │ │ ├── CommentReplyData.kt
│ │ │ │ └── Layers.kt
│ │ │ ├── search
│ │ │ │ ├── KeywordSuggest.kt
│ │ │ │ ├── SearchCost.kt
│ │ │ │ ├── SearchResult.kt
│ │ │ │ ├── SearchResultItem.kt
│ │ │ │ └── SearchSquare.kt
│ │ │ ├── season
│ │ │ │ ├── AppSeasonData.kt
│ │ │ │ ├── Episode.kt
│ │ │ │ ├── Follow.kt
│ │ │ │ ├── SeasonSection.kt
│ │ │ │ ├── WebFollowingSeason.kt
│ │ │ │ └── WebSeasonData.kt
│ │ │ ├── subtitle
│ │ │ │ └── Subtitle.kt
│ │ │ ├── toview
│ │ │ │ └── ToViewData.kt
│ │ │ ├── user
│ │ │ │ ├── Follow.kt
│ │ │ │ ├── LevelInfo.kt
│ │ │ │ ├── Nameplate.kt
│ │ │ │ ├── Official.kt
│ │ │ │ ├── Pendant.kt
│ │ │ │ ├── Profession.kt
│ │ │ │ ├── Relation.kt
│ │ │ │ ├── SpaceVideoData.kt
│ │ │ │ ├── Staff.kt
│ │ │ │ ├── UserCardInfoResponse.kt
│ │ │ │ ├── UserGarb.kt
│ │ │ │ ├── UserHonours.kt
│ │ │ │ ├── UserInfoResponse.kt
│ │ │ │ ├── UserSelfInfoResponse.kt
│ │ │ │ ├── Vip.kt
│ │ │ │ ├── favorite
│ │ │ │ │ ├── CntInfo.kt
│ │ │ │ │ ├── FavoriteFolderInfo.kt
│ │ │ │ │ ├── FavoriteFolderInfoListData.kt
│ │ │ │ │ ├── FavoriteItem.kt
│ │ │ │ │ ├── Upper.kt
│ │ │ │ │ └── UserFavoriteFoldersData.kt
│ │ │ │ └── garb
│ │ │ │ │ ├── CardBg.kt
│ │ │ │ │ ├── Equip.kt
│ │ │ │ │ └── Item.kt
│ │ │ ├── video
│ │ │ │ ├── AddCoin.kt
│ │ │ │ ├── OneClickTripleAction.kt
│ │ │ │ ├── PlayUrlResponse.kt
│ │ │ │ ├── PopularVideosResponse.kt
│ │ │ │ ├── RelatedVideosResponse.kt
│ │ │ │ ├── SetVideoFavorite.kt
│ │ │ │ ├── Tag.kt
│ │ │ │ ├── Timeline.kt
│ │ │ │ ├── UgcSeason.kt
│ │ │ │ ├── VideoDetail.kt
│ │ │ │ ├── VideoInfo.kt
│ │ │ │ ├── VideoMoreInfo.kt
│ │ │ │ └── VideoShot.kt
│ │ │ └── web
│ │ │ │ ├── Hover.kt
│ │ │ │ └── Nav.kt
│ │ └── util
│ │ │ ├── ApiSign.kt
│ │ │ ├── BiliAppConf.kt
│ │ │ ├── Buvid.kt
│ │ │ ├── CommonEnumIntSerializer.kt
│ │ │ └── Zlib.kt
│ │ ├── repositories
│ │ ├── AuthRepository.kt
│ │ ├── ChannelRepository.kt
│ │ ├── CoinRepository.kt
│ │ ├── CommentRepository.kt
│ │ ├── FavoriteRepository.kt
│ │ ├── HistoryRepository.kt
│ │ ├── LikeRepository.kt
│ │ ├── LoginRepository.kt
│ │ ├── OneClickTripleActionRepository.kt
│ │ ├── PgcRepository.kt
│ │ ├── RecommendVideoRepository.kt
│ │ ├── SearchRepository.kt
│ │ ├── SeasonRepository.kt
│ │ ├── ToViewRepository.kt
│ │ ├── UgcRepository.kt
│ │ ├── UserRepository.kt
│ │ ├── VideoDetailRepository.kt
│ │ └── VideoPlayRepository.kt
│ │ ├── util
│ │ ├── AvBvConverter.kt
│ │ ├── Extends.kt
│ │ └── UrlUtil.kt
│ │ └── websocket
│ │ └── LiveDataWebSocket.kt
│ └── test
│ ├── kotlin
│ └── dev
│ │ └── aaa1115910
│ │ └── biliapi
│ │ ├── BvLoginRepositoryTest.kt
│ │ ├── entity
│ │ └── DanmakuMaskTest.kt
│ │ ├── http
│ │ ├── BiliHttpApiTest.kt
│ │ ├── BiliLiveHttpApiTest.kt
│ │ ├── BiliPassportHttpApiTest.kt
│ │ └── BiliPlusHttpApiTest.kt
│ │ ├── repositories
│ │ ├── CommentRepositoryTest.kt
│ │ ├── FavoriteRepositoryTest.kt
│ │ ├── HistoryRepositoryTest.kt
│ │ ├── PgcRepositoryTest.kt
│ │ ├── RecommendVideoRepositoryTest.kt
│ │ ├── SearchRepositoryTest.kt
│ │ ├── SeasonRepositoryTest.kt
│ │ ├── UgcRepositoryTest.kt
│ │ ├── UserRepositoryTest.kt
│ │ ├── VideoDetailRepositoryTest.kt
│ │ └── VideoPlayRepositoryTest.kt
│ │ └── websocket
│ │ └── LiveDataWebSocketTest.kt
│ └── resources
│ ├── 3540266_25_2.exp.mobmask
│ └── 3540266_25_2.exp.webmask
├── bili-subtitle
├── .gitignore
├── build.gradle.kts
└── src
│ ├── main
│ └── kotlin
│ │ └── dev
│ │ └── aaa1115910
│ │ └── bilisubtitle
│ │ ├── SubtitleEncoder.kt
│ │ ├── SubtitleParser.kt
│ │ └── entity
│ │ ├── BiliSubtitle.kt
│ │ ├── SrtSubtitle.kt
│ │ ├── SubtitleItem.kt
│ │ └── Timestamp.kt
│ └── test
│ ├── kotlin
│ └── dev
│ │ └── aaa1115910
│ │ └── bilisubtitle
│ │ ├── SubtitleEncoderTest.kt
│ │ ├── SubtitleParserTest.kt
│ │ └── entity
│ │ └── TimestampTest.kt
│ └── resources
│ ├── example.bcc
│ └── example.srt
├── build.gradle.kts
├── buildSrc
├── .gitignore
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ ├── AppConfiguration.kt
│ └── ProtobufConfiguration.kt
├── gradle.properties
├── gradle
├── androidx.versions.toml
├── gradle.versions.toml
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── player
├── .gitignore
├── build.gradle.kts
├── core
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── assets
│ │ └── GlobalSign ECC Root CA R5.crt
│ │ └── kotlin
│ │ └── dev
│ │ └── aaa1115910
│ │ └── bv
│ │ └── player
│ │ ├── AbstractVideoPlayer.kt
│ │ ├── BvVideoPlayer.kt
│ │ ├── OkHttpUtil.kt
│ │ ├── VideoPlayerListener.kt
│ │ ├── VideoPlayerOptions.kt
│ │ ├── factory
│ │ └── PlayerFactory.kt
│ │ └── impl
│ │ └── exo
│ │ ├── ExoMediaPlayer.kt
│ │ └── ExoPlayerFactory.kt
├── mobile
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── kotlin
│ │ └── dev
│ │ └── aaa1115910
│ │ └── bv
│ │ └── player
│ │ └── mobile
│ │ ├── BvPlayer.kt
│ │ ├── MaterialDarkTheme.kt
│ │ ├── Media3VideoPlayer.kt
│ │ ├── NoRippleClickable.kt
│ │ ├── SeekBar.kt
│ │ └── controller
│ │ ├── BvPlayerController.kt
│ │ ├── FullscreenControllers.kt
│ │ ├── MiniControllers.kt
│ │ ├── PlayPauseButton.kt
│ │ ├── Tips.kt
│ │ └── menu
│ │ ├── DanmakuMenu.kt
│ │ ├── DashMenu.kt
│ │ ├── MoreMenu.kt
│ │ ├── SpeedMenu.kt
│ │ └── VideoListMenu.kt
├── shared
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ └── dev
│ │ │ └── aaa1115910
│ │ │ └── bv
│ │ │ └── player
│ │ │ ├── AkDanmakuPlayer.kt
│ │ │ ├── entity
│ │ │ ├── Audio.kt
│ │ │ ├── DanmakuSize.kt
│ │ │ ├── DanmakuTransparency.kt
│ │ │ ├── DanmakuType.kt
│ │ │ ├── RequestState.kt
│ │ │ ├── Resolution.kt
│ │ │ ├── VideoAspectRatio.kt
│ │ │ ├── VideoCodec.kt
│ │ │ ├── VideoListItem.kt
│ │ │ ├── VideoPlayerClosedCaptionMenuItem.kt
│ │ │ ├── VideoPlayerDanmakuMenuItem.kt
│ │ │ ├── VideoPlayerData.kt
│ │ │ ├── VideoPlayerMenuNavItem.kt
│ │ │ └── VideoPlayerPictureMenuItem.kt
│ │ │ ├── seekbar
│ │ │ ├── SeekBar.kt
│ │ │ ├── SeekBarThumb.kt
│ │ │ └── SeekMoveState.kt
│ │ │ └── util
│ │ │ ├── DanmakuMaskModifiers.kt
│ │ │ └── VideoShotExtends.kt
│ │ └── res
│ │ └── values
│ │ └── strings.xml
└── tv
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ └── kotlin
│ └── dev
│ └── aaa1115910
│ └── bv
│ └── player
│ └── tv
│ ├── BvPlayer.kt
│ ├── SeekBar.kt
│ └── controller
│ ├── BottomSubtitle.kt
│ ├── ControllerVideoInfo.kt
│ ├── MenuController.kt
│ ├── PlayStateTips.kt
│ ├── SeekController.kt
│ ├── SkipTip.kt
│ ├── VideoBottomController.kt
│ ├── VideoListController.kt
│ ├── VideoPlayerController.kt
│ ├── VideoShot.kt
│ └── playermenu
│ ├── ClosedCaptionMenu.kt
│ ├── DanmakuMenu.kt
│ ├── MenuNav.kt
│ ├── PictureMenu.kt
│ └── component
│ ├── CheckBoxMenuList.kt
│ ├── MenuListItem.kt
│ ├── RadioMenuList.kt
│ └── StepLessMenuItem.kt
├── screenshots.webp
├── screenshots1.webp
├── screenshots2.webp
├── settings.gradle.kts
└── utils
├── .gitignore
├── build.gradle.kts
├── consumer-rules.pro
├── proguard-rules.pro
└── src
└── main
├── AndroidManifest.xml
└── kotlin
└── dev
└── aaa1115910
└── bv
└── util
├── FirebaseUtil.kt
├── FocusRequesterExtends.kt
├── KLoggerExtends.kt
├── LongExtends.kt
├── SnapshotStateListExtends.kt
├── Timer.kt
├── ToastExtends.kt
├── createCustomInitialFocusRestorerModifiers.kt
└── ifElse.kt
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
--------------------------------------------------------------------------------
/.github/workflows/auto_close_issues.yml:
--------------------------------------------------------------------------------
1 | name: Check Issues
2 |
3 | on:
4 | issues:
5 | types: [opened]
6 | jobs:
7 | check:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - if: contains(github.event.issue.body, '我正在使用旧版本' )
11 | id: close-old-version
12 | name: Close Issue(template)
13 | uses: peter-evans/close-issue@v3
14 | with:
15 | comment: 请先尝试使用最新版本,如果问题依然存在再提交 issue
--------------------------------------------------------------------------------
/.github/workflows/close_inactive_issues.yml:
--------------------------------------------------------------------------------
1 | name: Close inactive issues
2 | on:
3 | schedule:
4 | - cron: "30 1 * * *"
5 |
6 | jobs:
7 | close-issues:
8 | name: Close inactive issues
9 | runs-on: ubuntu-latest
10 | if: github.repository == 'Leelion96/bv'
11 | permissions:
12 | issues: write
13 | steps:
14 | - uses: actions/stale@v5
15 | with:
16 | days-before-issue-stale: 60
17 | days-before-issue-close: 14
18 | days-before-pr-stale: -1
19 | stale-issue-label: "过时"
20 | stale-issue-message: "该 issue 已过时,因为它已经超过 60 天没有任何活动"
21 | close-issue-message: "该 issue 已关闭,因为它在被标记为过时后 14 天依旧没有任何活动"
22 | repo-token: ${{ secrets.GITHUB_TOKEN }}
23 | exempt-issue-labels: "bug,新功能,优化,有待讨论,疑难杂症"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .DS_Store
5 | /build
6 | /captures
7 | .externalNativeBuild
8 | .cxx
9 | /signing.properties
10 | /.idea/jarRepositories.xml
11 | /.idea/migrations.xml
12 | /.idea/codeStyles/
13 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "libs"]
2 | path = libs
3 | url = https://github.com/aaa1115910/bv-libs.git
4 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | /shelf/
2 | /workspace.xml
3 | /deploymentTargetDropDown.xml
4 | /gradle.xml
5 | /caches
6 | /libraries
7 | /modules.xml
8 | /navEditor.xml
9 | /assetWizardSettings.xml
10 | /misc.xml
11 | /compiler.xml
12 | /inspectionProfiles/Project_Default.xml
13 | /CamelCaseConfigNew.xml
14 | # GitHub Copilot persisted chat sessions
15 | /copilot/chatSessions
16 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 aaa1115910
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /google-services.json
3 | /release
4 | /r8Test
5 | /debug
--------------------------------------------------------------------------------
/app/compose_compiler_config.conf:
--------------------------------------------------------------------------------
1 | kotlin.collections.*
2 | kotlin.time.Duration
3 |
4 | kotlinx.coroutines.CoroutineScope
5 |
6 | androidx.paging.compose.LazyPagingItems
--------------------------------------------------------------------------------
/app/mobile/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/mobile/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/mobile/consumer-rules.pro
--------------------------------------------------------------------------------
/app/mobile/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/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/activities/FavoriteActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.activities
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
7 | import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
8 | import dev.aaa1115910.bv.mobile.screen.FavoriteScreen
9 | import dev.aaa1115910.bv.mobile.theme.BVMobileTheme
10 |
11 | class FavoriteActivity : ComponentActivity() {
12 | @OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
13 | override fun onCreate(savedInstanceState: Bundle?) {
14 | super.onCreate(savedInstanceState)
15 | setContent {
16 | val windowSize = calculateWindowSizeClass(this)
17 | BVMobileTheme {
18 | FavoriteScreen(
19 | windowSize = windowSize
20 | )
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/activities/FollowingSeasonActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.activities
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
7 | import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
8 | import dev.aaa1115910.bv.mobile.screen.FollowingSeasonScreen
9 | import dev.aaa1115910.bv.mobile.theme.BVMobileTheme
10 |
11 | class FollowingSeasonActivity : ComponentActivity() {
12 | @OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
13 | override fun onCreate(savedInstanceState: Bundle?) {
14 | super.onCreate(savedInstanceState)
15 | setContent {
16 | val windowSize = calculateWindowSizeClass(this)
17 | BVMobileTheme {
18 | FollowingSeasonScreen(
19 | windowSize = windowSize
20 | )
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/activities/FollowingUserActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.activities
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.mobile.screen.FollowingUserScreen
7 | import dev.aaa1115910.bv.mobile.theme.BVMobileTheme
8 |
9 | class FollowingUserActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVMobileTheme {
14 | FollowingUserScreen()
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/activities/HistoryActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.activities
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
7 | import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
8 | import dev.aaa1115910.bv.mobile.screen.HistoryScreen
9 | import dev.aaa1115910.bv.mobile.theme.BVMobileTheme
10 |
11 | class HistoryActivity : ComponentActivity() {
12 | @OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
13 | override fun onCreate(savedInstanceState: Bundle?) {
14 | super.onCreate(savedInstanceState)
15 | setContent {
16 | val windowSize = calculateWindowSizeClass(this)
17 | BVMobileTheme {
18 | HistoryScreen(
19 | windowSize = windowSize
20 | )
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/activities/LoginActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.activities
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.mobile.screen.LoginScreen
7 | import dev.aaa1115910.bv.mobile.theme.BVMobileTheme
8 |
9 | class LoginActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVMobileTheme {
14 | LoginScreen()
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/activities/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.activities
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
7 | import dev.aaa1115910.bv.mobile.screen.MobileMainScreen
8 | import dev.aaa1115910.bv.mobile.theme.BVMobileTheme
9 |
10 | class MainActivity : ComponentActivity() {
11 | override fun onCreate(savedInstanceState: Bundle?) {
12 | installSplashScreen()
13 | super.onCreate(savedInstanceState)
14 | setContent {
15 | BVMobileTheme {
16 | MobileMainScreen()
17 | }
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/activities/UserSpaceActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.activities
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.activity.ComponentActivity
7 | import androidx.activity.compose.setContent
8 | import dev.aaa1115910.bv.mobile.screen.UserSpaceScreen
9 | import dev.aaa1115910.bv.mobile.theme.BVMobileTheme
10 |
11 | class UserSpaceActivity : ComponentActivity() {
12 | companion object {
13 | fun actionStart(context: Context, mid: Long, name: String) {
14 | context.startActivity(
15 | Intent(context, UserSpaceActivity::class.java).apply {
16 | putExtra("mid", mid)
17 | putExtra("name", name)
18 | }
19 | )
20 | }
21 | }
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContent {
26 | BVMobileTheme {
27 | UserSpaceScreen()
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/kotlin/dev/aaa1115910/bv/mobile/screen/settings/details/DebugContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.mobile.screen.settings.details
2 |
3 | import androidx.compose.runtime.Composable
4 | import androidx.compose.ui.Modifier
5 |
6 | @Composable
7 | fun DebugContent(
8 | modifier: Modifier = Modifier
9 | ) {
10 |
11 | }
--------------------------------------------------------------------------------
/app/mobile/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 动态详情
4 | 我的收藏
5 | 我的追番
6 | 我的关注
7 | 历史记录
8 | 用户登录
9 | 设置
10 | 用户空间
11 | 视频播放
12 |
--------------------------------------------------------------------------------
/app/mobile/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/shared/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /src/main/res/raw/blacklist.bin
--------------------------------------------------------------------------------
/app/shared/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/consumer-rules.pro
--------------------------------------------------------------------------------
/app/shared/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/shared/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/app/shared/src/debug/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | BV Debug
4 |
--------------------------------------------------------------------------------
/app/shared/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/de/schnettler/datastore/manager/DataStoreManager.kt:
--------------------------------------------------------------------------------
1 | package de.schnettler.datastore.manager
2 |
3 | import androidx.datastore.core.DataStore
4 | import androidx.datastore.preferences.core.Preferences
5 | import androidx.datastore.preferences.core.edit
6 | import kotlinx.coroutines.flow.first
7 | import kotlinx.coroutines.flow.map
8 |
9 | class DataStoreManager(val dataStore: DataStore) {
10 | val preferenceFlow = dataStore.data
11 |
12 | suspend fun getPreference(preferenceEntry: PreferenceRequest) =
13 | preferenceFlow.first()[preferenceEntry.key] ?: preferenceEntry.defaultValue
14 |
15 | fun getPreferenceFlow(request: PreferenceRequest) =
16 | preferenceFlow.map {
17 | it[request.key] ?: request.defaultValue
18 | }
19 |
20 | suspend fun editPreference(key: Preferences.Key, newValue: T) {
21 | dataStore.edit { preferences ->
22 | preferences[key] = newValue
23 | }
24 | }
25 |
26 | suspend fun clearPreferences() {
27 | dataStore.edit { preferences -> preferences.clear() }
28 | }
29 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/de/schnettler/datastore/manager/PreferenceRequest.kt:
--------------------------------------------------------------------------------
1 | package de.schnettler.datastore.manager
2 |
3 | import androidx.datastore.preferences.core.Preferences
4 |
5 | open class PreferenceRequest(
6 | val key: Preferences.Key,
7 | val defaultValue: T,
8 | )
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/component/BottomTip.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.component
2 |
3 | import androidx.compose.foundation.layout.Column
4 | import androidx.compose.foundation.layout.height
5 | import androidx.compose.material.icons.Icons
6 | import androidx.compose.material.icons.outlined.Info
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.ui.Modifier
9 | import androidx.compose.ui.unit.dp
10 | import androidx.tv.material3.Icon
11 | import androidx.tv.material3.MaterialTheme
12 | import androidx.tv.material3.Text
13 |
14 | @Composable
15 | fun BottomTip(
16 | modifier: Modifier = Modifier,
17 | text: String
18 | ) {
19 | Column(
20 | modifier = modifier
21 | ) {
22 | Icon(
23 | modifier = Modifier.height(48.dp),
24 | imageVector = Icons.Outlined.Info,
25 | contentDescription = null,
26 | tint = MaterialTheme.colorScheme.onSurface
27 | )
28 | Text(
29 | text = text.replace("\n", "\n\n"),
30 | style = MaterialTheme.typography.bodySmall
31 | )
32 | }
33 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/component/buttons/CoinButton.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.component.buttons
2 |
3 | import androidx.compose.material.icons.Icons
4 | import androidx.compose.material.icons.outlined.Paid
5 | import androidx.compose.material.icons.rounded.Paid
6 | import androidx.compose.runtime.Composable
7 | import androidx.compose.ui.Modifier
8 | import androidx.compose.ui.tooling.preview.Preview
9 | import androidx.tv.material3.Button
10 | import androidx.tv.material3.Icon
11 |
12 | @Composable
13 | fun CoinButton(
14 | modifier: Modifier = Modifier,
15 | isCoined: Boolean,
16 | onClick: () -> Unit
17 | ) {
18 | Button(
19 | modifier = modifier,
20 | onClick = onClick,
21 | ) {
22 | Icon(
23 | imageVector = if (isCoined) Icons.Rounded.Paid else Icons.Outlined.Paid,
24 | contentDescription = null
25 | )
26 | }
27 | }
28 |
29 | @Preview
30 | @Composable
31 | fun CoinButtonPreview() {
32 | CoinButton(
33 | isCoined = false,
34 | onClick = {}
35 | )
36 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/dao/SearchHistoryDao.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.dao
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Delete
5 | import androidx.room.Insert
6 | import androidx.room.Query
7 | import androidx.room.Update
8 | import dev.aaa1115910.bv.entity.db.SearchHistoryDB
9 |
10 | @Dao
11 | interface SearchHistoryDao {
12 | @Query("SELECT * FROM search_history")
13 | suspend fun getAll(): List
14 |
15 | @Query("SELECT * FROM search_history ORDER BY search_date DESC LIMIT :count")
16 | suspend fun getHistories(count: Int): List
17 |
18 | @Query("SELECT * FROM search_history WHERE keyword = :keyword LIMIT 1")
19 | suspend fun findHistory(keyword: String): SearchHistoryDB?
20 |
21 | @Insert
22 | suspend fun insert(vararg searchHistoryDB: SearchHistoryDB)
23 |
24 | @Delete
25 | suspend fun delete(vararg searchHistoryDB: SearchHistoryDB)
26 |
27 | @Update
28 | suspend fun update(searchHistoryDB: SearchHistoryDB)
29 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/dao/UserDao.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.dao
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Delete
5 | import androidx.room.Insert
6 | import androidx.room.Query
7 | import androidx.room.Update
8 | import dev.aaa1115910.bv.entity.db.UserDB
9 |
10 | @Dao
11 | interface UserDao {
12 | @Query("SELECT * FROM user")
13 | suspend fun getAll(): List
14 |
15 | @Query("SELECT * FROM user WHERE uid = :uid LIMIT 1")
16 | suspend fun findUserByUid(uid: Long): UserDB?
17 |
18 | @Insert
19 | suspend fun insert(vararg userDB: UserDB)
20 |
21 | @Delete
22 | suspend fun delete(vararg userDB: UserDB)
23 |
24 | @Update
25 | suspend fun update(userDB: UserDB)
26 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/entity/PlayerType.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.entity
2 |
3 | enum class PlayerType {
4 | Media3
5 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/entity/ThemeType.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.entity
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.R
5 | import dev.aaa1115910.bv.util.stringRes
6 |
7 | enum class ThemeType(private val strRes: Int) {
8 | Auto(R.string.theme_type_auto),
9 | Dark(R.string.theme_type_dark),
10 | Light(R.string.theme_type_light);
11 |
12 | fun getDisplayName(context: Context): String = strRes.stringRes(context)
13 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/entity/carddata/VideoCardData.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.entity.carddata
2 |
3 | import dev.aaa1115910.bv.util.formatMinSec
4 |
5 | data class VideoCardData(
6 | val avid: Long,
7 | val title: String,
8 | val cover: String,
9 | val upName: String,
10 | val reason: String = "",
11 | val play: Int? = null,
12 | var playString: String = "",
13 | val danmaku: Int? = null,
14 | var danmakuString: String = "",
15 | val time: Long? = null,
16 | var timeString: String = "",
17 | val jumpToSeason: Boolean = false,
18 | val epId: Int? = null,
19 | val pubTime: String? = null,
20 | ) {
21 | init {
22 | play?.let {
23 | playString = if (it >= 10000) "${it / 10000}万" else "$it"
24 | }
25 | danmaku?.let {
26 | danmakuString = if (it >= 10000) "${it / 10000}万" else "$it"
27 | }
28 | time?.let {
29 | timeString = if (it > 0) it.formatMinSec() else ""
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/entity/db/SearchHistoryDB.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.entity.db
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 | import java.util.Date
7 |
8 | @Entity(tableName = "search_history")
9 | data class SearchHistoryDB(
10 | @PrimaryKey(autoGenerate = true) val id: Int? = null,
11 | @ColumnInfo(name = "keyword") val keyword: String,
12 | @ColumnInfo(name = "search_date") var searchDate: Date = Date(),
13 | )
14 |
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/entity/db/UserDB.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.entity.db
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 |
7 | @Entity(tableName = "user")
8 |
9 | data class UserDB(
10 | @PrimaryKey(autoGenerate = true) val id: Int? = null,
11 | @ColumnInfo(name = "uid") val uid: Long,
12 | @ColumnInfo(name = "username") var username: String,
13 | @ColumnInfo(name = "avatar") var avatar: String,
14 | @ColumnInfo(name = "auth") var auth: String,
15 | @ColumnInfo(name = "lock", defaultValue = "") var lock: String = "",
16 | )
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/entity/proxy/ProxyArea.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.entity.proxy
2 |
3 | import dev.aaa1115910.bv.util.Prefs
4 | import io.github.oshai.kotlinlogging.KotlinLogging
5 |
6 | enum class ProxyArea {
7 | MainLand, HongKong, TaiWan;
8 |
9 | companion object {
10 | private val logger = KotlinLogging.logger { }
11 | fun checkProxyArea(title: String): ProxyArea {
12 | val enableProxy = Prefs.enableProxy
13 | val proxyArea = when {
14 | !enableProxy -> MainLand
15 | title.contains(Regex("僅.*港")) -> HongKong
16 | title.contains(Regex("僅.*台")) -> TaiWan
17 | else -> MainLand
18 | }
19 | if (enableProxy) logger.debug { "Check proxy area: $title->$proxyArea" }
20 | return proxyArea
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/repository/VideoInfoRepository.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.repository
2 |
3 | import dev.aaa1115910.bv.player.entity.VideoListItem
4 |
5 | class VideoInfoRepository {
6 | val videoList = mutableListOf()
7 | }
8 |
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/util/EnumExtends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.biliapi.entity.season.FollowingSeasonStatus
5 | import dev.aaa1115910.biliapi.entity.season.FollowingSeasonType
6 | import dev.aaa1115910.bv.R
7 |
8 | fun FollowingSeasonStatus.getDisplayName(context: Context) = when (this) {
9 | FollowingSeasonStatus.All -> context.getString(R.string.following_season_status_all)
10 | FollowingSeasonStatus.Want -> context.getString(R.string.following_season_status_want)
11 | FollowingSeasonStatus.Watching -> context.getString(R.string.following_season_status_watching)
12 | FollowingSeasonStatus.Watched -> context.getString(R.string.following_season_status_watched)
13 | }
14 |
15 | fun FollowingSeasonType.getDisplayName(context: Context) = when (this) {
16 | FollowingSeasonType.Bangumi -> context.getString(R.string.following_season_type_bangumi)
17 | FollowingSeasonType.Cinema -> context.getString(R.string.following_season_type_film_and_television)
18 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/util/ImageExtends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | fun String.resizedImageUrl(size: ImageSize): String {
4 | return when (size) {
5 | ImageSize.Default -> this
6 | else -> "$this@${size.sizeString}.webp"
7 | }
8 | }
9 |
10 | enum class ImageSize(val sizeString: String) {
11 | Default(""),
12 | Cover("180h_288w_1c"),
13 | SmallVideoCardCover("400h_640w_1c"),
14 | SeasonCoverThumbnail("466h_622w")
15 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/util/NotYetImplemented.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import dev.aaa1115910.bv.BVApp
4 |
5 | fun notYetImplemented() {
6 | "Not yet implemented".toast(BVApp.context)
7 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/util/PgcTypeExtends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.biliapi.entity.pgc.PgcType
5 | import dev.aaa1115910.bv.R
6 |
7 | fun PgcType.getDisplayName(context: Context) = when (this) {
8 | PgcType.Anime -> R.string.pgc_type_anime
9 | PgcType.GuoChuang -> R.string.pgc_type_guochuang
10 | PgcType.Movie -> R.string.pgc_type_movie
11 | PgcType.Documentary -> R.string.pgc_type_documentary
12 | PgcType.Tv -> R.string.pgc_type_tv
13 | PgcType.Variety -> R.string.pgc_type_variety
14 | }.stringRes(context)
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/util/calculateWindowSizeClassInPreview.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
4 | import androidx.compose.material3.windowsizeclass.WindowSizeClass
5 | import androidx.compose.runtime.Composable
6 | import androidx.compose.ui.platform.LocalConfiguration
7 | import androidx.compose.ui.unit.DpSize
8 | import androidx.compose.ui.unit.dp
9 |
10 | @ExperimentalMaterial3WindowSizeClassApi
11 | @Composable
12 | fun calculateWindowSizeClassInPreview(): WindowSizeClass {
13 | val configuration = LocalConfiguration.current
14 | val size = DpSize(configuration.screenWidthDp.dp, configuration.screenHeightDp.dp)
15 | return WindowSizeClass.calculateFromSize(size)
16 | }
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/pgc/PgcAnimeViewModel.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.viewmodel.pgc
2 |
3 | import dev.aaa1115910.biliapi.repositories.PgcRepository
4 | import dev.aaa1115910.biliapi.entity.pgc.PgcType
5 |
6 | class PgcAnimeViewModel(
7 | override val pgcRepository: PgcRepository
8 | ) : PgcViewModel(
9 | pgcRepository = pgcRepository,
10 | pgcType = PgcType.Anime
11 | )
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/pgc/PgcDocumentaryViewModel.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.viewmodel.pgc
2 |
3 | import dev.aaa1115910.biliapi.repositories.PgcRepository
4 | import dev.aaa1115910.biliapi.entity.pgc.PgcType
5 |
6 | class PgcDocumentaryViewModel(
7 | override val pgcRepository: PgcRepository
8 | ) : PgcViewModel(
9 | pgcRepository = pgcRepository,
10 | pgcType = PgcType.Documentary
11 | )
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/pgc/PgcGuoChuangViewModel.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.viewmodel.pgc
2 |
3 | import dev.aaa1115910.biliapi.repositories.PgcRepository
4 | import dev.aaa1115910.biliapi.entity.pgc.PgcType
5 |
6 | class PgcGuoChuangViewModel(
7 | override val pgcRepository: PgcRepository
8 | ) : PgcViewModel(
9 | pgcRepository = pgcRepository,
10 | pgcType = PgcType.GuoChuang
11 | )
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/pgc/PgcMovieViewModel.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.viewmodel.pgc
2 |
3 | import dev.aaa1115910.biliapi.repositories.PgcRepository
4 | import dev.aaa1115910.biliapi.entity.pgc.PgcType
5 |
6 | class PgcMovieViewModel(
7 | override val pgcRepository: PgcRepository
8 | ) : PgcViewModel(
9 | pgcRepository = pgcRepository,
10 | pgcType = PgcType.Movie
11 | )
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/pgc/PgcTvViewModel.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.viewmodel.pgc
2 |
3 | import dev.aaa1115910.biliapi.repositories.PgcRepository
4 | import dev.aaa1115910.biliapi.entity.pgc.PgcType
5 |
6 | class PgcTvViewModel(
7 | override val pgcRepository: PgcRepository
8 | ) : PgcViewModel(
9 | pgcRepository = pgcRepository,
10 | pgcType = PgcType.Tv
11 | )
--------------------------------------------------------------------------------
/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/pgc/PgcVarietyViewModel.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.viewmodel.pgc
2 |
3 | import dev.aaa1115910.biliapi.repositories.PgcRepository
4 | import dev.aaa1115910.biliapi.entity.pgc.PgcType
5 |
6 | class PgcVarietyViewModel(
7 | override val pgcRepository: PgcRepository
8 | ) : PgcViewModel(
9 | pgcRepository = pgcRepository,
10 | pgcType = PgcType.Variety
11 | )
--------------------------------------------------------------------------------
/app/shared/src/main/proto/blacklist.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package dev.aaa1115910.bv;
4 |
5 | message BlacklistNano {
6 | int32 version = 1;
7 | int32 count = 2;
8 | repeated int64 uids = 3;
9 | }
--------------------------------------------------------------------------------
/app/shared/src/main/res/drawable/ic_banner.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/drawable/ic_banner.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/font/noto_sans_math_regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/font/noto_sans_math_regular.ttf
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-anydpi-v26/ic_banner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/shared/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/shared/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #FFFFFF
5 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 12dp
5 |
6 |
7 | 18dp
8 |
9 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
--------------------------------------------------------------------------------
/app/shared/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/shared/src/r8Test/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/shared/src/r8Test/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | BV R8 Test
4 |
--------------------------------------------------------------------------------
/app/shared/src/test/kotlin/android/util/Log.kt:
--------------------------------------------------------------------------------
1 | package android.util
2 |
3 | class Log {
4 | companion object {
5 | @JvmStatic
6 | fun isLoggable(tag: String, level: Int): Boolean {
7 | return true
8 | }
9 |
10 | @JvmStatic
11 | fun println(priority: Int, tag: String, msg: String): Int {
12 | println("[$tag] $msg")
13 | return 0
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/app/shared/src/test/kotlin/dev/aaa1115910/bv/network/GithubApiTest.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.network
2 |
3 | import kotlinx.coroutines.runBlocking
4 | import kotlin.test.Test
5 |
6 | class GithubApiTest {
7 | @Test
8 | fun `get latest release build`() = runBlocking {
9 | println(GithubApi.getLatestReleaseBuild())
10 | }
11 |
12 | @Test
13 | fun `get latest pre-release build`() = runBlocking {
14 | println(GithubApi.getLatestPreReleaseBuild())
15 | }
16 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/tv/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/tv/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/tv/consumer-rules.pro
--------------------------------------------------------------------------------
/app/tv/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/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/pgc/anime/AnimeTimelineActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.pgc.anime
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.main.pgc.anime.AnimeTimelineScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class AnimeTimelineActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | AnimeTimelineScreen()
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/search/SearchInputActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.search
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.runtime.remember
7 | import androidx.compose.ui.focus.FocusRequester
8 | import dev.aaa1115910.bv.tv.screens.search.SearchInputScreen
9 | import dev.aaa1115910.bv.ui.theme.BVTheme
10 |
11 | class SearchInputActivity : ComponentActivity() {
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | setContent {
15 | val defaultFocusRequester = remember { FocusRequester() }
16 | BVTheme {
17 | SearchInputScreen(defaultFocusRequester = defaultFocusRequester)
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/settings/LogsActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.settings
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.settings.LogsScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class LogsActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | LogsScreen()
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/settings/MediaCodecActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.settings
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.settings.MediaCodecScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class MediaCodecActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | MediaCodecScreen()
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/settings/SettingsActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.settings
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.runtime.remember
7 | import androidx.compose.ui.focus.FocusRequester
8 | import dev.aaa1115910.bv.tv.screens.settings.SettingsScreen
9 | import dev.aaa1115910.bv.ui.theme.BVTheme
10 |
11 | class SettingsActivity : ComponentActivity() {
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | setContent {
15 | BVTheme {
16 | val settingFocusRequester = remember { FocusRequester() }
17 | SettingsScreen(defaultFocusRequester = settingFocusRequester)
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/settings/SpeedTestActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.settings
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.settings.SpeedTestScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class SpeedTestActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | SpeedTestScreen()
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/FavoriteActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.user.FavoriteScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class FavoriteActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | FavoriteScreen()
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/FollowActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.user.FollowScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class FollowActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | FollowScreen()
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/FollowingSeasonActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.user.FollowingSeasonScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class FollowingSeasonActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | FollowingSeasonScreen()
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/HistoryActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.user.HistoryScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class HistoryActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | HistoryScreen()
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/LoginActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.login.LoginScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class LoginActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | LoginScreen()
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/ToViewActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | // import dev.aaa1115910.bv.screen.user.HistoryScreen
7 | import dev.aaa1115910.bv.tv.screens.user.ToViewScreen
8 | import dev.aaa1115910.bv.ui.theme.BVTheme
9 |
10 | class ToViewActivity : ComponentActivity() {
11 | override fun onCreate(savedInstanceState: Bundle?) {
12 | super.onCreate(savedInstanceState)
13 | setContent {
14 | BVTheme {
15 | // HistoryScreen()
16 | ToViewScreen()
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/UserInfoActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.user.UserInfoScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class UserInfoActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | UserInfoScreen()
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/UserLockSettingsActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.activity.ComponentActivity
7 | import androidx.activity.compose.setContent
8 | import dev.aaa1115910.bv.tv.screens.user.lock.UserLockSettingsScreen
9 | import dev.aaa1115910.bv.ui.theme.BVTheme
10 |
11 | class UserLockSettingsActivity : ComponentActivity() {
12 |
13 | companion object {
14 | fun actionStart(
15 | context: Context,
16 | uid: Long
17 | ) {
18 | context.startActivity(
19 | Intent(context, UserLockSettingsActivity::class.java).apply {
20 | putExtra("uid", uid)
21 | }
22 | )
23 | }
24 | }
25 |
26 | override fun onCreate(savedInstanceState: Bundle?) {
27 | super.onCreate(savedInstanceState)
28 | setContent {
29 | BVTheme {
30 | UserLockSettingsScreen()
31 | }
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/user/UserSwitchActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.user
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import dev.aaa1115910.bv.tv.screens.user.UserSwitchScreen
7 | import dev.aaa1115910.bv.ui.theme.BVTheme
8 |
9 | class UserSwitchActivity : ComponentActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContent {
13 | BVTheme {
14 | UserSwitchScreen()
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/video/TagActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.video
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.activity.ComponentActivity
7 | import androidx.activity.compose.setContent
8 | import dev.aaa1115910.bv.tv.screens.TagScreen
9 | import dev.aaa1115910.bv.ui.theme.BVTheme
10 |
11 | class TagActivity : ComponentActivity() {
12 | companion object {
13 | fun actionStart(context: Context, tagId: Int, tagName: String) {
14 | context.startActivity(
15 | Intent(context, TagActivity::class.java).apply {
16 | putExtra("tagId", tagId)
17 | putExtra("tagName", tagName)
18 | }
19 | )
20 | }
21 | }
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContent {
26 | BVTheme {
27 | TagScreen()
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/activities/video/UpInfoActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.activities.video
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.activity.ComponentActivity
7 | import androidx.activity.compose.setContent
8 | import dev.aaa1115910.bv.tv.screens.user.UpSpaceScreen
9 | import dev.aaa1115910.bv.ui.theme.BVTheme
10 |
11 | class UpInfoActivity : ComponentActivity() {
12 | companion object {
13 | fun actionStart(context: Context, mid: Long, name: String) {
14 | context.startActivity(
15 | Intent(context, UpInfoActivity::class.java).apply {
16 | putExtra("mid", mid)
17 | putExtra("name", name)
18 | }
19 | )
20 | }
21 | }
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContent {
26 | BVTheme {
27 | UpSpaceScreen()
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/HomeScreen.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/home/DynamicsScreen.kt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/home/DynamicsScreen.kt
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/login/LoginScreen.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.login
2 |
3 | import androidx.compose.runtime.Composable
4 | import androidx.compose.ui.Modifier
5 |
6 | @Composable
7 | fun LoginScreen(
8 | modifier: Modifier = Modifier
9 | ) {
10 | /*when (Prefs.apiType) {
11 | ApiType.Http -> {
12 | WebQRLoginContent(modifier)
13 | }
14 |
15 | ApiType.GRPC -> {
16 | SmsLoginContent(modifier)
17 | }
18 | }*/
19 | AppQRLoginContent(modifier)
20 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/AiContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun AiContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { AiChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun AiChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.aiList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/AnimalContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun AnimalContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { AnimalChildRegionButtons() },
17 | )
18 | }
19 |
20 | @Composable
21 | fun AnimalChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.animalList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/CarContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun CarContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { CarChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun CarChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.carList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/CinephileContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun CinephileContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { CinephileChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun CinephileChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.cinephileList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/DanceContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun DanceContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { DanceChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun DanceChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.danceList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/DougaContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun DougaContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { DougaChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun DougaChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.dougaList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/EmotionContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun EmotionContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { EmotionChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun EmotionChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.emotionList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/EntContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun EntContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { EntChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun EntChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.entList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/FashionContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun FashionContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { FashionChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun FashionChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.fashionList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/FoodContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun FoodContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { FoodChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun FoodChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.foodList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/GameContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun GameContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { GameChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun GameChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.gameList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/GymContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun GymContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { GymChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun GymChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.gymList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/HandmakeContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun HandmakeContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { HandmakeChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun HandmakeChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.handmakeList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/HomeContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun HomeContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { HomeChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun HomeChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.homeList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/InformationContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun InformationContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { InformationChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun InformationChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.informationList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/KichikuContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun KichikuContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { KichikuChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun KichikuChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.kichikuList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/KnowledgeContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun KnowledgeContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { KnowledgeChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun KnowledgeChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.knowledgeList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/LifeExperienceContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun LifeExperienceContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { LifeExperienceChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun LifeExperienceChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.lifeExperienceList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/LifeJoyContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun LifeJoyContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { LifeJoyChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun LifeJoyChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.lifeJoyList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/MuiscContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun MusicContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { MusicChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun MusicChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.musicList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/MysticismContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun MysticismContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { MysticismChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun MysticismChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.mysticismList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/OutdoorsContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun OutdoorsContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { OutdoorsChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun OutdoorsChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.outdoorsList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/PaintingContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun PaintingContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { PaintingChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun PaintingChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.paintingList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/ParentingContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun ParentingContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { ParentingChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun ParentingChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.parentingList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/RuralContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun RuralContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { RuralChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun RuralChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.ruralList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/ShortPlayContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun ShortPlayContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { ShortPlayChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun ShortPlayChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.shortplayList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/SportsContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun SportsContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { SportsChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun SportsChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.sportsList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/TechContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun TechContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { TechChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun TechChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.techList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/TravelContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun TravelContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { TravelChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun TravelChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.travelList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/VlogContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun VlogContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { VlogChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun VlogChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.vlogList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/kotlin/dev/aaa1115910/bv/tv/screens/main/ugc/healthContent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.tv.screens.main.ugc
2 |
3 | import androidx.compose.foundation.layout.fillMaxWidth
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import dev.aaa1115910.biliapi.entity.ugc.UgcTypeV2
7 |
8 | @Composable
9 | fun HealthContent(
10 | modifier: Modifier = Modifier,
11 | state: UgcScaffoldState
12 | ) {
13 | UgcRegionScaffold(
14 | modifier = modifier,
15 | state = state,
16 | childRegionButtons = { HealthChildRegionButtons() }
17 | )
18 | }
19 |
20 | @Composable
21 | fun HealthChildRegionButtons(modifier: Modifier = Modifier) {
22 | UgcChildRegionButtons(
23 | modifier = modifier.fillMaxWidth(),
24 | childUgcTypes = UgcTypeV2.healthList
25 | )
26 | }
--------------------------------------------------------------------------------
/app/tv/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/bili-api-grpc/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/api/ticket/v1/ticket.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.api.ticket.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | service Ticket {
8 | // 获取鉴权用 Ticket
9 | rpc GetTicket (GetTicketRequest) returns (GetTicketResponse);
10 | }
11 |
12 | //
13 | message GetTicketRequest {
14 | // 包含:
15 | // + x-fingerprint(包含手机各类信息, 使用 datacenter.hakase.protobuf.AndroidDeviceInfo 生成)
16 | // + x-exbadbasket(?)
17 | map context = 1;
18 | // 暂时固定为 ec01
19 | string key_id = 2;
20 | //
21 | bytes sign = 3;
22 | // 暂时留空
23 | string token = 4;
24 | }
25 |
26 | //
27 | message GetTicketResponse {
28 | //
29 | message Context {
30 | //
31 | string v_voucher = 1;
32 | }
33 | // x-bili-ticket
34 | string ticket = 1;
35 | // 有效期起
36 | int64 created_at = 2;
37 | // 有效期
38 | int64 ttl = 3;
39 | //
40 | Context context = 4;
41 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/archive/middleware/v1/preload.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.archive.middleware.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 视频秒开参数
8 | message PlayerArgs {
9 | // 清晰度
10 | int64 qn = 1;
11 | // 流版本
12 | int64 fnver = 2;
13 | // 流类型
14 | int64 fnval = 3;
15 | // 返回url是否强制使用域名
16 | // 0:不强制使用域名 1:http域名 2:https域名
17 | int64 force_host = 4;
18 | // 音量均衡
19 | int64 voice_balance = 5;
20 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/card/v1/card.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.card.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/card/v1/single.proto";
8 |
9 | // 卡片信息
10 | message Card {
11 | oneof item {
12 | // 小封面条目
13 | SmallCoverV5 small_cover_v5 = 1;
14 | //
15 | LargeCoverV1 large_cover_v1 = 2;
16 | //
17 | ThreeItemAllV2 three_item_all_v2 = 3;
18 | //
19 | ThreeItemV1 three_item_v1 = 4;
20 | //
21 | HotTopic hot_topic = 5;
22 | //
23 | DynamicHot three_item_h_v5 = 6;
24 | //
25 | MiddleCoverV3 middle_cover_v3 = 7;
26 | //
27 | LargeCoverV4 large_cover_v4 = 8;
28 | // 热门列表顶部按钮
29 | PopularTopEntrance popular_top_entrance = 9;
30 | //
31 | RcmdOneItem rcmd_one_item = 10;
32 | //
33 | SmallCoverV5Ad small_cover_v5_ad = 11;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/distribution/setting/download.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.distribution.setting.download;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/distribution/v1/distribution.proto";
8 |
9 | //
10 | message DownloadSettingsConfig {
11 | //
12 | bilibili.app.distribution.v1.BoolValue enable_download_auto_start = 1;
13 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/distribution/setting/dynamic.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.distribution.setting.dynamic;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/distribution/v1/distribution.proto";
8 |
9 | //
10 | message DynamicAutoPlay {
11 | //
12 | bilibili.app.distribution.v1.Int64Value value = 1;
13 | }
14 |
15 | //
16 | message DynamicDeviceConfig {
17 | //
18 | DynamicAutoPlay auto_play = 1;
19 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/distribution/setting/internaldevice.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.distribution.setting.internaldevice;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/distribution/v1/distribution.proto";
8 |
9 | //
10 | message InternalDeviceConfig {
11 | // 首次启动时间
12 | bilibili.app.distribution.v1.Int64Value fts = 1;
13 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/distribution/setting/night.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.distribution.setting.night;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/distribution/v1/distribution.proto";
8 |
9 | //
10 | message NightSettingsConfig {
11 | //
12 | bilibili.app.distribution.v1.BoolValue is_night_follow_system = 1;
13 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/distribution/setting/other.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.distribution.setting.other;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/distribution/v1/distribution.proto";
8 |
9 | //
10 | message OtherSettingsConfig {
11 | //
12 | bilibili.app.distribution.v1.Int64Value watermark_type = 1;
13 | //
14 | bilibili.app.distribution.v1.Int64Value web_image_quality_type = 2;
15 | //
16 | bilibili.app.distribution.v1.BoolValue enable_read_pasteboard = 3;
17 | //
18 | bilibili.app.distribution.v1.BoolValue paste_auto_jump = 4;
19 | //
20 | bilibili.app.distribution.v1.BoolValue mini_screen_play_when_back = 5;
21 | //
22 | bilibili.app.distribution.v1.BoolValue enable_resume_playing = 6;
23 | //
24 | bilibili.app.distribution.v1.BoolValue enable_wifi_auto_update = 7;
25 | //
26 | bilibili.app.distribution.v1.BoolValue enable_guide_screenshot_share = 8;
27 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/distribution/setting/privacy.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.distribution.setting.privacy;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/distribution/v1/distribution.proto";
8 |
9 | //
10 | message MidPrivacySettingsConfig {
11 | //
12 | bilibili.app.distribution.v1.BoolValue recommend_to_known = 1;
13 | }
14 |
15 | //
16 | message PrivacySettingsConfig {
17 | //
18 | bilibili.app.distribution.v1.BoolValue ad_recommand_store = 1;
19 | // 传感器权限
20 | bilibili.app.distribution.v1.BoolValue sensor_access = 2;
21 |
22 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/distribution/setting/search.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.distribution.setting.search;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/app/distribution/v1/distribution.proto";
8 |
9 | //
10 | message SearchAutoPlay {
11 | //
12 | bilibili.app.distribution.v1.Int64Value value = 1;
13 | //
14 | bilibili.app.distribution.v1.BoolValue affected_by_server_side = 2;
15 | }
16 |
17 | //
18 | message SearchDeviceConfig {
19 | //
20 | SearchAutoPlay auto_play = 1;
21 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/dynamic/common/dynamic.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.dynamic.common;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | message ItemWHRatio {
9 | //
10 | int32 ratio = 1;
11 | //
12 | int32 width = 2;
13 | //
14 | int32 height = 3;
15 | }
16 |
17 | //
18 | enum WHRatio {
19 | W_H_RATIO_1_1 = 0;
20 | W_H_RATIO_16_9 = 1;
21 | W_H_RATIO_3_4 = 2;
22 | W_H_RATIO_CUSTOM = 3;
23 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/playerunite/pgcanymodel/PGCAnyModel.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.playerunite.pgcanymodel;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/pgc/gateway/player/v2/playurl.proto";
8 |
9 | message PGCAnyModel {
10 | bilibili.pgc.gateway.player.v2.PlayViewBusinessInfo business = 3;
11 | bilibili.pgc.gateway.player.v2.Event event = 4;
12 | bilibili.pgc.gateway.player.v2.ViewInfo view_info = 5;
13 | bilibili.pgc.gateway.player.v2.PlayAbilityExtConf play_ext_conf = 6;
14 | //bilibili.pgc.gateway.player.v2.PlayExtInfo play_ext_info = 7;
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/playerunite/ugcanymodel/UGCAnyModel.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.playerunite.ugcanymodel;
4 |
5 | option java_multiple_files = true;
6 |
7 | message ButtonStyle {
8 | string text = 1;
9 | string text_color = 2;
10 | string bg_color = 3;
11 | string jump_link = 4;
12 | }
13 |
14 | enum PlayLimitCode {
15 | PLC_UNKNOWN = 0;
16 | PLC_NOTPAYED = 1;
17 | }
18 |
19 | message PlayLimit {
20 | PlayLimitCode code = 1;
21 | string message = 2;
22 | string sub_message = 3;
23 | ButtonStyle button = 4;
24 | }
25 |
26 | message UGCAnyModel {
27 | PlayLimit play_limit = 1;
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/show/gateway/v1/service.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.show.gateway.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "bilibili/broadcast/message/main/native.proto";
8 |
9 | //
10 | service AppShow {
11 | // 获取Native页进度数据
12 | rpc GetActProgress (GetActProgressReq) returns (GetActProgressReply);
13 | }
14 |
15 | // 获取Native页进度数据-请求
16 | message GetActProgressReq {
17 | // Native页id
18 | int64 pageID = 1;
19 | // 用户mid
20 | int64 mid = 2;
21 | }
22 |
23 | // 获取Native页进度数据-响应
24 | message GetActProgressReply {
25 | // 进度数据
26 | bilibili.broadcast.message.main.NativePageEvent event = 1;
27 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/show/mixture/v1/mixture.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.show.mixture.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | service Mixture {
9 | //
10 | rpc Widget(WidgetReq) returns (WidgetReply);
11 | }
12 |
13 | //
14 | message RcmdReason {
15 | //
16 | string content = 1;
17 | //
18 | uint32 corner_mark = 2;
19 | }
20 |
21 | //
22 | message WidgetItem {
23 | //
24 | string cover = 1;
25 | //
26 | string view = 2;
27 | //
28 | RcmdReason rcmd_reason = 3;
29 | //
30 | string title = 4;
31 | //
32 | string name = 5;
33 | //
34 | string uri = 6;
35 | //
36 | string goto = 7;
37 | //
38 | int64 id = 8;
39 | //
40 | int32 view_icon = 9;
41 | }
42 |
43 | //
44 | message WidgetReply {
45 | //
46 | repeated WidgetItem item = 1;
47 | }
48 |
49 | //
50 | message WidgetReq {
51 | //
52 | string from_spmid = 1;
53 | //
54 | uint32 page_no = 2;
55 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/show/region/v1/region.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.show.region.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | service Region {
9 | //
10 | rpc Region (RegionReq) returns (RegionReply);
11 | }
12 |
13 | //
14 | message RegionConfig {
15 | //
16 | string scenes_name = 1;
17 | //
18 | string scenes_type = 2;
19 | }
20 |
21 | //
22 | message RegionInfo {
23 | //
24 | int32 tid = 1;
25 | //
26 | int32 reid = 2;
27 | //
28 | string name = 3;
29 | //
30 | string logo = 4;
31 | //
32 | string goto = 5;
33 | //
34 | string param = 6;
35 | //
36 | string uri = 7;
37 | //
38 | int32 type = 8;
39 | //
40 | int32 is_bangumi = 9;
41 | //
42 | repeated RegionInfo children = 10;
43 | //
44 | repeated RegionConfig config = 11;
45 | }
46 |
47 | //
48 | message RegionReply {
49 | //
50 | repeated RegionInfo regions = 1;
51 | }
52 |
53 | //
54 | message RegionReq {
55 | //
56 | string lang = 1;
57 | }
58 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/app/wall/v1/wall.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.app.wall.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 免流规则
8 | service Wall {
9 | // 获取免流规则信息
10 | rpc RuleInfo (RuleRequest) returns (RulesReply);
11 | }
12 |
13 | // 免流规则信息
14 | message RuleInfo {
15 | // 是否支持免流
16 | bool tf = 1;
17 | // 操作模式
18 | // break:无 replace:替换 proxy:代理
19 | string m = 2;
20 | // 操作参数
21 | string a = 3;
22 | // 匹配目标正则
23 | string p = 4;
24 | //
25 | repeated string a_backup = 5;
26 | }
27 |
28 | // 获取免流规则信息-请求
29 | message RuleRequest {}
30 |
31 | // 免流规则信息组
32 | message RulesInfo {
33 | // 免流规则信息
34 | repeated RuleInfo rulesInfo = 1;
35 | }
36 |
37 | // 获取免流规则信息-响应
38 | message RulesReply {
39 | // 各ISP的免流规则信息组
40 | // ISP如: cu ct cm
41 | map rulesInfo = 1;
42 | //
43 | string hash_value = 2;
44 | }
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/editor/notify.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.editor;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 |
9 | //
10 | service OperationNotify {
11 | //
12 | rpc OperationNotify(google.protobuf.Empty) returns (stream Notify);
13 | }
14 |
15 | message Notify {
16 | // 消息唯一标示
17 | int64 msg_id = 1;
18 | // 消息类型
19 | int32 msg_type = 2;
20 | // 接收方uid
21 | int64 receiver_uid = 3;
22 | //接收方类型
23 | int32 receiver_type = 4;
24 | // 故事的版本
25 | int64 story_version = 5;
26 | // 操作结果的hash值
27 | int64 op_hash = 6;
28 | // 操作产生用户的uid
29 | int64 op_sender = 7;
30 | // patch内容
31 | string op_content = 8;
32 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/esports/notify.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.esports;
4 |
5 | option java_multiple_files = true;
6 |
7 | message Notify {
8 | // cid
9 | int64 cid = 1;
10 | }
11 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/fission/notify.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.fission;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 |
9 | //
10 | service Fission {
11 | //
12 | rpc GameNotify(google.protobuf.Empty) returns (stream GameNotifyReply);
13 | }
14 |
15 | message GameNotifyReply {
16 | // 类型字段
17 | uint32 type = 1;
18 | // 数据字段
19 | string data = 2;
20 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/main/native.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.main;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 |
9 | //
10 | service NativePage {
11 | //
12 | rpc WatchNotify(google.protobuf.Empty) returns (stream NativePageEvent);
13 | }
14 |
15 | //
16 | message NativePageEvent {
17 | // Native页ID
18 | int64 PageID = 1;
19 | //
20 | repeated EventItem Items = 2;
21 | }
22 |
23 | //
24 | message EventItem {
25 | // 组件标识
26 | int64 ItemID = 1;
27 | // 组件类型
28 | string Type = 2;
29 | // 进度条数值
30 | int64 Num = 3;
31 | // 进度条展示数值
32 | string DisplayNum = 4;
33 | // h5的组件标识
34 | string WebKey = 5;
35 | // 活动统计维度
36 | // 0:用户维度 1:规则维度
37 | int64 dimension = 6;
38 | }
39 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/main/search.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.main;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 | import "bilibili/app/dynamic/v2/dynamic.proto";
9 |
10 | service Search {
11 | rpc ChatResultPush (google.protobuf.Empty) returns (stream ChatResult);
12 | }
13 |
14 | //
15 | message Bubble {
16 | repeated bilibili.app.dynamic.v2.Paragraph paragraphs = 1;
17 | }
18 |
19 | //
20 | message ChatResult {
21 | //
22 | int32 code = 1;
23 | //
24 | string session_id = 2;
25 | //
26 | repeated Bubble bubble = 3;
27 | //
28 | string rewrite_word = 4;
29 | //
30 | string title = 5;
31 | }
32 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/note/sync.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.note;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | message Sync {
9 | // 笔记id
10 | int64 note_id = 1;
11 | // 唯一标示
12 | string hash = 2;
13 | }
14 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/ogv/live.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.ogv;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 开播事件
8 | message LiveStartEvent {}
9 |
10 | // 直播中止事件
11 | message LiveEndEvent {}
12 |
13 | // 在线人数事件
14 | message LiveOnlineEvent {
15 | //在线人数
16 | int64 online = 1;
17 | }
18 |
19 | // 变更通知
20 | message LiveUpdateEvent {
21 | // 直播后状态
22 | // 1:下线 2:转点播
23 | int32 after_premiere_type = 1;
24 | // 直播开始绝对时间 单位ms
25 | int64 start_time = 2;
26 | // id
27 | string id = 3;
28 | // 服务端播放进度,未打散,负数表示距离开播时间,正数表示已开播时间,单位:毫秒
29 | // 用户实际播放进度:progress - delay_time
30 | int64 progress = 4;
31 | }
32 |
33 | // 直播间事件
34 | message CMDBody {
35 | //命令类型
36 | oneof event {
37 | // 开播事件
38 | LiveStartEvent start = 1;
39 | // 直播中止事件
40 | LiveEndEvent emergency = 2;
41 | // 在线人数事件
42 | LiveOnlineEvent online = 3;
43 | // 变更通知
44 | LiveUpdateEvent update = 4;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/message/ticket/activitygame.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.message.ticket;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | enum RoomStatus {
9 | // 暂停:
10 | Pause = 0;
11 | // 播放:
12 | Play = 1;
13 | // 终止:
14 | End = 2;
15 | }
16 |
17 | // 推送选项
18 | message RoomEvent {
19 | // RoomStatus 类型
20 | RoomStatus room_status = 1;
21 | //
22 | string room_message = 2;
23 | }
24 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/v1/laser.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 |
9 | // Laser
10 | service Laser {
11 | // 监听上报事件
12 | rpc WatchLogUploadEvent(google.protobuf.Empty) returns (stream LaserLogUploadResp);
13 | }
14 |
15 | // 服务端下发日志上报事件
16 | message LaserLogUploadResp {
17 | // 任务id
18 | int64 taskid = 1;
19 | // 下发时间
20 | string date = 2;
21 | }
22 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/v1/mod.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 |
9 | // ModManager
10 | service ModManager {
11 | //
12 | rpc WatchResource(google.protobuf.Empty) returns (stream ModResourceResp);
13 | }
14 |
15 | //
16 | message ModResourceResp {
17 | //
18 | int32 atcion = 1;
19 | //
20 | string app_key = 2;
21 | //
22 | string pool_name = 3;
23 | //
24 | string module_name = 4;
25 | //
26 | int64 module_version = 5;
27 | //
28 | int64 list_version = 6;
29 | }
30 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/v1/test.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/any.proto";
8 | import "google/protobuf/empty.proto";
9 |
10 | // 服务端下发的测试专用消息,客户端debug/release包都会通过弹窗响应该消息
11 | // 后端平台 必须 限制该消息只能针对单个用户发送
12 |
13 | // Test
14 | service Test {
15 | // 监听上报事件
16 | rpc WatchTestEvent(google.protobuf.Empty) returns (stream TestResp);
17 | }
18 |
19 | //
20 | service Test2 {
21 | //
22 | rpc Test(AddParams) returns (google.protobuf.Empty);
23 | }
24 |
25 | //
26 | message AddParams {
27 | //
28 | int32 a = 1;
29 | //
30 | int32 b = 2;
31 | }
32 |
33 | //
34 | message AddResult {
35 | //
36 | int32 r = 1;
37 | }
38 |
39 | message TestResp {
40 | // 任务id
41 | int64 taskid = 1;
42 | // 时间戳
43 | int64 timestamp = 2;
44 | // 消息
45 | string message = 3;
46 | // 扩展
47 | google.protobuf.Any extra = 4;
48 | }
49 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/broadcast/v2/laser.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.broadcast.v2;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 |
9 | // Laser
10 | service Laser {
11 | // 监听Laser事件
12 | rpc WatchEvent(google.protobuf.Empty) returns (stream LaserEventResp);
13 | }
14 |
15 | // 服务端下发Laser事件
16 | message LaserEventResp {
17 | // 任务id
18 | int64 taskid = 1;
19 | // 指令名
20 | string action = 2;
21 | // 指令参数json字符串
22 | string params = 3;
23 | }
24 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/community/service/govern/v1/govern.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.community.service.govern.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/empty.proto";
8 |
9 | //
10 | service Qoe {
11 | //
12 | rpc QoeReport (QoeReportReq) returns (google.protobuf.Empty);
13 | }
14 |
15 | //
16 | message QoeReportReq {
17 | //
18 | int64 id = 1;
19 | //
20 | int64 scene = 2;
21 | //
22 | int32 type = 3;
23 | //
24 | bool cancel = 4;
25 | //
26 | string business_type = 5;
27 | //
28 | int64 oid = 6;
29 | //
30 | QoeScoreResult score_result = 7;
31 | //
32 | string business_data = 8;
33 | }
34 |
35 | //
36 | message QoeScoreResult {
37 | //
38 | float score = 1;
39 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/im/interfaces/inner-interface/v1/api.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.im.interface.inner.interface.v1;
4 |
5 | option java_multiple_files = true;
6 | option java_package = "bilibili.im.interfaces.inner.interface1.v1";
7 |
8 | //
9 | service InnerInterface {
10 | //
11 | rpc UpdateListInn(ReqOpBlacklist) returns(RspOpBlacklist);
12 | }
13 |
14 | //
15 | message BanUser {
16 | // 用户mid
17 | uint64 uid = 1;
18 | // 封禁业务
19 | int32 limit = 2;
20 | // 封禁时间
21 | int32 time = 3;
22 | // 模式
23 | // 1:add 2:remove
24 | int32 mode = 4;
25 | }
26 |
27 | //
28 | message ReqOpBlacklist {
29 | // 需要封禁/解封的用户信息
30 | repeated BanUser ban_users = 1;
31 | }
32 |
33 | //
34 | message RspOpBlacklist {
35 | //
36 | repeated uint64 failed_users = 1;
37 | }
38 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/main/common/arch/doll/v1/doll.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.main.common.arch.doll.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | service Echo {
9 | //
10 | rpc Ping(PingRequest) returns(PingResponse);
11 | //
12 | rpc Say(SayRequest) returns(SayResponse);
13 | //
14 | rpc Error(ErrorRequest) returns(ErrorResponse);
15 | }
16 |
17 | //
18 | message ErrorRequest {
19 | //
20 | int32 error = 2;
21 | //
22 | int64 time = 1;
23 | //
24 | int64 delay = 3;
25 | }
26 |
27 | //
28 | message ErrorResponse {
29 | //
30 | string host = 1;
31 | //
32 | int64 time = 3;
33 | }
34 |
35 | //
36 | message PingRequest {
37 | //
38 | int64 time = 1;
39 | }
40 |
41 | //
42 | message PingResponse {
43 | //
44 | string host = 1;
45 | //
46 | int64 time = 3;
47 | }
48 |
49 | //
50 | message SayRequest {
51 | //
52 | string content = 1;
53 | }
54 |
55 | //
56 | message SayResponse {
57 | //
58 | string host = 1;
59 | //
60 | string content = 2;
61 | //
62 | int64 time = 3;
63 | }
64 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/metadata/device/device.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.metadata.device;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 设备信息
8 | // gRPC头部:x-bili-device-bin
9 | message Device {
10 | // 产品id
11 | // 粉 白 蓝 直播姬 HD 海外 OTT 漫画 TV野版 小视频 网易漫画 网易漫画 网易漫画HD 国际版 东南亚版
12 | // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 30
13 | int32 app_id = 1;
14 | // 构建id
15 | int32 build = 2;
16 | // 设备buvid
17 | string buvid = 3;
18 | // 包类型
19 | string mobi_app = 4;
20 | // 平台类型
21 | // ios android
22 | string platform = 5;
23 | // 设备类型
24 | string device = 6;
25 | // 渠道
26 | string channel = 7;
27 | // 手机品牌
28 | string brand = 8;
29 | // 手机型号
30 | string model = 9;
31 | // 系统版本
32 | string osver = 10;
33 | // 本地设备指纹
34 | string fp_local = 11;
35 | // 远程设备指纹
36 | string fp_remote = 12;
37 | // APP版本号
38 | string version_name = 13;
39 | // 设备指纹, 不区分本地或远程设备指纹,作为推送目标的索引
40 | string fp = 14;
41 | // 首次启动时的毫秒时间戳
42 | int64 fts = 15;
43 | }
44 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/metadata/fawkes/fawkes.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.metadata.fawkes;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | message FawkesReply {
9 | // 客户端在fawkes系统中对应的已发布最新的config版本号
10 | string config = 1;
11 | // 客户端在fawkes系统中对应的已发布最新的ff版本号
12 | string ff = 2;
13 | }
14 |
15 | //
16 | message FawkesReq {
17 | // 客户端在fawkes系统的唯一名, 如 `android64`
18 | string appkey = 1;
19 | // 客户端在fawkes系统中的环境参数, 如 `prod`
20 | string env = 2;
21 | // 启动id, 8 位 0~9, a~z 组成的字符串
22 | string session_id = 3;
23 | }
24 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/metadata/locale/locale.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.metadata.locale;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 区域标识
8 | // gRPC头部:x-bili-locale-bin
9 | message Locale {
10 | // App设置的locale
11 | LocaleIds c_locale = 1;
12 | // 系统默认的locale
13 | LocaleIds s_locale = 2;
14 | // sim卡的国家码+运营商码
15 | string sim_code = 3;
16 | // 时区
17 | string timezone = 4;
18 | }
19 |
20 | // Defined by https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html
21 | message LocaleIds {
22 | // A language designator is a code that represents a language.
23 | string language = 1;
24 | // Writing systems.
25 | string script = 2;
26 | // A region designator is a code that represents a country or an area.
27 | string region = 3;
28 | }
29 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/metadata/metadata.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.metadata;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 请求元数据
8 | // gRPC头部:x-bili-metadata-bin
9 | message Metadata {
10 | // 登录 access_key
11 | string access_key = 1;
12 | // 包类型, 如 `android`
13 | string mobi_app = 2;
14 | // 运行设备, 留空即可
15 | string device = 3;
16 | // 构建id, 如 `7380300`
17 | int32 build = 4;
18 | // APP分发渠道, 如 `master`
19 | string channel = 5;
20 | // 设备唯一标识
21 | string buvid = 6;
22 | // 平台类型, 如 `android`
23 | string platform = 7;
24 | }
25 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/metadata/network/network.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.metadata.network;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 网络类型标识
8 | // gRPC头部:x-bili-network-bin
9 | message Network {
10 | // 网络类型
11 | NetworkType type = 1;
12 | // 免流类型
13 | TFType tf = 2;
14 | // 运营商
15 | string oid = 3;
16 | }
17 |
18 | // 网络类型
19 | enum NetworkType {
20 | NT_UNKNOWN = 0; // 未知
21 | WIFI = 1; // WIFI
22 | CELLULAR = 2; // 蜂窝网络
23 | OFFLINE = 3; // 未连接
24 | OTHERNET = 4; // 其他网络
25 | ETHERNET = 5; // 以太网
26 | }
27 |
28 | // 免流类型
29 | enum TFType {
30 | TF_UNKNOWN = 0; // 正常计费
31 | U_CARD = 1; // 联通卡
32 | U_PKG = 2; // 联通包
33 | C_CARD = 3; // 移动卡
34 | C_PKG = 4; // 移动包
35 | T_CARD = 5; // 电信卡
36 | T_PKG = 6; // 电信包
37 | }
38 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/metadata/parabox/parabox.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.metadata.parabox;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | message Exp {
9 | //
10 | int64 id = 1;
11 | //
12 | int32 bucket = 2;
13 | }
14 |
15 | //
16 | message Exps {
17 | //
18 | repeated Exp exps = 1;
19 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/metadata/restriction/restriction.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.metadata.restriction;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 模式类型
8 | enum ModeType {
9 | NORMAL = 0; // 正常模式
10 | TEENAGERS = 1; // 青少年模式
11 | LESSONS = 2; // 课堂模式
12 | }
13 |
14 | // 限制条件
15 | message Restriction {
16 | // 青少年模式开关状态
17 | bool teenagers_mode = 1;
18 | // 课堂模式开关状态
19 | bool lessons_mode = 2;
20 | // 模式类型(旧版)
21 | ModeType mode = 3;
22 | // app 审核review状态
23 | bool review = 4;
24 | // 客户端是否选择关闭个性化推荐
25 | bool disable_rcmd = 5;
26 | }
27 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/pagination/pagination.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.pagination;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 分页信息
8 | message FeedPagination {
9 | //
10 | int32 page_size = 1;
11 | //
12 | string offset = 2;
13 | //
14 | bool is_refresh = 3;
15 | }
16 |
17 | // 分页信息
18 | message FeedPaginationReply {
19 | //
20 | string next_offset = 1;
21 | //
22 | string prev_offset = 2;
23 | //
24 | string last_read_offset = 3;
25 | }
26 |
27 | // 分页信息
28 | message Pagination {
29 | //
30 | int32 page_size = 1;
31 | //
32 | string next = 2;
33 | }
34 |
35 | // 分页信息
36 | message PaginationReply {
37 | //
38 | string next = 1;
39 | //
40 | string prev = 2;
41 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/pgc/service/premiere/v1/premiere.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.pgc.service.premiere.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | // 首播服务
8 | service Premiere {
9 | // 获取首播状态
10 | rpc Status (PremiereStatusReq) returns (PremiereStatusReply);
11 | }
12 |
13 | // 获取首播状态-请求
14 | message PremiereStatusReq {
15 | // 剧集epid
16 | int64 ep_id = 1;
17 | }
18 |
19 | // 获取首播状态-响应
20 | message PremiereStatusReply {
21 | // 服务端播放进度 单位ms 用户实际播放进度:progress - delay_time
22 | int64 progress = 1;
23 | // 起播时间戳 单位ms
24 | int64 start_time = 2;
25 | // 延迟播放时长 单位ms
26 | int64 delay_time = 3;
27 | // 首播在线人数
28 | int64 online_count = 4;
29 | // 首播状态
30 | // 1:预热 2:首播中 3:紧急停播 4:已结束
31 | int32 status = 5;
32 | // 首播结束后跳转类型
33 | // 1:下架 2:转点播
34 | int32 after_premiere_type = 6;
35 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/polymer/demo/demo.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.polymer.demo;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | message HelloWorldReq {
9 | //
10 | string content = 1;
11 | }
12 |
13 | //
14 | message HelloWorldResp {
15 | //
16 | string data = 1;
17 | }
18 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/polymer/list/v1/list.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.polymer.list.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | service List {
9 | //
10 | rpc FavoriteTab(FavoriteTabReq) returns (FavoriteTabReply);
11 | //
12 | rpc CheckAccount(CheckAccountReq) returns (CheckAccountReply);
13 | }
14 |
15 | //
16 | message CheckAccountReply {
17 | //
18 | bool is_new = 1;
19 | }
20 |
21 | //
22 | message CheckAccountReq {
23 | //
24 | int64 uid = 1;
25 | //
26 | string periods = 2;
27 | }
28 |
29 | //
30 | message FavoriteTabItem {
31 | //
32 | string name = 1;
33 | //
34 | string uri = 2;
35 | //
36 | string type = 3;
37 | }
38 |
39 | //
40 | message FavoriteTabReply {
41 | //
42 | repeated FavoriteTabItem items = 1;
43 | }
44 |
45 | //
46 | message FavoriteTabReq {}
47 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/relation/interfaces/api.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.relation.interface.v1;
4 |
5 | option java_multiple_files = true;
6 | option java_package = "bilibili.relation.interface1.v1";
7 |
8 | service RelationInterface {
9 | // 评论区 At 用户列表 (无需登录鉴权)
10 | rpc AtSearch (AtSearchReq) returns (AtSearchReply);
11 | }
12 |
13 | message AtSearchReq {
14 | // 可以为 1 , 但是不能为 0 或空 不知道有啥用
15 | int64 mid = 1;
16 | // 用户名搜索关键词
17 | string keyword = 2;
18 | }
19 |
20 | message AtSearchReply {
21 | // 搜索结果分组
22 | repeated AtGroup items = 1;
23 | }
24 |
25 | message AtGroup {
26 | // 分组类型 2: 我的关注 4:其他 ,其他自测
27 | int32 group_type = 1;
28 | // 分组名称
29 | string group_name = 2;
30 | // 用户列表
31 | repeated AtItem items = 3;
32 | }
33 |
34 | message AtItem {
35 | int64 mid = 1;
36 | string name = 2;
37 | string face = 3;
38 | int32 fans = 4;
39 | int32 official_verify_type = 5;
40 | }
41 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/render/render.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.render;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/any.proto";
8 |
9 | //
10 | message Render {
11 | //
12 | int64 code = 1;
13 | //
14 | string message = 2;
15 | //
16 | string ttl = 3;
17 | //
18 | google.protobuf.Any data = 4;
19 | }
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/rpc/status.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.rpc;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/any.proto";
8 |
9 | // 响应gRPC Status
10 | // 当status code是[UNKNOWN = 2]时,details为业务详细的错误信息,进行proto any转换成业务码结构体
11 | message Status {
12 | // 业务错误码
13 | int32 code = 1;
14 | // 业务错误信息
15 | string message = 2;
16 | // 扩展信息嵌套(相当于该messasge的套娃)
17 | repeated google.protobuf.Any details = 3;
18 | }
19 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/bilibili/vega/deneb/v1/deneb.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package bilibili.vega.deneb.v1;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/any.proto";
8 |
9 | //
10 | service VegaDenebRPC {
11 | //
12 | rpc MessagePulls (MessagePullsReq) returns (MessagePullsReply);
13 | }
14 |
15 | //
16 | message MessagePullsReply {
17 | //
18 | repeated google.protobuf.Any data = 1;
19 | //
20 | int32 pn = 2;
21 | //
22 | int32 ps = 3;
23 | //
24 | int64 count = 4;
25 | //
26 | bool has_next = 5;
27 | }
28 |
29 | //
30 | message MessagePullsReq {
31 | //
32 | int64 start_seq_id = 1;
33 | //
34 | int64 end_seq_id = 2;
35 | //
36 | int32 pn = 3;
37 | //
38 | int32 ps = 4;
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/common/ErrorProto.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package common;
4 |
5 | option java_multiple_files = true;
6 |
7 | import "google/protobuf/any.proto";
8 |
9 | // 响应gRPC Status
10 | // 当status code是[UNKNOWN = 2]时,details为业务详细的错误信息,进行proto any转换成业务码结构体
11 | message ErrorProto {
12 | // 业务错误码
13 | int32 code = 1;
14 | // 业务错误信息
15 | string message = 2;
16 | // 扩展信息嵌套(相当于该messasge的套娃)
17 | repeated google.protobuf.Any details = 3;
18 | }
19 |
--------------------------------------------------------------------------------
/bili-api-grpc/proto/pgc/biz/room.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pgc.biz;
4 |
5 | option java_multiple_files = true;
6 |
7 | //
8 | message RoomProto {
9 | //
10 | repeated string room_id = 1;
11 | }
--------------------------------------------------------------------------------
/bili-api/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/bili-api/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(gradleLibs.plugins.kotlin.jvm)
3 | alias(gradleLibs.plugins.kotlin.serialization)
4 | }
5 |
6 | group = "dev.aaa1115910"
7 |
8 | dependencies {
9 | implementation(project(":bili-api-grpc"))
10 | implementation(libs.jsoup)
11 | implementation(libs.kotlinx.coroutines)
12 | implementation(libs.kotlinx.serialization)
13 | implementation(libs.ktor.client.content.negotiation)
14 | implementation(libs.ktor.client.core)
15 | implementation(libs.ktor.client.encoding)
16 | //implementation(libs.ktor.jsoup)
17 | implementation(libs.ktor.client.okhttp)
18 | implementation(libs.ktor.client.serialization.kotlinx)
19 | implementation(libs.logging)
20 | implementation(libs.slf4j.simple)
21 | testImplementation(libs.kotlin.test)
22 | }
23 |
24 | tasks.test {
25 | useJUnitPlatform()
26 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/GUARD_BUY.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "GUARD_BUY",
3 | "data": {
4 | "uid": 6501027,
5 | "username": "玉紫",
6 | "guard_level": 3,
7 | "num": 1,
8 | "price": 198000,
9 | "gift_id": 10003,
10 | "gift_name": "舰长",
11 | "start_time": 1669435051,
12 | "end_time": 1669435051
13 | }
14 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/HOT_RANK_SETTLEMENT.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "HOT_RANK_SETTLEMENT",
3 | "data": {
4 | "area_name": "手游",
5 | "cache_key": "c2f8a79cc9a709237fb65df23fd61025",
6 | "dm_msg": "恭喜主播 <% 逍遥散人 %> 荣登限时热门榜手游榜top9! 即将获得轮播资源位推荐哦!",
7 | "dmscore": 144,
8 | "face": "https://i1.hdslb.com/bfs/face/8a5de2d7486251e80307d8600cbf8649eb4035fe.jpg",
9 | "icon": "https://i0.hdslb.com/bfs/live/b4961bcfba56a26b69c35690dfcbdabbeb973c64.png",
10 | "rank": 9,
11 | "timestamp": 1669435204,
12 | "uname": "逍遥散人",
13 | "url": "https://live.bilibili.com/p/html/live-app-hotrank/result.html?is_live_half_webview=1&hybrid_half_ui=1,5,250,200,f4eefa,0,30,0,0,0;2,5,250,200,f4eefa,0,30,0,0,0;3,5,250,200,f4eefa,0,30,0,0,0;4,5,250,200,f4eefa,0,30,0,0,0;5,5,250,200,f4eefa,0,30,0,0,0;6,5,250,200,f4eefa,0,30,0,0,0;7,5,250,200,f4eefa,0,30,0,0,0;8,5,250,200,f4eefa,0,30,0,0,0&areaId=3&cache_key=c2f8a79cc9a709237fb65df23fd61025"
14 | }
15 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/HOT_RANK_SETTLEMENT_V2.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "HOT_RANK_SETTLEMENT_V2",
3 | "data": {
4 | "rank": 7,
5 | "uname": "逍遥散人",
6 | "face": "https://i1.hdslb.com/bfs/face/8a5de2d7486251e80307d8600cbf8649eb4035fe.jpg",
7 | "timestamp": 1669434904,
8 | "icon": "https://i0.hdslb.com/bfs/live/cb2e160ac4f562b347bb5ae6e635688ebc69580f.png",
9 | "area_name": "原神",
10 | "url": "https://live.bilibili.com/p/html/live-app-hotrank/result.html?is_live_half_webview=1&hybrid_half_ui=1,5,250,200,f4eefa,0,30,0,0,0;2,5,250,200,f4eefa,0,30,0,0,0;3,5,250,200,f4eefa,0,30,0,0,0;4,5,250,200,f4eefa,0,30,0,0,0;5,5,250,200,f4eefa,0,30,0,0,0;6,5,250,200,f4eefa,0,30,0,0,0;7,5,250,200,f4eefa,0,30,0,0,0;8,5,250,200,f4eefa,0,30,0,0,0&areaId=321&cache_key=17276a47cc6fd1420feb0f2d86f60e85",
11 | "cache_key": "17276a47cc6fd1420feb0f2d86f60e85",
12 | "dm_msg": "恭喜主播 <% 逍遥散人 %> 荣登限时热门榜原神榜top7! 即将获得轮播资源位推荐哦!"
13 | }
14 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/HOT_ROOM_NOTIFY.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "HOT_ROOM_NOTIFY",
3 | "data": {
4 | "threshold": 10000,
5 | "ttl": 300,
6 | "exit_no_refresh": 1,
7 | "random_delay_req_v2": [
8 | {
9 | "path": "/live/getRoundPlayVideo",
10 | "delay": 10
11 | },
12 | {
13 | "path": "/xlive/web-room/v1/index/getOffLiveList",
14 | "delay": 120000
15 | }
16 | ]
17 | }
18 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/INTERACT_WORD.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "INTERACT_WORD",
3 | "data": {
4 | "contribution": {
5 | "grade": 0
6 | },
7 | "dmscore": 2,
8 | "fans_medal": {
9 | "anchor_roomid": 0,
10 | "guard_level": 0,
11 | "icon_id": 0,
12 | "is_lighted": 0,
13 | "medal_color": 0,
14 | "medal_color_border": 0,
15 | "medal_color_end": 0,
16 | "medal_color_start": 0,
17 | "medal_level": 0,
18 | "medal_name": "",
19 | "score": 0,
20 | "special": "",
21 | "target_id": 0
22 | },
23 | "identities": [
24 | 1
25 | ],
26 | "is_spread": 0,
27 | "msg_type": 1,
28 | "privilege_type": 0,
29 | "roomid": 21721813,
30 | "score": 1669399871533,
31 | "spread_desc": "",
32 | "spread_info": "",
33 | "tail_icon": 0,
34 | "timestamp": 1669399871,
35 | "trigger_time": 1669399870422980000,
36 | "uid": 268831673,
37 | "uname": "丸子泡汤ON",
38 | "uname_color": ""
39 | }
40 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/LIKE_INFO_V3_CLICK.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "LIKE_INFO_V3_CLICK",
3 | "data": {
4 | "show_area": 0,
5 | "msg_type": 6,
6 | "like_icon": "https://i0.hdslb.com/bfs/live/23678e3d90402bea6a65251b3e728044c21b1f0f.png",
7 | "uid": 393552291,
8 | "like_text": "为主播点赞了",
9 | "uname": "有卢克迪丽歇斯",
10 | "uname_color": "",
11 | "identities": [
12 | 1
13 | ],
14 | "fans_medal": {
15 | "target_id": 0,
16 | "medal_level": 0,
17 | "medal_name": "",
18 | "medal_color": 0,
19 | "medal_color_start": 12632256,
20 | "medal_color_end": 12632256,
21 | "medal_color_border": 12632256,
22 | "is_lighted": 0,
23 | "guard_level": 0,
24 | "special": "",
25 | "icon_id": 0,
26 | "anchor_roomid": 0,
27 | "score": 0
28 | },
29 | "contribution_info": {
30 | "grade": 0
31 | },
32 | "dmscore": 20
33 | }
34 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/LIKE_INFO_V3_UPDATE.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "LIKE_INFO_V3_UPDATE",
3 | "data": {
4 | "click_count": 15805
5 | }
6 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/LIVE_INTERACTIVE_GAME.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "LIVE_INTERACTIVE_GAME",
3 | "data": {
4 | "type": 2,
5 | "uid": 2588066,
6 | "uname": "傻傻分不清噜",
7 | "uface": "",
8 | "gift_id": 0,
9 | "gift_name": "",
10 | "gift_num": 0,
11 | "price": 0,
12 | "paid": false,
13 | "msg": "这个debuff还行不影响",
14 | "fans_medal_level": 0,
15 | "guard_level": 0,
16 | "timestamp": 1669400655,
17 | "anchor_lottery": null,
18 | "pk_info": null,
19 | "anchor_info": null,
20 | "combo_info": null
21 | }
22 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/LIVE_MULTI_VIEW_CHANGE.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "LIVE_MULTI_VIEW_CHANGE",
3 | "data": {
4 | "scatter": {
5 | "max": 120,
6 | "min": 5
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/ONLINE_RANK_COUNT.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "ONLINE_RANK_COUNT",
3 | "data": {
4 | "count": 530
5 | }
6 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/ONLINE_RANK_TOP3.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "ONLINE_RANK_TOP3",
3 | "data": {
4 | "dmscore": 112,
5 | "list": [
6 | {
7 | "msg": "恭喜 <%玉紫%> 成为高能用户",
8 | "rank": 2
9 | }
10 | ]
11 | }
12 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/PREPARING.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "PREPARING",
3 | "round": 1,
4 | "roomid": "47867"
5 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/ROOM_REAL_TIME_MESSAGE_UPDATE.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "ROOM_REAL_TIME_MESSAGE_UPDATE",
3 | "data": {
4 | "roomid": 545068,
5 | "fans": 2567341,
6 | "red_notice": -1,
7 | "fans_club": 47278
8 | }
9 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/SUPER_CHAT_ENTRANCE.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "SUPER_CHAT_ENTRANCE",
3 | "data": {
4 | "icon": "https://i0.hdslb.com/bfs/live/0a9ebd72c76e9cbede9547386dd453475d4af6fe.png",
5 | "jump_url": "https://live.bilibili.com/p/html/live-app-superchat2/index.html?is_live_half_webview=1&hybrid_half_ui=1,3,100p,70p,ffffff,0,30,100;2,2,375,100p,ffffff,0,30,100;3,3,100p,70p,ffffff,0,30,100;4,2,375,100p,ffffff,0,30,100;5,3,100p,60p,ffffff,0,30,100;6,3,100p,60p,ffffff,0,30,100;7,3,100p,60p,ffffff,0,30,100",
6 | "status": 0
7 | }
8 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/USER_TOAST_MSG.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "USER_TOAST_MSG",
3 | "data": {
4 | "anchor_show": true,
5 | "color": "#00D1F1",
6 | "dmscore": 90,
7 | "effect_id": 397,
8 | "end_time": 1669435051,
9 | "face_effect_id": 44,
10 | "gift_id": 10003,
11 | "guard_level": 3,
12 | "is_show": 0,
13 | "num": 1,
14 | "op_type": 3,
15 | "payflow_id": "2211261157000842110278874",
16 | "price": 138000,
17 | "role_name": "舰长",
18 | "room_effect_id": 590,
19 | "start_time": 1669435051,
20 | "svga_block": 0,
21 | "target_guard_count": 972,
22 | "toast_msg": "<%玉紫%> 续费了舰长,今天是TA陪伴主播的第691天",
23 | "uid": 6501027,
24 | "unit": "月",
25 | "user_show": true,
26 | "username": "玉紫"
27 | }
28 | }
--------------------------------------------------------------------------------
/bili-api/example-response/live-event/WATCHED_CHANGE.json5:
--------------------------------------------------------------------------------
1 | {
2 | "cmd": "WATCHED_CHANGE",
3 | "data": {
4 | "num": 305504,
5 | "text_small": "30.5万",
6 | "text_large": "30.5万人看过"
7 | }
8 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/ApiType.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity
2 |
3 | enum class ApiType {
4 | Web, App
5 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/home/RecommendData.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.home
2 |
3 | import dev.aaa1115910.biliapi.entity.ugc.UgcItem
4 |
5 | data class RecommendData(
6 | val items: List,
7 | val nextPage: RecommendPage
8 | )
9 |
10 | data class RecommendPage(
11 | val nextWebIdx: Int = 1,
12 | val nextAppIdx: Int = 0
13 | )
14 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/login/Captcha.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.login
2 |
3 | /**
4 | * 人机数据
5 | *
6 | * @param token 登录 API token
7 | * @param gt 极验id 一般为固定值
8 | * @param challenge 极验KEY 由B站后端产生用于人机验证
9 | */
10 | data class Captcha(
11 | val token: String,
12 | val challenge: String,
13 | val gt: String
14 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/login/QR.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.login
2 |
3 | import java.util.Date
4 |
5 | /**
6 | * 获取扫码登录的二维码
7 | *
8 | * @param url 二维码内容
9 | * @param key 用于查询扫码登录结果
10 | */
11 | data class QrLoginData(
12 | val url: String,
13 | val key: String
14 | )
15 |
16 | /**
17 | * 扫码登录结果
18 | *
19 | * @param state 登录结果状态
20 | * @param cookies 登录成功的 cookies
21 | */
22 | data class QrLoginResult(
23 | val state: QrLoginState,
24 | val accessToken: String? = null,
25 | val refreshToken: String? = null,
26 | val cookies: WebCookies? = null
27 | )
28 |
29 | enum class QrLoginState {
30 | Ready,
31 | RequestingQRCode,
32 | WaitingForScan,
33 | WaitingForConfirm,
34 | Expired,
35 | Success,
36 | Error,
37 | Unknown
38 | }
39 |
40 | data class WebCookies(
41 | val dedeUserId: Long,
42 | val dedeUserIdCkMd5: String,
43 | val sid: String,
44 | val biliJct: String,
45 | val sessData: String,
46 | val expiredDate: Date
47 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/pgc/PgcType.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.pgc
2 |
3 | enum class PgcType {
4 | Anime,
5 | GuoChuang,
6 | Movie,
7 | Documentary,
8 | Tv,
9 | Variety
10 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/rank/Popular.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.rank
2 |
3 | import dev.aaa1115910.biliapi.entity.ugc.UgcItem
4 |
5 | data class PopularVideoData(
6 | val list: List,
7 | val nextPage: PopularVideoPage,
8 | val noMore: Boolean
9 | )
10 |
11 | data class PopularVideoPage(
12 | val nextWebPageSize: Int = 20,
13 | val nextWebPageNumber: Int = 1,
14 | val nextAppIndex: Int = 0,
15 | )
16 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/reply/CommentPage.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.reply
2 |
3 | data class CommentPage(
4 | val nextWebPage: String = "",
5 | val nextAppPage: String = ""
6 | )
7 |
8 | data class CommentReplyPage(
9 | val nextWebPage: Int = 0,
10 | val nextAppPage: String = ""
11 | )
12 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/reply/CommentSort.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.reply
2 |
3 | enum class CommentSort(val param: Int) {
4 | Hot(3), HotAndTime(1), Time(2)
5 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/ugc/region/UgcFeedData.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.ugc.region
2 |
3 | import dev.aaa1115910.biliapi.entity.ugc.UgcItem
4 |
5 | data class UgcFeedData(
6 | var hasNext: Boolean,
7 | var nextPage: UgcFeedPage,
8 | var items: List = emptyList()
9 | ) {
10 | companion object {
11 | fun fromRegionFeedRcmd(data: dev.aaa1115910.biliapi.http.entity.region.RegionFeedRcmd): UgcFeedData {
12 | return UgcFeedData(
13 | hasNext = data.archives.isNotEmpty(),
14 | nextPage = UgcFeedPage(),
15 | items = data.archives.map { UgcItem.fromRegionRcmdArchive(it) }
16 | )
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/ugc/region/UgcFeedPage.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.ugc.region
2 |
3 | data class UgcFeedPage(
4 | val nextPage: Int = 1
5 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/ugc/region/UgcRegionData.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.ugc.region
2 |
3 | import dev.aaa1115910.biliapi.entity.CarouselData
4 | import dev.aaa1115910.biliapi.entity.ugc.UgcItem
5 |
6 | @Deprecated("User region v2 instead")
7 | data class UgcRegionData(
8 | val carouselData: CarouselData?,
9 | val items: List,
10 | val next: UgcRegionPage
11 | ) {
12 | companion object {
13 | fun fromRegionDynamic(data: dev.aaa1115910.biliapi.http.entity.region.RegionDynamic): UgcRegionData {
14 | return UgcRegionData(
15 | carouselData = data.banner?.let { CarouselData.fromUgcRegionDynamicBanner(it) },
16 | items = data.new.map { UgcItem.fromRegionDynamicListItem(it) },
17 | next = UgcRegionPage(data.cBottom)
18 | )
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/ugc/region/UgcRegionListData.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.ugc.region
2 |
3 | import dev.aaa1115910.biliapi.entity.ugc.UgcItem
4 |
5 | @Deprecated("User region v2 instead")
6 | data class UgcRegionListData(
7 | val items: List,
8 | val next: UgcRegionPage
9 | ) {
10 | companion object {
11 | fun fromRegionDynamicList(data: dev.aaa1115910.biliapi.http.entity.region.RegionDynamicList): UgcRegionListData {
12 | return UgcRegionListData(
13 | items = data.new.map { UgcItem.fromRegionDynamicListItem(it) },
14 | next = UgcRegionPage(data.cBottom)
15 | )
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/ugc/region/UgcRegionPage.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.ugc.region
2 |
3 | @Deprecated("User region v2 instead")
4 | data class UgcRegionPage(
5 | val nextPage: Long = 0
6 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/user/Author.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.user
2 |
3 | import dev.aaa1115910.biliapi.http.entity.video.VideoOwner
4 |
5 | data class Author(
6 | val mid: Long,
7 | val name: String,
8 | val face: String
9 | ) {
10 | companion object {
11 | fun fromVideoOwner(videoOwner: VideoOwner) = Author(
12 | mid = videoOwner.mid,
13 | name = videoOwner.name,
14 | face = videoOwner.face
15 | )
16 |
17 | fun fromAuthor(author: bilibili.app.archive.v1.Author) = Author(
18 | mid = author.mid,
19 | name = author.name,
20 | face = author.face
21 | )
22 | }
23 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/user/FollowedUser.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.user
2 |
3 | data class FollowedUser(
4 | val mid: Long,
5 | val name: String,
6 | val avatar: String,
7 | val sign: String
8 | ) {
9 | companion object {
10 | fun fromHttpFollowedUser(followedUser: dev.aaa1115910.biliapi.http.entity.user.UserFollowData.FollowedUser) =
11 | FollowedUser(
12 | mid = followedUser.mid,
13 | name = followedUser.uname,
14 | avatar = followedUser.face,
15 | sign = followedUser.sign
16 | )
17 | }
18 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/video/Dimension.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.video
2 |
3 | data class Dimension(
4 | val width: Int,
5 | val height: Int,
6 | val isVertical: Boolean = width < height
7 | ) {
8 | companion object {
9 | fun fromDimension(dimension: bilibili.app.archive.v1.Dimension) = Dimension(
10 | width = dimension.width.toInt(),
11 | height = dimension.height.toInt()
12 | )
13 |
14 | fun fromDimension(dimension: dev.aaa1115910.biliapi.http.entity.video.Dimension) =
15 | Dimension(
16 | width = dimension.width,
17 | height = dimension.height
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/video/Heartbeat.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.video
2 |
3 | enum class HeartbeatVideoType(val value: Int) {
4 | Video(3), Season(4), Course(10)
5 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/entity/video/Tag.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.entity.video
2 |
3 | data class Tag(
4 | val id: Int,
5 | val name: String
6 | ) {
7 | companion object {
8 | fun fromTag(tag: dev.aaa1115910.biliapi.http.entity.video.Tag) = Tag(
9 | id = tag.tagId,
10 | name = tag.tagName
11 | )
12 |
13 | fun fromTag(tag: bilibili.app.view.v1.Tag) = Tag(
14 | id = tag.id.toInt(),
15 | name = tag.name
16 | )
17 |
18 | fun fromTag(tag: dev.aaa1115910.biliapi.http.entity.video.VideoDetail.Tag) = Tag(
19 | id = tag.tagId,
20 | name = tag.tagName
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/dynamic/DynamicDetailResponse.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.dynamic
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class DynamicDetailData(
7 | val item: DynamicItem
8 | )
9 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/index/IndexFilterArea.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.index
2 |
3 | object IndexFilterArea {
4 | private val areaFilter = mapOf(
5 | -1 to "全部",
6 | 1 to "中国大陆",
7 | 2 to "日本",
8 | 3 to "美国",
9 | 4 to "英国",
10 | 5 to "其他",
11 | 6 to "中国港台",
12 | 8 to "韩国",
13 | 9 to "法国",
14 | 10 to "泰国",
15 | 13 to "西班牙",
16 | 15 to "德国",
17 | 35 to "意大利",
18 | )
19 |
20 | private val movieAreaIds = listOf(
21 | -1, 1, 6, 3, 28, 9, 4, 15, 10, 35, 13, 5
22 | )
23 | private val tvAreaIds = listOf(
24 | -1, 1, 2, 3, 4, 10, 5
25 | )
26 |
27 | val movieAreas by lazy { movieAreaIds.associateWith { areaFilter[it]!! } }
28 | val tvAreas by lazy { tvAreaIds.associateWith { areaFilter[it]!! } }
29 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/index/IndexFilterProducerId.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.index
2 |
3 | object IndexFilterProducerId {
4 | private val producerIdFilter = mapOf(
5 | -1 to "全部",
6 | 1 to "BBC",
7 | 2 to "NHK",
8 | 3 to "SKY",
9 | 4 to "央视",
10 | 5 to "ITV",
11 | 6 to "历史频道",
12 | 7 to "探索频道",
13 | 8 to "卫视",
14 | 9 to "自制",
15 | 10 to "ZDF",
16 | 11 to "合作机构",
17 | 12 to "国内其他",
18 | 13 to "国外其他",
19 | 14 to "国家地理",
20 | 15 to "索尼",
21 | 16 to "环球",
22 | 17 to "派拉蒙",
23 | 18 to "华纳",
24 | 19 to "迪士尼",
25 | 20 to "HBO",
26 |
27 | )
28 |
29 | private val producerIdIds = listOf(
30 | -1, 4, 1, 7, 14, 2, 6, 8, 9, 5, 3, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20
31 | )
32 |
33 | val producerIds by lazy { producerIdIds.associateWith { producerIdFilter[it]!! } }
34 | }
35 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/index/IndexOrder.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.index
2 |
3 | enum class IndexOrder(val id: Int) {
4 | UpdateTime(0), DanmakuCount(1), PlayCount(2), FollowCount(3),
5 | Score(4), StartTime(5), PublishTime(6)
6 | }
7 |
8 | private val animeIds = listOf(3, 0, 4, 2, 5)
9 | private val guochuangIds = listOf(3, 0, 4, 2, 5)
10 | private val varietyIds = listOf(2, 0, 6, 4, 1)
11 | private val tvIds = listOf(2, 0, 1, 3, 4)
12 | private val movieIds = listOf(2, 0, 6, 4)
13 | private val documentaryIds = listOf(2, 4, 0, 6, 1)
14 |
15 | val animeIndexOrders by lazy { animeIds.map { IndexOrder.entries[it] } }
16 | val guochuangIndexOrders by lazy { guochuangIds.map { IndexOrder.entries[it] } }
17 | val varietyIndexOrders by lazy { varietyIds.map { IndexOrder.entries[it] } }
18 | val tvIndexOrders by lazy { tvIds.map { IndexOrder.entries[it] } }
19 | val movieIndexOrders by lazy { movieIds.map { IndexOrder.entries[it] } }
20 | val documentaryIndexOrders by lazy { documentaryIds.map { IndexOrder.entries[it] } }
21 |
22 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/live/LiveDanmuInfoResponse.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.live
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class DanmuInfoData(
8 | val group: String,
9 | @SerialName("business_id")
10 | val businessId: Int,
11 | @SerialName("refresh_row_factor")
12 | val refreshRowFactor: Float,
13 | @SerialName("refresh_rate")
14 | val refreshRate: Int,
15 | @SerialName("max_delay")
16 | val maxDelay: Int,
17 | val token: String,
18 | @SerialName("host_list")
19 | val hostList: List = emptyList()
20 | )
21 |
22 | @Serializable
23 | data class HostListItem(
24 | val host: String,
25 | val port: Int,
26 | @SerialName("wss_port")
27 | val wssPort: Int,
28 | @SerialName("ws_port")
29 | val wsPort: Int
30 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/live/LiveEvent.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.live
2 |
3 | interface LiveEvent
4 |
5 | data class DanmakuEvent(
6 | val content: String,
7 | val mid: Long,
8 | val username: String,
9 | val medalName: String? = null,
10 | val medalLevel: Int? = null
11 | ) : LiveEvent
12 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/login/Captcha.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.login
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 申请 captcha 验证码结果
8 | *
9 | * @param type 验证方式 用于判断使用哪一种验证方式,目前所见只有极验 geetest:极验
10 | * @param token 登录 API token 与 captcha 无关,与登录接口有关
11 | * @param geetest 极验 captcha 数据
12 | * @param tencent 作用尚不明确
13 | */
14 | @Serializable
15 | data class CaptchaData(
16 | val type: String,
17 | val token: String,
18 | val geetest: Geetest,
19 | val tencent: Tencent
20 | ) {
21 | /**
22 | * 极验captcha数据
23 | *
24 | * @param gt 极验id 一般为固定值
25 | * @param challenge 极验KEY 由B站后端产生用于人机验证
26 | */
27 | @Serializable
28 | data class Geetest(
29 | val challenge: String,
30 | val gt: String
31 | )
32 |
33 | @Serializable
34 | data class Tencent(
35 | @SerialName("appid")
36 | val appId: String
37 | )
38 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/login/qr/WebQR.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.login.qr
2 |
3 | import io.ktor.http.Cookie
4 | import kotlinx.serialization.SerialName
5 | import kotlinx.serialization.Serializable
6 | import kotlinx.serialization.Transient
7 |
8 | @Serializable
9 | data class RequestWebQRData(
10 | val url: String,
11 | @SerialName("qrcode_key")
12 | val qrcodeKey: String
13 | )
14 |
15 |
16 | @Serializable
17 | data class QRLoginResponse(
18 | val code: Int,
19 | val message: String,
20 | val ttl: Int,
21 | val data: WebQRLoginData,
22 | @Transient
23 | var cookies: List = emptyList()
24 | )
25 |
26 | @Serializable
27 | data class WebQRLoginData(
28 | val url: String,
29 | @SerialName("refresh_token")
30 | val refreshToken: String,
31 | val timestamp: Long,
32 | val code: Int,
33 | val message: String
34 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/login/sms/SendSmsResponse.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.login.sms
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 发送验证码结果
8 | */
9 | @Serializable
10 | data class SendSmsResponse(
11 | @SerialName("captcha_key")
12 | val captchaKey: String,
13 | @SerialName("recaptcha_url")
14 | val recaptchaUrl: String
15 | )
16 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/region/RegionBanner.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.region
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class RegionBanner(
8 | @SerialName("region_banner_list")
9 | val regionBannerList: List
10 | )
11 |
12 | @Serializable
13 | data class UgcRegionBannerItem(
14 | val image: String,
15 | val title: String,
16 | @SerialName("sub_title")
17 | val subTitle: String,
18 | val url: String,
19 | val rid: Int
20 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/region/RegionFeedRcmd.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.region
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class RegionFeedRcmd(
8 | val archives: List
9 | ) {
10 | @Serializable
11 | data class Archive(
12 | val aid: Long,
13 | val bvid: String,
14 | val cid: Long,
15 | val title: String,
16 | val cover: String,
17 | val duration: Int,
18 | val pubdate: Long,
19 | val stat: Stat,
20 | val author: Author,
21 | val trackid: String,
22 | val goto: String,
23 | @SerialName("rec_reason")
24 | val recReason: String
25 | ) {
26 | @Serializable
27 | data class Stat(
28 | val view: Int,
29 | val like: Int,
30 | val danmaku: Int
31 | )
32 |
33 | @Serializable
34 | data class Author(
35 | val mid: Long,
36 | val name: String
37 | )
38 | }
39 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/reply/CommentReplyData.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.reply
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class CommentReplyData(
8 | val config: Config,
9 | val control: Control,
10 | val page: Page,
11 | val replies: List = emptyList(),
12 | val root: CommentData.Reply,
13 | // @SerialName("show_text")
14 | // val showText: String,
15 | // @SerialName("show_type")
16 | // val showType: Int,
17 | val upper: Upper
18 | ) {
19 | @Serializable
20 | data class Page(
21 | val count: Int,
22 | val num: Int,
23 | val size: Int
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/season/Follow.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.season
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class SeasonFollowData(
7 | val fmid: Int,
8 | val relation: Boolean,
9 | val status: Int,
10 | val toast: String
11 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/season/SeasonSection.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.season
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import kotlinx.serialization.json.JsonArray
6 |
7 | /**
8 | * 板块 花絮、PV、番外等非正片内容
9 | *
10 | * @param attr
11 | * @param episodeId
12 | * @param episodeIds
13 | * @param episodes 板块内容
14 | * @param id 板块id
15 | * @param title 板块标题
16 | * @param type
17 | */
18 | @Serializable
19 | data class SeasonSection(
20 | val attr: Int,
21 | @SerialName("episode_id")
22 | val episodeId: Int,
23 | @SerialName("episode_ids")
24 | val episodeIds: JsonArray? = null,
25 | val episodes: List = emptyList(),
26 | val id: Int,
27 | val title: String,
28 | val type: Int
29 | )
30 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/LevelInfo.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 等级信息
8 | *
9 | * @param currentLevel 当前等级 0-6级
10 | * @param currentMin 当前等级经验最低值
11 | * @param currentExp 当前经验
12 | * @param nextExp 升级下一等级需达到的经验
13 | */
14 | @Serializable
15 | data class LevelInfo(
16 | @SerialName("current_level")
17 | val currentLevel: Int,
18 | @SerialName("current_min")
19 | val currentMin: Int,
20 | @SerialName("current_exp")
21 | val currentExp: Int,
22 | @SerialName("next_exp")
23 | val nextExp: Int
24 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/Nameplate.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 勋章
8 | *
9 | * @param nid 勋章id
10 | * @param name 勋章名称
11 | * @param image 勋章图标
12 | * @param imageSmall 勋章图标(小)
13 | * @param level 勋章等级
14 | * @param condition 获取条件
15 | */
16 | @Serializable
17 | data class Nameplate(
18 | val nid: Int,
19 | val name: String,
20 | val image: String,
21 | @SerialName("image_small")
22 | val imageSmall: String,
23 | val level: String,
24 | val condition: String
25 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/Official.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | /**
6 | * 认证信息
7 | *
8 | * @param role 认证类型 0:无 1 2 7 9:个人认证 3 4 5 6:机构认证
9 | * @param title 认证信息 无为空
10 | * @param desc 认证备注 无为空
11 | * @param type 是否认证 -1:无 0:个人认证 1:机构认证
12 | */
13 | @Serializable
14 | data class Official(
15 | val role: Int,
16 | val title: String,
17 | val desc: String,
18 | val type: Int
19 | )
20 |
21 | /**
22 | * 认证信息
23 | *
24 | * @param type 是否认证 -1:无 0:认证
25 | * @param desc 认证信息 无为空
26 | */
27 | @Serializable
28 | data class OfficialVerify(
29 | val type: Int,
30 | val desc: String
31 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/Pendant.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 头像框
8 | *
9 | * @param pid 头像框id
10 | * @param name 头像框名称
11 | * @param image 头像框图片url
12 | * @param expire 过期时间 此接口返回恒为0
13 | * @param imageEnhance 头像框图片url
14 | * @param imageEnhanceFrame 头像框图片逐帧序列url
15 | */
16 | @Serializable
17 | data class Pendant(
18 | val pid: Int,
19 | val name: String,
20 | val image: String,
21 | val expire: Int = 0,
22 | @SerialName("image_enhance")
23 | val imageEnhance: String? = null,
24 | @SerialName("image_enhance_frame")
25 | val imageEnhanceFrame: String? = null
26 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/Profession.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 专业资质信息
8 | *
9 | * @param name 资质名称
10 | * @param department 职位
11 | * @param title 所属机构
12 | * @param isShow 是否显示 0:不显示 1:显示
13 | */
14 | @Serializable
15 | data class Profession(
16 | val name: String,
17 | val department: String,
18 | val title: String,
19 | @SerialName("is_show")
20 | val isShow: Int
21 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/Staff.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | /**
6 | * 创作者个人信息
7 | *
8 | * @param mid 成员mid
9 | * @param title 成员名称
10 | * @param name 成员昵称
11 | * @param face 成员头像url
12 | * @param vip 成员大会员状态
13 | * @param official 成员认证信息
14 | * @param follower 成员粉丝数
15 | */
16 | @Serializable
17 | data class Staff(
18 | val mid: Long,
19 | val title: String,
20 | val name: String,
21 | val face: String,
22 | val vip: Vip,
23 | val official: Official,
24 | val follower: Int
25 | )
26 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/UserGarb.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 用户头像挂件
8 | *
9 | * @param urlImageAniCut
10 | */
11 | @Serializable
12 | data class UserGarb(
13 | @SerialName("url_image_ani_cut")
14 | val urlImageAniCut: String
15 | )
16 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/UserHonours.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class UserHonours(
7 | val mid: Long,
8 | val colour: Colour? = null,
9 | val tags: List = emptyList()
10 | ) {
11 | @Serializable
12 | data class Colour(
13 | val dark: String,
14 | val normal: String
15 | )
16 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/favorite/CntInfo.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user.favorite
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * @param collect 收藏数
8 | * @param play 播放数
9 | * @param thumbUp 点赞数
10 | * @param share 分享数
11 | */
12 | @Serializable
13 | data class CntInfo(
14 | val collect: Int,
15 | val play: Int,
16 | val danmaku: Int = 0,
17 | @SerialName("thumb_up")
18 | val thumbUp: Int = 0,
19 | val share: Int = 0
20 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/favorite/FavoriteFolderInfoListData.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user.favorite
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 收藏夹信息及内容
8 | *
9 | * @param info 收藏夹元数据
10 | * @param medias 收藏夹内容
11 | * @param hasMore 还有更多数据
12 | */
13 | @Serializable
14 | data class FavoriteFolderInfoListData(
15 | val info: FavoriteFolderInfo,
16 | val medias: List = emptyList(),
17 | @SerialName("has_more")
18 | val hasMore: Boolean
19 | )
20 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/favorite/Upper.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user.favorite
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * 收藏夹上传者
8 | *
9 | * @param mid 创建者mid
10 | * @param name 创建者昵称
11 | * @param face 创建者头像url
12 | * @param followed 是否已关注创建者
13 | * @param vipType 会员类别 0:无 1:月大会员 2:年度及以上大会员
14 | * @param vipStatue 会员开通状态 0:无 1:有
15 | */
16 | @Serializable
17 | data class Upper(
18 | val mid: Long,
19 | val name: String,
20 | val face: String,
21 | val followed: Boolean = false,
22 | @SerialName("vip_type")
23 | val vipType: Int = 0,
24 | @SerialName("vip_statue")
25 | val vipStatue: Int = 0
26 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/user/garb/CardBg.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.user.garb
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import kotlinx.serialization.json.JsonObject
6 |
7 | @Serializable
8 | data class CardBg(
9 | @SerialName("act_id")
10 | val actId: Int,
11 | val level: Int,
12 | @SerialName("bg_no")
13 | val bgNo: Int,
14 | val color: String,
15 | @SerialName("no_prefix")
16 | val noPrefix: String,
17 | @SerialName("no_color_format")
18 | val noColorFormat: JsonObject? = null
19 | )
20 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/video/AddCoin.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.video
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | /**
6 | * 投币时顺便点赞的结果
7 | *
8 | * @param like 是否点赞成功 true:成功 false:失败 已赞过则附加点赞失败
9 | */
10 | @Serializable
11 | data class AddCoin(
12 | val like: Boolean
13 | )
14 |
15 | /**
16 | * 检查是否投币
17 | *
18 | * @param multiply 投币枚数 未投币为0
19 | */
20 | @Serializable
21 | data class CheckSentCoin(
22 | val multiply:Int
23 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/video/OneClickTripleAction.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.video
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class OneClickTripleAction(
7 | val like: Boolean,
8 | val coin: Boolean,
9 | val fav: Boolean
10 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/video/PopularVideosResponse.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.video
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class PopularVideoData(
8 | val list: List,
9 | @SerialName("no_more")
10 | val noMore: Boolean
11 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/video/SetVideoFavorite.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.video
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | /**
6 | * 添加/移除收藏
7 | *
8 | * @param prompt 是否为未关注用户收藏 false:否 true:是
9 | */
10 | @Serializable
11 | data class SetVideoFavorite(
12 | val prompt:Boolean
13 | )
14 |
15 | /**
16 | * 检查是否被收藏
17 | *
18 | * @param count 1
19 | * @param favoured 是否收藏 true:已收藏 false:未收藏
20 | */
21 | @Serializable
22 | data class CheckVideoFavoured(
23 | val count:Int,
24 | val favoured:Boolean
25 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/video/VideoShot.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.video
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import kotlinx.serialization.json.JsonElement
6 |
7 | @Serializable
8 | data class VideoShot(
9 | @SerialName("pvdata")
10 | val pvData: String? = null,
11 | @SerialName("img_x_len")
12 | val imgXLen: Int = 10,
13 | @SerialName("img_y_len")
14 | val imgYLen: Int = 10,
15 | @SerialName("img_x_size")
16 | val imgXSize: Int = 0,
17 | @SerialName("img_y_size")
18 | val imgYSize: Int = 0,
19 | val image: List = emptyList(),
20 | val index: List? = null,
21 | @SerialName("video_shots")
22 | var videoShots: JsonElement? = null,
23 | var indexs: JsonElement? = null
24 | )
25 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/web/Hover.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.web
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class Hover(
7 | val text: List,
8 | val img: String
9 | )
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/entity/web/Nav.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.entity.web
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class NavResponseData(
8 | val isLogin: Boolean,
9 | @SerialName("wbi_img")
10 | val wbiImg: WbiImg
11 | ) {
12 | @Serializable
13 | data class WbiImg(
14 | @SerialName("img_url")
15 | val imgUrl: String,
16 | @SerialName("sub_url")
17 | val subUrl: String
18 | ) {
19 | fun getImgKey(): String = imgUrl.split("/").last().split(".").first()
20 | fun getSubKey(): String = subUrl.split("/").last().split(".").first()
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/util/BiliAppConf.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.util
2 |
3 | object BiliAppConf {
4 | const val GRPC_HOST = "grpc.biliapi.net"
5 | const val GRPC_PORT = 443
6 | const val APP_ID = 5
7 | const val APP_BUILD_CODE = 6830300
8 | const val CHANNEL = "bili"
9 | const val MOBI_APP = "android_hd"
10 | const val DEVICE = ""
11 | const val PLATFORM = "android"
12 | const val TIMEZONE = "Asia/Shanghai"
13 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/util/Buvid.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.util
2 |
3 | import java.math.BigInteger
4 | import java.security.MessageDigest
5 |
6 | fun generateBuvid(): String {
7 | val mac = mutableListOf()
8 | for (i in 0 until 6) {
9 | val min = 0
10 | val max = 0xff
11 | val num = (Math.random() * (max - min + 1) + min).toInt().toString(16)
12 | mac.add(num)
13 | }
14 | val md5 = md5(mac.joinToString(":"))
15 | val md5Arr = md5.split("").toTypedArray()
16 | return "XY${md5Arr[2]}${md5Arr[12]}${md5Arr[22]}$md5"
17 | }
18 |
19 | fun md5(input: String): String {
20 | val md = MessageDigest.getInstance("MD5")
21 | val messageDigest = md.digest(input.toByteArray())
22 | val no = BigInteger(1, messageDigest)
23 | var hashText = no.toString(16)
24 | while (hashText.length < 32) {
25 | hashText = "0$hashText"
26 | }
27 | return hashText
28 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/http/util/Zlib.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http.util
2 |
3 | import io.ktor.utils.io.core.use
4 | import java.io.ByteArrayOutputStream
5 | import java.util.zip.Deflater
6 | import java.util.zip.Inflater
7 |
8 | fun ByteArray.zlibCompress(): ByteArray {
9 | val output = ByteArray(this.size * 4)
10 | val compressor = Deflater().apply {
11 | setInput(this@zlibCompress)
12 | finish()
13 | }
14 | val compressedDataLength: Int = compressor.deflate(output)
15 | return output.copyOfRange(0, compressedDataLength)
16 | }
17 |
18 | fun ByteArray.zlibDecompress(): ByteArray {
19 | val inflater = Inflater()
20 | val outputStream = ByteArrayOutputStream()
21 | return outputStream.use {
22 | val buffer = ByteArray(1024)
23 | inflater.setInput(this)
24 | var count = -1
25 | while (count != 0) {
26 | count = inflater.inflate(buffer)
27 | outputStream.write(buffer, 0, count)
28 | }
29 | inflater.end()
30 | outputStream.toByteArray()
31 | }
32 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/repositories/AuthRepository.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.repositories
2 |
3 | class AuthRepository {
4 | var sessionData: String? = null
5 | var biliJct: String? = null
6 | var accessToken: String? = null
7 | var mid: Long? = null
8 | var buvid3: String? = null
9 | var buvid: String? = null
10 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/repositories/CoinRepository.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.repositories
2 |
3 | import dev.aaa1115910.biliapi.http.BiliHttpApi
4 |
5 | class CoinRepository(private val authRepository: AuthRepository) {
6 | suspend fun checkVideoCoined(
7 | aid: Long,
8 | bvid: String? = null,
9 | ): Boolean {
10 | val like = BiliHttpApi.checkVideoSentCoin(
11 | avid = aid,
12 | bvid = bvid,
13 | sessData = authRepository.sessionData!!
14 | )
15 | return like
16 | }
17 |
18 | suspend fun sendVideoCoin(
19 | aid: Long,
20 | bvid: String? = null,
21 | multiply: Int = 1,
22 | ) {
23 | val (success, message) = BiliHttpApi.sendVideoCoin(
24 | avid = aid,
25 | bvid = bvid,
26 | multiply = multiply,
27 | csrf = authRepository.biliJct ?: "",
28 | sessData = authRepository.sessionData!!,
29 | buvid3 = authRepository.buvid3!!,
30 | )
31 | if (!success) throw Exception("投币失败:$message")
32 | }
33 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/repositories/LikeRepository.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.repositories
2 |
3 | import dev.aaa1115910.biliapi.http.BiliHttpApi
4 |
5 | class LikeRepository(private val authRepository: AuthRepository) {
6 | suspend fun checkVideoLiked(
7 | aid: Long,
8 | bvid: String? = null,
9 | ): Boolean {
10 | val like = BiliHttpApi.checkVideoLiked(
11 | avid = aid,
12 | bvid = bvid,
13 | sessData = authRepository.sessionData!!
14 | )
15 | return like
16 | }
17 | suspend fun updateVideoLiked(
18 | aid: Long,
19 | bvid: String? = null,
20 | like: Boolean,
21 | ){
22 | val (success, message) = BiliHttpApi.sendVideoLike(
23 | avid = aid,
24 | bvid = bvid,
25 | like = like,
26 | csrf = authRepository.biliJct ?: "",
27 | sessData = authRepository.sessionData!!,
28 | )
29 | if (!success) {
30 | throw Exception("点赞失败: $message")
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/repositories/OneClickTripleActionRepository.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.repositories
2 |
3 | import dev.aaa1115910.biliapi.http.BiliHttpApi
4 | import dev.aaa1115910.biliapi.http.entity.video.OneClickTripleAction
5 |
6 | class OneClickTripleActionRepository(private val authRepository: AuthRepository) {
7 | suspend fun sendVideoOneClickTripleAction(
8 | aid: Long,
9 | bvid: String? = null
10 | ): OneClickTripleAction? {
11 | val (success, message, data)
12 | = BiliHttpApi.sendVideoOneClickTripleAction(
13 | avid = aid,
14 | bvid = bvid, csrf = authRepository.biliJct ?: "",
15 | sessData = authRepository.sessionData!!,
16 | )
17 | if (!success) throw Exception("投币失败:$message")
18 | return data
19 | }
20 | }
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/util/Extends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.util
2 |
3 | fun String.convertStringTimeToSeconds(): Int {
4 | val parts = this.split(":")
5 | val hours = if (parts.size == 3) parts[0].toInt() else 0
6 | val minutes = parts[parts.size - 2].toInt()
7 | val seconds = parts[parts.size - 1].toInt()
8 | return (hours * 3600) + (minutes * 60) + seconds
9 | }
10 |
11 | fun Long.toBv(): String = AvBvConverter.av2bv(this)
12 | fun String.toAv(): Long = AvBvConverter.bv2av(this)
--------------------------------------------------------------------------------
/bili-api/src/main/kotlin/dev/aaa1115910/biliapi/util/UrlUtil.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.util
2 |
3 | import io.ktor.http.Url
4 |
5 | object UrlUtil {
6 | fun isVideoUrl(url: String): Boolean {
7 | return url.startsWith("bilibili://video/")
8 | || url.startsWith("https://www.bilibili.com/video/")
9 | }
10 |
11 | fun parseAidFromUrl(url: String): Long {
12 | if (url.startsWith("bilibili://video/")) {
13 | return url.split("/").last().toLong()
14 | } else {
15 | val pathSegments = Url(url).rawSegments
16 | val videoSegmentIndex = pathSegments.indexOf("video")
17 | val videoId = pathSegments[videoSegmentIndex + 1]
18 | return if (videoId.startsWith("BV")) {
19 | AvBvConverter.bv2av(videoId)
20 | } else {
21 | videoId.drop(2).toLong()
22 | }
23 | }
24 | }
25 |
26 | fun parseBvidFromUrl(url: String) = parseAidFromUrl(url).toBv()
27 | }
28 |
--------------------------------------------------------------------------------
/bili-api/src/test/kotlin/dev/aaa1115910/biliapi/http/BiliPlusHttpApiTest.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.http
2 |
3 | import kotlinx.coroutines.runBlocking
4 | import org.junit.jupiter.api.Test
5 |
6 | class BiliPlusHttpApiTest {
7 |
8 | @Test
9 | fun `get season video view`() = runBlocking {
10 | val result = BiliPlusHttpApi.view(955635143)
11 | println(result)
12 | }
13 |
14 | @Test
15 | fun `get normal video view`() = runBlocking {
16 | val result = BiliPlusHttpApi.view(955635143)
17 | println(result)
18 | }
19 |
20 | @Test
21 | fun `get not found video view`() = runBlocking {
22 | val result = BiliPlusHttpApi.view(1)
23 | println(result)
24 | }
25 |
26 | @Test
27 | fun `get season id by avid`() = runBlocking {
28 | val seasonId = BiliPlusHttpApi.getSeasonIdByAvid(314583081)
29 | println(seasonId)
30 | }
31 | }
--------------------------------------------------------------------------------
/bili-api/src/test/kotlin/dev/aaa1115910/biliapi/websocket/LiveDataWebSocketTest.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.biliapi.websocket
2 |
3 | import kotlinx.coroutines.delay
4 | import kotlinx.coroutines.runBlocking
5 | import org.junit.jupiter.api.Test
6 |
7 | internal class LiveDataWebSocketTest {
8 |
9 | @Test
10 | fun connectLiveEvent() {
11 | runBlocking {
12 | LiveDataWebSocket.connectLiveEvent(5555) {
13 | println(it)
14 | }
15 | for (i in 1..10) {
16 | delay(1_000)
17 | }
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/bili-api/src/test/resources/3540266_25_2.exp.mobmask:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/bili-api/src/test/resources/3540266_25_2.exp.mobmask
--------------------------------------------------------------------------------
/bili-api/src/test/resources/3540266_25_2.exp.webmask:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/bili-api/src/test/resources/3540266_25_2.exp.webmask
--------------------------------------------------------------------------------
/bili-subtitle/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/bili-subtitle/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(gradleLibs.plugins.kotlin.jvm)
3 | alias(gradleLibs.plugins.kotlin.serialization)
4 | }
5 |
6 | dependencies {
7 | implementation(libs.kotlinx.serialization)
8 | testImplementation(libs.kotlin.test)
9 | }
10 |
11 | tasks.test {
12 | useJUnitPlatform()
13 | }
14 |
--------------------------------------------------------------------------------
/bili-subtitle/src/main/kotlin/dev/aaa1115910/bilisubtitle/entity/BiliSubtitle.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bilisubtitle.entity
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class BiliSubtitle(
8 | @SerialName("font_size")
9 | val fontSize: Float? = null,
10 | @SerialName("font_color")
11 | val fontColor: String? = null,
12 | @SerialName("background_alpha")
13 | val backgroundAlpha: Float? = null,
14 | @SerialName("background_color")
15 | val backgroundColor: String? = null,
16 | @SerialName("Stroke")
17 | val stroke: String? = null,
18 | val type: String? = null,
19 | val lang: String? = null,
20 | val version: String? = null,
21 | val body: List = emptyList()
22 | )
23 |
24 | @Serializable
25 | data class BiliSubtitleItem(
26 | val from: Float,
27 | val to: Float,
28 | val sid: Int? = null,
29 | val location: Int,
30 | val content: String,
31 | val music: Float? = null
32 | )
--------------------------------------------------------------------------------
/bili-subtitle/src/main/kotlin/dev/aaa1115910/bilisubtitle/entity/SrtSubtitle.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bilisubtitle.entity
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class SrtSubtitle(
7 | val content: List = emptyList()
8 | )
9 |
10 | @Serializable
11 | data class SrtSubtitleItem(
12 | val index: Int,
13 | val from: String,
14 | val to: String,
15 | val content: String
16 | ) {
17 | fun toRaw() = """
18 | $index
19 | $from --> $to
20 | $content
21 |
22 | """.trimIndent()
23 | }
24 |
--------------------------------------------------------------------------------
/bili-subtitle/src/main/kotlin/dev/aaa1115910/bilisubtitle/entity/SubtitleItem.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bilisubtitle.entity
2 |
3 | data class SubtitleItem(
4 | val from: Timestamp,
5 | val to: Timestamp,
6 | val content: String
7 | ) {
8 | fun isShowing(time: Long) = from.totalMills <= time && to.totalMills >= time
9 | }
10 |
--------------------------------------------------------------------------------
/bili-subtitle/src/test/kotlin/dev/aaa1115910/bilisubtitle/SubtitleEncoderTest.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bilisubtitle
2 |
3 | import java.io.File
4 | import kotlin.test.Test
5 |
6 | class SubtitleEncoderTest {
7 |
8 | @Test
9 | fun `encode to bcc`() {
10 | val fileContent = this::class.java.getResource("/example.srt")?.readText()!!
11 | val data = SubtitleParser.fromSrtString(fileContent)
12 | val result = SubtitleEncoder.encodeToBcc(data)
13 | val outputFile = File("build/output.bcc")
14 | outputFile.createNewFile()
15 | outputFile.writeText(result)
16 | }
17 |
18 | @Test
19 | fun `encode to srt`() {
20 | val fileContent = this::class.java.getResource("/example.bcc")?.readText()!!
21 | val data = SubtitleParser.fromBccString(fileContent)
22 | val result = SubtitleEncoder.encodeToSrt(data)
23 | val outputFile = File("build/output.srt")
24 | outputFile.createNewFile()
25 | outputFile.writeText(result)
26 | }
27 | }
--------------------------------------------------------------------------------
/bili-subtitle/src/test/kotlin/dev/aaa1115910/bilisubtitle/SubtitleParserTest.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bilisubtitle
2 |
3 | import kotlin.test.Test
4 |
5 | class SubtitleParserTest {
6 | @Test
7 | fun `read bcc subtitle`() {
8 | val fileContent = this::class.java.getResource("/example.bcc")?.readText()!!
9 | val result = SubtitleParser.fromBccString(fileContent)
10 | println(result)
11 | }
12 |
13 | @Test
14 | fun `read srt subtitle`() {
15 | val fileContent = this::class.java.getResource("/example.srt")?.readText()!!
16 | val result = SubtitleParser.fromSrtString(fileContent)
17 | println(result)
18 | }
19 | }
--------------------------------------------------------------------------------
/bili-subtitle/src/test/kotlin/dev/aaa1115910/bilisubtitle/entity/TimestampTest.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bilisubtitle.entity
2 |
3 | import kotlin.test.Test
4 |
5 | class TimestampTest {
6 | @Test
7 | fun `parse bcc time`() {
8 | val time = 7530.2f
9 | println(Timestamp.fromBccString(time))
10 | }
11 |
12 | @Test
13 | fun `parse srt time`() {
14 | val time = "01:03:17,775"
15 | println(Timestamp.fromSrtString(time))
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(gradleLibs.plugins.android.application) apply false
3 | alias(gradleLibs.plugins.android.library) apply false
4 | alias(gradleLibs.plugins.compose.compiler) apply false
5 | alias(gradleLibs.plugins.google.ksp) apply false
6 | alias(gradleLibs.plugins.kotlin.android) apply false
7 | alias(gradleLibs.plugins.kotlin.jvm) apply false
8 | alias(gradleLibs.plugins.kotlin.serialization) apply false
9 | alias(gradleLibs.plugins.versions)
10 | }
--------------------------------------------------------------------------------
/buildSrc/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | }
4 |
5 | repositories {
6 | mavenCentral()
7 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jan 01 20:59:26 CST 2025
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/player/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/player/core/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/player/core/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/player/core/consumer-rules.pro
--------------------------------------------------------------------------------
/player/core/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
--------------------------------------------------------------------------------
/player/core/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/player/core/src/main/assets/GlobalSign ECC Root CA R5.crt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/player/core/src/main/assets/GlobalSign ECC Root CA R5.crt
--------------------------------------------------------------------------------
/player/core/src/main/kotlin/dev/aaa1115910/bv/player/VideoPlayerListener.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player
2 |
3 | interface VideoPlayerListener {
4 | /** 异常 */
5 | fun onError(error: Exception)
6 |
7 | /**
8 | * 准备
9 | */
10 | fun onReady()
11 |
12 | /** 播放 */
13 | fun onPlay()
14 |
15 | /** 暂停 */
16 | fun onPause()
17 |
18 | /** 缓冲中 */
19 | fun onBuffering()
20 |
21 | /** 播放结束 */
22 | fun onEnd()
23 |
24 | /** 空闲,例如播放前 */
25 | fun onIdle()
26 |
27 | /** 后退 */
28 | fun onSeekBack(seekBackIncrementMs: Long)
29 |
30 | /** 前进 */
31 | fun onSeekForward(seekForwardIncrementMs: Long)
32 |
33 | }
--------------------------------------------------------------------------------
/player/core/src/main/kotlin/dev/aaa1115910/bv/player/VideoPlayerOptions.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player
2 |
3 | data class VideoPlayerOptions(
4 | val userAgent: String? = null,
5 | val referer: String? = null,
6 | val enableFfmpegAudioRenderer: Boolean = false
7 | )
--------------------------------------------------------------------------------
/player/core/src/main/kotlin/dev/aaa1115910/bv/player/factory/PlayerFactory.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.factory
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.AbstractVideoPlayer
5 | import dev.aaa1115910.bv.player.VideoPlayerOptions
6 |
7 | abstract class PlayerFactory {
8 | abstract fun create(context: Context, options: VideoPlayerOptions): T
9 | }
--------------------------------------------------------------------------------
/player/core/src/main/kotlin/dev/aaa1115910/bv/player/impl/exo/ExoPlayerFactory.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.impl.exo
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.VideoPlayerOptions
5 | import dev.aaa1115910.bv.player.factory.PlayerFactory
6 |
7 | class ExoPlayerFactory : PlayerFactory() {
8 | override fun create(context: Context, options: VideoPlayerOptions): ExoMediaPlayer {
9 | return ExoMediaPlayer(context, options)
10 | }
11 | }
--------------------------------------------------------------------------------
/player/mobile/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/player/mobile/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/player/mobile/consumer-rules.pro
--------------------------------------------------------------------------------
/player/mobile/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
--------------------------------------------------------------------------------
/player/mobile/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/player/mobile/src/main/kotlin/dev/aaa1115910/bv/player/mobile/MaterialDarkTheme.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.mobile
2 |
3 | import android.os.Build
4 | import androidx.compose.material3.MaterialTheme
5 | import androidx.compose.material3.darkColorScheme
6 | import androidx.compose.material3.dynamicDarkColorScheme
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.ui.platform.LocalContext
9 |
10 | @Composable
11 | fun MaterialDarkTheme(content: @Composable () -> Unit) {
12 | val context = LocalContext.current
13 | val colorScheme =
14 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) dynamicDarkColorScheme(context) else darkColorScheme()
15 |
16 | MaterialTheme(colorScheme = colorScheme) {
17 | content()
18 | }
19 | }
--------------------------------------------------------------------------------
/player/mobile/src/main/kotlin/dev/aaa1115910/bv/player/mobile/NoRippleClickable.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.mobile
2 |
3 | import androidx.compose.foundation.clickable
4 | import androidx.compose.foundation.interaction.MutableInteractionSource
5 | import androidx.compose.runtime.remember
6 | import androidx.compose.ui.Modifier
7 | import androidx.compose.ui.composed
8 |
9 | fun Modifier.noRippleClickable(
10 | enabled: Boolean = true,
11 | onClick: () -> Unit
12 | ): Modifier = composed {
13 | clickable(
14 | indication = null,
15 | interactionSource = remember { MutableInteractionSource() },
16 | enabled = enabled
17 | ) {
18 | onClick()
19 | }
20 | }
--------------------------------------------------------------------------------
/player/shared/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/player/shared/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/player/shared/consumer-rules.pro
--------------------------------------------------------------------------------
/player/shared/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
--------------------------------------------------------------------------------
/player/shared/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/Audio.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.shared.R
5 |
6 | enum class Audio(val code: Int, private val strRes: Int) {
7 | A64K(30216, R.string.audio_64k),
8 | A132K(30232, R.string.audio_132k),
9 | A192K(30280, R.string.audio_192k),
10 | ADolbyAtoms(30250, R.string.audio_dolby_atoms),
11 | AHiRes(30251, R.string.audio_hi_res);
12 |
13 | companion object {
14 | fun fromCode(code: Int) = runCatching {
15 | entries.find { it.code == code }
16 | }.getOrDefault(A64K)
17 | }
18 |
19 | fun getDisplayName(context: Context) = context.getString(strRes)
20 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/DanmakuSize.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | enum class DanmakuSize(val scale: Float) {
4 | S1(0.25f), S2(0.5f), S3(0.6f), S4(0.7f), S5(0.8f), S6(0.9f), S7(1f),
5 | S8(1.1f), S9(1.2f), S10(1.3f), S11(1.4f), S12(1.5f), S13(2f);
6 |
7 | companion object {
8 | fun fromOrdinal(ordinal: Int) = runCatching { entries[ordinal] }
9 | .getOrDefault(S2)
10 | }
11 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/DanmakuTransparency.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | enum class DanmakuTransparency(val transparency: Float) {
4 | T1(1f), T2(0.9f), T3(0.8f), T4(0.7f), T5(0.6f),
5 | T6(0.5f), T7(0.3f), T8(0.2f), T9(0.1f);
6 |
7 | companion object {
8 | fun fromOrdinal(ordinal: Int) = runCatching { entries[ordinal] }
9 | .getOrDefault(T1)
10 | }
11 |
12 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/DanmakuType.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.shared.R
5 |
6 | enum class DanmakuType(private val strRes: Int) {
7 | All(R.string.video_player_menu_danmaku_type_all),
8 | Top(R.string.video_player_menu_danmaku_type_top),
9 | Rolling(R.string.video_player_menu_danmaku_type_cross),
10 | Bottom(R.string.video_player_menu_danmaku_type_bottom);
11 |
12 | fun getDisplayName(context: Context) = context.getString(strRes)
13 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/RequestState.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | enum class RequestState {
4 | Ready, Doing, Done, Success, Failed
5 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/VideoAspectRatio.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.shared.R
5 |
6 | enum class VideoAspectRatio(private val strRes: Int) {
7 | Default(R.string.video_aspect_ratio_default),
8 | FourToThree(R.string.video_aspect_ratio_four_to_three),
9 | SixteenToNine(R.string.video_aspect_ratio_sixteen_to_nine);
10 |
11 | fun getDisplayName(context: Context) = context.getString(strRes)
12 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/VideoPlayerClosedCaptionMenuItem.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.shared.R
5 |
6 | enum class VideoPlayerClosedCaptionMenuItem(private val strRes: Int) {
7 | Switch(R.string.video_player_menu_subtitle_switch),
8 | Size(R.string.video_player_menu_subtitle_size),
9 | Opacity(R.string.video_player_menu_subtitle_background_opacity),
10 | Padding(R.string.video_player_menu_subtitle_bottom_padding);
11 |
12 | fun getDisplayName(context: Context) = context.getString(strRes)
13 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/VideoPlayerDanmakuMenuItem.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.shared.R
5 |
6 | enum class VideoPlayerDanmakuMenuItem(private val strRes: Int) {
7 | Switch(R.string.video_player_menu_danmaku_switch),
8 | Size(R.string.video_player_menu_danmaku_size),
9 | Opacity(R.string.video_player_menu_danmaku_opacity),
10 | Area(R.string.video_player_menu_danmaku_area),
11 | Mask(R.string.video_player_menu_danmaku_mask);
12 |
13 | fun getDisplayName(context: Context) = context.getString(strRes)
14 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/VideoPlayerMenuNavItem.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | import android.content.Context
4 | import androidx.compose.material.icons.Icons
5 | import androidx.compose.material.icons.outlined.ClearAll
6 | import androidx.compose.material.icons.outlined.ClosedCaption
7 | import androidx.compose.material.icons.outlined.Image
8 | import androidx.compose.ui.graphics.vector.ImageVector
9 | import dev.aaa1115910.bv.player.shared.R
10 |
11 | enum class VideoPlayerMenuNavItem(private val strRes: Int, val icon: ImageVector) {
12 | Picture(R.string.video_player_menu_nav_picture, Icons.Outlined.Image),
13 | Danmaku(R.string.video_player_menu_nav_danmaku, Icons.Outlined.ClearAll),
14 | ClosedCaption(R.string.video_player_menu_nav_subtitle, Icons.Outlined.ClosedCaption);
15 |
16 | fun getDisplayName(context: Context) = context.getString(strRes)
17 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/entity/VideoPlayerPictureMenuItem.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.entity
2 |
3 | import android.content.Context
4 | import dev.aaa1115910.bv.player.shared.R
5 |
6 | enum class VideoPlayerPictureMenuItem(private val strRes: Int) {
7 | Resolution(R.string.video_player_menu_picture_resolution),
8 | Codec(R.string.video_player_menu_picture_codec),
9 | AspectRatio(R.string.video_player_menu_picture_aspect_ratio),
10 | PlaySpeed(R.string.video_player_menu_picture_play_speed),
11 | Audio(R.string.video_player_menu_picture_audio);
12 |
13 | fun getDisplayName(context: Context) = context.getString(strRes)
14 | }
--------------------------------------------------------------------------------
/player/shared/src/main/kotlin/dev/aaa1115910/bv/player/seekbar/SeekMoveState.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.player.seekbar
2 |
3 | enum class SeekMoveState {
4 | Backward,
5 | Forward,
6 | Idle
7 | }
--------------------------------------------------------------------------------
/player/tv/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/player/tv/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/player/tv/consumer-rules.pro
--------------------------------------------------------------------------------
/player/tv/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
--------------------------------------------------------------------------------
/player/tv/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/screenshots.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/screenshots.webp
--------------------------------------------------------------------------------
/screenshots1.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/screenshots1.webp
--------------------------------------------------------------------------------
/screenshots2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/screenshots2.webp
--------------------------------------------------------------------------------
/utils/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/utils/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leelion96/bv/70ad3d8a784e78bdec28d084fbb5ceee2c4a1f17/utils/consumer-rules.pro
--------------------------------------------------------------------------------
/utils/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
--------------------------------------------------------------------------------
/utils/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/utils/src/main/kotlin/dev/aaa1115910/bv/util/FirebaseUtil.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import android.content.Context
4 | import com.google.firebase.FirebaseApp
5 | import com.google.firebase.analytics.ktx.analytics
6 | import com.google.firebase.crashlytics.ktx.crashlytics
7 | import com.google.firebase.ktx.Firebase
8 |
9 | object FirebaseUtil {
10 | private var initialized = false
11 |
12 | fun init(context: Context) {
13 | initialized = FirebaseApp.initializeApp(context) != null
14 | }
15 |
16 | fun log(msg: String) {
17 | if (!initialized) return
18 | Firebase.crashlytics.log(msg)
19 | }
20 |
21 | fun recordException(throwable: Throwable) {
22 | if (!initialized) return
23 | Firebase.crashlytics.recordException(throwable)
24 | }
25 |
26 | fun setCrashlyticsCollectionEnabled(enable: Boolean) {
27 | if (!initialized) return
28 | Firebase.crashlytics.setCrashlyticsCollectionEnabled(enable)
29 | Firebase.analytics.setAnalyticsCollectionEnabled(enable)
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/utils/src/main/kotlin/dev/aaa1115910/bv/util/FocusRequesterExtends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import androidx.compose.ui.focus.FocusRequester
4 | import kotlinx.coroutines.CoroutineScope
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.launch
8 |
9 | /**
10 | * 改进的请求焦点的方法,失败后等待 100ms 后重试
11 | */
12 | fun FocusRequester.requestFocus(scope: CoroutineScope) {
13 | scope.launch(Dispatchers.Default) {
14 | runCatching {
15 | requestFocus()
16 | }.onFailure {
17 | delay(100)
18 | runCatching { requestFocus() }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/utils/src/main/kotlin/dev/aaa1115910/bv/util/LongExtends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import java.util.concurrent.TimeUnit
4 |
5 | fun Long.formatMinSec(): String {
6 | return if (this < 0L) {
7 | "00:00"
8 | } else {
9 | String.format(
10 | "%02d:%02d",
11 | TimeUnit.MILLISECONDS.toMinutes(this),
12 | TimeUnit.MILLISECONDS.toSeconds(this) -
13 | TimeUnit.MINUTES.toSeconds(
14 | TimeUnit.MILLISECONDS.toMinutes(this)
15 | )
16 | )
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/utils/src/main/kotlin/dev/aaa1115910/bv/util/SnapshotStateListExtends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import androidx.compose.runtime.snapshots.SnapshotStateList
4 |
5 | fun SnapshotStateList.swapList(newList: List) {
6 | clear()
7 | addAll(newList)
8 | }
9 |
--------------------------------------------------------------------------------
/utils/src/main/kotlin/dev/aaa1115910/bv/util/ToastExtends.kt:
--------------------------------------------------------------------------------
1 | package dev.aaa1115910.bv.util
2 |
3 | import android.content.Context
4 | import android.widget.Toast
5 |
6 | fun String.toast(context: Context, duration: Int = Toast.LENGTH_SHORT) {
7 | Toast.makeText(context, this, duration).show()
8 | }
9 |
10 | fun Int.toast(context: Context, duration: Int = Toast.LENGTH_SHORT) {
11 | Toast.makeText(context, context.getText(this), duration).show()
12 | }
--------------------------------------------------------------------------------