import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/http/api.dart'; import 'package:PiliPlus/http/browser_ua.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/login.dart'; import 'package:PiliPlus/models/common/account_type.dart'; import 'package:PiliPlus/models/common/live/live_contribution_rank_type.dart'; import 'package:PiliPlus/models/common/live/live_search_type.dart'; import 'package:PiliPlus/models_new/live/live_area_list/area_item.dart'; import 'package:PiliPlus/models_new/live/live_area_list/area_list.dart'; import 'package:PiliPlus/models_new/live/live_contribution_rank/data.dart'; import 'package:PiliPlus/models_new/live/live_danmaku/danmaku_msg.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/data.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/shield_info.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/shield_user_list.dart'; import 'package:PiliPlus/models_new/live/live_dm_info/data.dart'; import 'package:PiliPlus/models_new/live/live_emote/data.dart'; import 'package:PiliPlus/models_new/live/live_emote/datum.dart'; import 'package:PiliPlus/models_new/live/live_feed_index/data.dart'; import 'package:PiliPlus/models_new/live/live_follow/data.dart'; import 'package:PiliPlus/models_new/live/live_room_info_h5/data.dart'; import 'package:PiliPlus/models_new/live/live_room_play_info/data.dart'; import 'package:PiliPlus/models_new/live/live_search/data.dart'; import 'package:PiliPlus/models_new/live/live_second_list/data.dart'; import 'package:PiliPlus/models_new/live/live_superchat/data.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts/account.dart'; import 'package:PiliPlus/utils/app_sign.dart'; import 'package:PiliPlus/utils/wbi_sign.dart'; import 'package:dio/dio.dart'; abstract final class LiveHttp { static Account get recommend => Accounts.get(AccountType.recommend); static Future> sendLiveMsg({ required Object roomId, required Object msg, Object? dmType, Object? emoticonOptions, int replyMid = 0, String replayDmid = '', }) async { String csrf = Accounts.main.csrf; final res = await Request().post( Api.sendLiveMsg, queryParameters: await WbiSign.makSign({ 'web_location': 444.8, }), data: FormData.fromMap({ 'bubble': 0, 'msg': msg, 'color': 16777215, 'mode': 1, 'dm_type': ?dmType, if (emoticonOptions != null) 'emoticonOptions': emoticonOptions else ...{ 'room_type': 0, 'jumpfrom': 0, 'reply_mid': replyMid, 'reply_attr': 0, 'replay_dmid': replayDmid, 'statistics': '{"appId":100,"platform":5}', 'reply_type': 0, 'reply_uname': '', }, 'fontsize': 25, 'rnd': DateTime.now().millisecondsSinceEpoch ~/ 1000, 'roomid': roomId, 'csrf': csrf, 'csrf_token': csrf, }), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } static Future> liveRoomInfo({ required Object roomId, Object? qn, bool onlyAudio = false, }) async { final res = await Request().get( Api.liveRoomInfo, queryParameters: await WbiSign.makSign({ 'room_id': roomId, 'protocol': '0,1', 'format': '0,1,2', 'codec': '0,1,2', 'qn': ?qn, 'platform': 'web', 'ptype': 8, 'dolby': 5, 'panorama': 1, if (onlyAudio) 'only_audio': 1, 'web_location': 444.8, }), ); if (res.data['code'] == 0) { return Success(RoomPlayInfoData.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future> liveRoomInfoH5({ required Object roomId, }) async { final res = await Request().get( Api.liveRoomInfoH5, queryParameters: { 'room_id': roomId, }, ); if (res.data['code'] == 0) { return Success(RoomInfoH5Data.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future?>> liveRoomDmPrefetch({ required Object roomId, }) async { final res = await Request().get( Api.liveRoomDmPrefetch, queryParameters: {'roomid': roomId}, options: Options( headers: { 'referer': 'https://live.bilibili.com/$roomId', 'user-agent': BrowserUa.pc, }, ), ); if (res.data['code'] == 0) { try { return Success( (res.data['data']?['room'] as List?) ?.map((e) => DanmakuMsg.fromPrefetch(e)) .toList(), ); } catch (e) { return Error(e.toString()); } } else { return Error(res.data['message']); } } static Future> liveRoomGetDanmakuToken({ required Object roomId, }) async { final res = await Request().get( Api.liveRoomDmToken, queryParameters: await WbiSign.makSign({ 'id': roomId, 'web_location': 444.8, }), ); if (res.data['code'] == 0) { return Success(LiveDmInfoData.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future?>> getLiveEmoticons({ required int roomId, }) async { final res = await Request().get( Api.getLiveEmoticons, queryParameters: { 'platform': 'pc', 'room_id': roomId, }, ); if (res.data['code'] == 0) { return Success(LiveEmoteData.fromJson(res.data['data']).data); } else { return Error(res.data['message']); } } static Future> liveFeedIndex({ required int pn, bool moduleSelect = false, }) async { final params = { 'access_key': ?recommend.accessKey, 'channel': 'master', 'actionKey': 'appkey', 'build': 8430300, 'version': '8.43.0', 'c_locale': 'zh_CN', 'device': 'android', 'device_name': 'android', 'device_type': 0, 'fnval': 912, 'disable_rcmd': 0, 'https_url_req': 1, if (moduleSelect) 'module_select': 1, 'mobi_app': 'android', 'network': 'wifi', 'page': pn, 'platform': 'android', if (recommend.isLogin) 'relation_page': 1, 's_locale': 'zh_CN', 'scale': 2, 'statistics': Constants.statisticsApp, }; AppSign.appSign(params); final res = await Request().get( Api.liveFeedIndex, queryParameters: params, options: Options( headers: { 'buvid': LoginHttp.buvid, 'fp_local': '1111111111111111111111111111111111111111111111111111111111111111', 'fp_remote': '1111111111111111111111111111111111111111111111111111111111111111', 'session_id': '11111111', 'env': 'prod', 'app-key': 'android', 'User-Agent': Constants.userAgentApp, 'x-bili-trace-id': Constants.traceId, 'x-bili-aurora-eid': '', 'x-bili-aurora-zone': '', 'bili-http-engine': 'cronet', }, ), ); if (res.data['code'] == 0) { return Success(LiveIndexData.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future> liveFollow(int page) async { final res = await Request().get( Api.liveFollow, queryParameters: { 'page': page, 'page_size': 9, 'ignoreRecord': 1, 'hit_ab': true, }, ); if (res.data['code'] == 0) { return Success(LiveFollowData.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future> liveSecondList({ required int pn, required Object? areaId, required Object? parentAreaId, String? sortType, }) async { final params = { 'access_key': ?recommend.accessKey, 'actionKey': 'appkey', 'channel': 'master', 'area_id': ?areaId, 'parent_area_id': ?parentAreaId, 'build': 8430300, 'version': '8.43.0', 'c_locale': 'zh_CN', 'device': 'android', 'device_name': 'android', 'device_type': 0, 'fnval': 912, 'disable_rcmd': 0, 'https_url_req': 1, 'mobi_app': 'android', 'module_select': 0, 'network': 'wifi', 'page': pn, 'page_size': 20, 'platform': 'android', 'qn': 0, 'sort_type': ?sortType, 'tag_version': 1, 's_locale': 'zh_CN', 'scale': 2, 'statistics': Constants.statisticsApp, }; AppSign.appSign(params); final res = await Request().get( Api.liveSecondList, queryParameters: params, options: Options( headers: { 'buvid': LoginHttp.buvid, 'fp_local': '1111111111111111111111111111111111111111111111111111111111111111', 'fp_remote': '1111111111111111111111111111111111111111111111111111111111111111', 'session_id': '11111111', 'env': 'prod', 'app-key': 'android', 'User-Agent': Constants.userAgentApp, 'x-bili-trace-id': Constants.traceId, 'x-bili-aurora-eid': '', 'x-bili-aurora-zone': '', 'bili-http-engine': 'cronet', }, ), ); if (res.data['code'] == 0) { return Success(LiveSecondData.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future?>> liveAreaList() async { final params = { 'access_key': ?recommend.accessKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', 'version': '8.43.0', 'c_locale': 'zh_CN', 'device': 'android', 'disable_rcmd': 0, 'mobi_app': 'android', 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, }; AppSign.appSign(params); final res = await Request().get( Api.liveAreaList, queryParameters: params, ); if (res.data['code'] == 0) { return Success( (res.data['data']?['list'] as List?) ?.map((e) => AreaList.fromJson(e)) .toList(), ); } else { return Error(res.data['message']); } } static Future>> getLiveFavTag() async { final params = { 'access_key': ?Accounts.main.accessKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', 'version': '8.43.0', 'c_locale': 'zh_CN', 'device': 'android', 'disable_rcmd': 0, 'mobi_app': 'android', 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, }; AppSign.appSign(params); final res = await Request().get( Api.getLiveFavTag, queryParameters: params, ); if (res.data['code'] == 0) { return Success( (res.data['data']?['tags'] as List?) ?.map((e) => AreaItem.fromJson(e)) .toList() ?? [], ); } else { return Error(res.data['message']); } } static Future> setLiveFavTag({ required String ids, }) async { final data = { 'tags': ids, 'access_key': Accounts.main.accessKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', 'version': '8.43.0', 'c_locale': 'zh_CN', 'device': 'android', 'disable_rcmd': 0, 'mobi_app': 'android', 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, }; AppSign.appSign(data); final res = await Request().post( Api.setLiveFavTag, data: data, options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } static Future?>> liveRoomAreaList({ required Object parentid, }) async { final params = { 'access_key': ?recommend.accessKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', 'version': '8.43.0', 'c_locale': 'zh_CN', 'device': 'android', 'disable_rcmd': 0, 'need_entrance': 1, 'parent_id': parentid, 'source_id': 2, 'mobi_app': 'android', 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, }; AppSign.appSign(params); final res = await Request().get( Api.liveRoomAreaList, queryParameters: params, ); if (res.data['code'] == 0) { return Success( (res.data['data'] as List?)?.map((e) => AreaItem.fromJson(e)).toList(), ); } else { return Error(res.data['message']); } } static Future> liveSearch({ required int page, required String keyword, required LiveSearchType type, }) async { final params = { 'access_key': ?recommend.accessKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', 'version': '8.43.0', 'c_locale': 'zh_CN', 'device': 'android', 'page': page, 'pagesize': 30, 'keyword': keyword, 'disable_rcmd': 0, 'mobi_app': 'android', 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, 'type': type.name, }; AppSign.appSign(params); final res = await Request().get( Api.liveSearch, queryParameters: params, ); if (res.data['code'] == 0) { return Success(LiveSearchData.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future> getLiveInfoByUser( Object roomId, ) async { final res = await Request().get( Api.getLiveInfoByUser, queryParameters: await WbiSign.makSign({ 'room_id': roomId, 'from': 0, 'not_mock_enter_effect': 1, 'web_location': 444.8, }), ); if (res.data['code'] == 0) { return Success(LiveDmBlockData.fromJson(res.data['data']).shieldInfo); } else { return Error(res.data['message']); } } static Future> liveSetSilent({ required String type, required int level, }) async { final csrf = Accounts.main.csrf; final res = await Request().post( Api.liveSetSilent, data: { 'type': type, 'level': level, 'csrf': csrf, 'csrf_token': csrf, }, options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } static Future> addShieldKeyword({ required String keyword, }) async { final csrf = Accounts.main.csrf; final res = await Request().post( Api.addShieldKeyword, data: { 'keyword': keyword, 'csrf': csrf, 'csrf_token': csrf, }, options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } static Future> delShieldKeyword({ required String keyword, }) async { final csrf = Accounts.main.csrf; final res = await Request().post( Api.delShieldKeyword, data: { 'keyword': keyword, 'csrf': csrf, 'csrf_token': csrf, }, options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } static Future> liveShieldUser({ required Object uid, required Object roomid, required int type, }) async { final csrf = Accounts.main.csrf; final res = await Request().post( Api.liveShieldUser, data: { 'uid': uid, 'roomid': roomid, 'type': type, 'csrf': csrf, 'csrf_token': csrf, }, options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return Success(ShieldUserList.fromJson(res.data['data'])); } else { return Error(res.data['message']); } } static Future> liveLikeReport({ required int clickTime, required Object roomId, required Object uid, Object? anchorId, }) async { final res = await Request().post( Api.liveLikeReport, data: await WbiSign.makSign({ 'click_time': clickTime, 'room_id': roomId, 'uid': uid, 'anchor_id': ?anchorId, 'web_location': 444.8, 'csrf': Accounts.heartbeat.csrf, }), options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } @pragma('vm:notify-debugger-on-exception') static Future> superChatMsg( Object roomId, ) async { final res = await Request().get( Api.superChatMsg, queryParameters: { 'room_id': roomId, }, ); if (res.data['code'] == 0) { try { return Success(SuperChatData.fromJson(res.data['data'])); } catch (e, s) { return Error('$e\n\n$s'); } } else { return Error(res.data['message']); } } static Future> liveDmReport({ required int roomId, required Object mid, required String msg, required String reason, required int reasonId, required int dmType, required Object idStr, required Object ts, required Object sign, }) async { final csrf = Accounts.main.csrf; final data = { 'id': 0, 'roomid': roomId, 'tuid': mid, 'msg': msg, 'reason': reason, 'ts': ts, 'sign': sign, 'reason_id': reasonId, 'token': '', 'dm_type': dmType, 'id_str': idStr, 'csrf_token': csrf, 'csrf': csrf, 'visit_id': '', }; final res = await Request().post( Api.liveDmReport, data: data, options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } static Future> liveContributionRank({ required Object ruid, required Object roomId, required int page, required LiveContributionRankType type, }) async { final res = await Request().get( Api.liveContributionRank, queryParameters: await WbiSign.makSign({ 'ruid': ruid, 'room_id': roomId, 'page': page, 'page_size': 100, 'type': type.name, 'switch': type.sw1tch, 'platform': 'web', 'web_location': 444.8, }), ); if (res.data['code'] == 0) { try { return Success(LiveContributionRankData.fromJson(res.data['data'])); } catch (e, s) { return Error('$e\n\n$s'); } } else { return Error(res.data['message']); } } static Future> superChatReport({ required int id, required Object roomId, required Object uid, required String msg, required String reason, required int ts, required String token, }) async { final csrf = Accounts.main.csrf; final res = await Request().post( Api.superChatReport, data: { 'id': id, 'roomid': roomId, 'uid': uid, 'msg': msg, 'reason': reason, 'ts': ts, 'sign': '', 'reason_id': reason, 'token': token, 'id_str': id.toString(), 'csrf_token': csrf, 'csrf': csrf, 'visit_id': '', }, options: Options(contentType: Headers.formUrlEncodedContentType), ); if (res.data['code'] == 0) { return const Success(null); } else { return Error(res.data['message']); } } }