opt: account (#1306)

* opt: account

* opt: account

* opt: live api

* opt: buvid

* Revert "opt: buvid"

This reverts commit da1ea68f8b.

* tweak
This commit is contained in:
My-Responsitories
2025-09-23 15:58:40 +08:00
committed by GitHub
parent 6b4fb0d611
commit 1345fd36e4
18 changed files with 173 additions and 208 deletions

View File

@@ -7,9 +7,12 @@ import 'package:hive/hive.dart';
abstract class Accounts {
static late final Box<LoginAccount> account;
static final Map<AccountType, Account> accountMode = {};
static Account get main => accountMode[AccountType.main]!;
static Account get heartbeat => accountMode[AccountType.heartbeat]!;
static final List<Account> accountMode = List.filled(
AccountType.values.length,
AnonymousAccount(),
);
static Account get main => accountMode[AccountType.main.index];
static Account get heartbeat => accountMode[AccountType.heartbeat.index];
static Account get history {
final heartbeat = Accounts.heartbeat;
if (heartbeat is AnonymousAccount) {
@@ -70,14 +73,11 @@ abstract class Accounts {
static Future<void> refresh() async {
for (var a in account.values) {
for (var t in a.type) {
accountMode[t] = a;
accountMode[t.index] = a;
}
}
for (var type in AccountType.values) {
accountMode[type] ??= AnonymousAccount();
}
await Future.wait(
(accountMode.values.toSet()..retainWhere((i) => !i.activited)).map(
(accountMode.toSet()..removeWhere((i) => i.activited)).map(
Request.buvidActive,
),
);
@@ -85,7 +85,7 @@ abstract class Accounts {
static Future<void> clear() async {
await account.clear();
for (var i in AccountType.values) {
for (int i = 0; i < AccountType.values.length; i++) {
accountMode[i] = AnonymousAccount();
}
await AnonymousAccount().delete();
@@ -100,9 +100,11 @@ abstract class Accounts {
static Future<void> deleteAll(Set<Account> accounts) async {
var isloginMain = Accounts.main.isLogin;
Accounts.accountMode.updateAll(
(_, a) => accounts.contains(a) ? AnonymousAccount() : a,
);
for (int i = 0; i < AccountType.values.length; i++) {
if (accounts.contains(accountMode[i])) {
accountMode[i] = AnonymousAccount();
}
}
await Future.wait(accounts.map((i) => i.delete()));
if (isloginMain && !Accounts.main.isLogin) {
await LoginUtils.onLogoutMain();
@@ -110,8 +112,8 @@ abstract class Accounts {
}
static Future<void> set(AccountType key, Account account) async {
await (accountMode[key]?..type.remove(key))?.onChange();
accountMode[key] = account..type.add(key);
await (accountMode[key.index]..type.remove(key)).onChange();
accountMode[key.index] = account..type.add(key);
await account.onChange();
if (!account.activited) await Request.buvidActive(account);
switch (key) {
@@ -129,6 +131,6 @@ abstract class Accounts {
}
static Account get(AccountType key) {
return accountMode[key]!;
return accountMode[key.index];
}
}

View File

@@ -5,41 +5,52 @@ import 'package:PiliPlus/utils/id_utils.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:hive/hive.dart';
abstract class Account {
final bool isLogin = false;
late final DefaultCookieJar cookieJar;
String? accessKey;
String? refresh;
late final Set<AccountType> type;
sealed class Account {
Map<String, dynamic>? toJson() => null;
final int mid = 0;
late String csrf;
final Map<String, String> headers = const {};
Future<void> onChange() => Future.value();
bool activited = false;
Set<AccountType> get type => const {};
Future<void> delete();
Future<void> onChange();
bool get activited => false;
Map<String, dynamic>? toJson();
set activited(bool value) => throw UnimplementedError();
String? get accessKey => throw UnimplementedError();
DefaultCookieJar get cookieJar => throw UnimplementedError();
String get csrf => throw UnimplementedError();
Future<void> delete() => throw UnimplementedError();
Map<String, String> get headers => throw UnimplementedError();
bool get isLogin => throw UnimplementedError();
int get mid => throw UnimplementedError();
String? get refresh => throw UnimplementedError();
const Account();
}
@HiveType(typeId: 9)
class LoginAccount implements Account {
class LoginAccount extends Account {
@override
final bool isLogin = true;
@override
@HiveField(0)
late final DefaultCookieJar cookieJar;
final DefaultCookieJar cookieJar;
@override
@HiveField(1)
String? accessKey;
final String? accessKey;
@override
@HiveField(2)
String? refresh;
final String? refresh;
@override
@HiveField(3)
late final Set<AccountType> type;
final Set<AccountType> type;
@override
bool activited = false;
@@ -55,14 +66,22 @@ class LoginAccount implements Account {
};
@override
late String csrf =
late final String csrf =
cookieJar.domainCookies['bilibili.com']!['/']!['bili_jct']!.cookie.value;
@override
Future<void> delete() => _box.delete(_midStr);
bool _hasDelete = false;
@override
Future<void> onChange() => _box.put(_midStr, this);
Future<void> delete() {
assert(_hasDelete = true);
return _box.delete(_midStr);
}
@override
Future<void> onChange() {
assert(!_hasDelete);
return _box.put(_midStr, this);
}
@override
Map<String, dynamic>? toJson() => {
@@ -88,16 +107,12 @@ class LoginAccount implements Account {
cookieJar.setBuvid3();
}
LoginAccount.fromJson(Map json) {
cookieJar = BiliCookieJar.fromJson(json['cookies'])..setBuvid3();
accessKey = json['accessKey'];
refresh = json['refresh'];
type =
(json['type'] as Iterable?)
?.map((i) => AccountType.values[i])
.toSet() ??
{};
}
factory LoginAccount.fromJson(Map json) => LoginAccount(
BiliCookieJar.fromJson(json['cookies']),
json['accessKey'],
json['refresh'],
(json['type'] as Iterable?)?.map((i) => AccountType.values[i]).toSet(),
);
@override
int get hashCode => mid.hashCode;
@@ -107,21 +122,21 @@ class LoginAccount implements Account {
identical(this, other) || (other is LoginAccount && mid == other.mid);
}
class AnonymousAccount implements Account {
class AnonymousAccount extends Account {
@override
final bool isLogin = false;
@override
late final DefaultCookieJar cookieJar;
final DefaultCookieJar cookieJar = DefaultCookieJar()..setBuvid3();
@override
String? accessKey;
final String? accessKey = null;
@override
String? refresh;
final String? refresh = null;
@override
Set<AccountType> type = {};
final Set<AccountType> type = {};
@override
final int mid = 0;
@override
String csrf = '';
final String csrf = '';
@override
final Map<String, String> headers = Constants.baseHeaders;
@@ -134,17 +149,9 @@ class AnonymousAccount implements Account {
cookieJar.setBuvid3();
}
@override
Future<void> onChange() async {}
@override
Map<String, dynamic>? toJson() => null;
static final _instance = AnonymousAccount._();
AnonymousAccount._() {
cookieJar = DefaultCookieJar(ignoreExpires: true)..setBuvid3();
}
AnonymousAccount._();
factory AnonymousAccount() => _instance;
@@ -179,8 +186,9 @@ extension BiliCookieJar on DefaultCookieJar {
[];
void setBuvid3() {
domainCookies['bilibili.com'] ??= {'/': {}};
domainCookies['bilibili.com']!['/']!['buvid3'] ??= SerializableCookie(
(domainCookies['bilibili.com'] ??= {
'/': {},
})['/']!['buvid3'] ??= SerializableCookie(
Cookie('buvid3', IdUtils.genBuvid3())..setBiliDomain(),
);
}
@@ -208,52 +216,6 @@ extension BiliCookieJar on DefaultCookieJar {
};
}
class NoAccount implements Account {
@override
String? accessKey;
@override
bool activited = false;
@override
DefaultCookieJar cookieJar = DefaultCookieJar();
@override
String csrf = '';
@override
String? refresh;
@override
Set<AccountType> type = const {};
@override
Future<void> delete() {
return Future.value();
}
@override
final Map<String, String> headers = const {};
@override
bool isLogin = false;
@override
int mid = 0;
@override
Future<void> onChange() {
return Future.value();
}
@override
Map<String, dynamic>? toJson() {
return null;
}
NoAccount._();
static final _instance = NoAccount._();
factory NoAccount() => _instance;
final class NoAccount extends Account {
const NoAccount();
}

View File

@@ -51,6 +51,7 @@ class AccountManager extends Interceptor {
Api.getSeasonDetailApi,
Api.liveRoomDmToken,
Api.liveRoomDmPrefetch,
Api.superChatMsg,
Api.searchByType,
Api.dynSearch,
Api.searchArchive,
@@ -68,6 +69,18 @@ class AccountManager extends Interceptor {
Api.liveList,
Api.searchTrending,
Api.searchRecommend,
Api.getRankApi,
Api.pgcRank,
Api.pgcSeasonRank,
Api.pgcIndexResult,
Api.popularSeriesOne,
Api.popularSeriesList,
Api.popularPrecious,
Api.liveAreaList,
Api.liveFeedIndex,
Api.liveSecondList,
Api.liveRoomAreaList,
Api.liveSearch,
},
// progress
AccountType.video: {
@@ -118,7 +131,7 @@ class AccountManager extends Interceptor {
late final Account account = options.extra['account'] ?? _findAccount(path);
if (_skipCookie(path) || account is NoAccount) return handler.next(options);
if (account is NoAccount || _skipCookie(path)) return handler.next(options);
if (!account.isLogin && path == Api.heartBeat) {
return handler.reject(

View File

@@ -25,7 +25,7 @@ abstract class Update {
Api.latestApp,
options: Options(
headers: {'user-agent': UaType.mob.ua},
extra: {'account': NoAccount()},
extra: {'account': const NoAccount()},
),
);
if (res.data is Map || res.data.isEmpty) {