Skip to content

Commit

Permalink
Support one-click refresh of igneous cookie
Browse files Browse the repository at this point in the history
支持一键刷新igneous cookie
  • Loading branch information
jiangtian616 committed Sep 24, 2024
1 parent 36fd867 commit 5bbeef8
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 6 deletions.
2 changes: 2 additions & 0 deletions changelog/v8.0.2.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
- 支持一键刷新igneous cookie
- 修复在部分场景下,注销后cookie仍然保留的bug
- 修复E站更新后无法显示图片配额的bug;现在仅有捐赠者会显示图片配额;去除重置图片配额的功能

- Support one-click refresh of igneous cookie
- Fix the bug that cookies are still retained after logout in some scenarios
- Fix the bug that the image quota cannot be displayed after updating of E-Hentai. Now only image quota will only be displayed for donators. Remove the function of resetting the image quota
2 changes: 2 additions & 0 deletions lib/src/consts/eh_consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,6 @@ class EHConsts {
static const String EX509ImageUrl = 'https://exhentai.org/img/509.gif';

static const String desktopWebviewDirectoryName = 'EBWebView';

static const String igneousCookieName = 'igneous';
}
164 changes: 161 additions & 3 deletions lib/src/pages/setting/account/cookie/cookie_page.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
import 'dart:io';

import 'package:clipboard/clipboard.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/get_rx/get_rx.dart';
import 'package:get/get_utils/get_utils.dart';
import 'package:jhentai/src/consts/eh_consts.dart';
import 'package:jhentai/src/extension/dio_exception_extension.dart';
import 'package:jhentai/src/extension/widget_extension.dart';
import 'package:jhentai/src/network/eh_request.dart';
import 'package:jhentai/src/setting/user_setting.dart';
import 'package:jhentai/src/utils/cookie_util.dart';
import 'package:jhentai/src/utils/snack_util.dart';
import 'package:jhentai/src/utils/toast_util.dart';
import 'package:jhentai/src/widget/loading_state_indicator.dart';

import '../../../../exception/eh_site_exception.dart';
import '../../../../network/eh_ip_provider.dart';
import '../../../../network/eh_timeout_translator.dart';
import '../../../../service/log.dart';
import '../../../../setting/network_setting.dart';

class CookiePage extends StatelessWidget {
const CookiePage({Key? key}) : super(key: key);
class CookiePage extends StatefulWidget {
const CookiePage({super.key});

@override
State<CookiePage> createState() => _CookiePageState();
}

class _CookiePageState extends State<CookiePage> {
Dio? _dio;
LoadingState _refreshIgneousState = LoadingState.idle;

@override
Widget build(BuildContext context) {
Expand All @@ -26,6 +50,20 @@ class CookiePage extends StatelessWidget {
(cookie) => ListTile(
title: Text(cookie.name),
subtitle: Text(cookie.value),
trailing: cookie.name == EHConsts.igneousCookieName
? Row(
mainAxisSize: MainAxisSize.min,
children: [
LoadingStateIndicator(
loadingState: _refreshIgneousState,
loadingWidgetBuilder: () => const CupertinoActivityIndicator().marginOnly(right: 10),
idleWidgetBuilder: () => IconButton(icon: const Icon(Icons.refresh), onPressed: _refreshIgneousCookie),
successWidgetSameWithIdle: true,
errorWidgetSameWithIdle: true,
)
],
)
: null,
onTap: _copyAllCookies,
dense: true,
),
Expand All @@ -52,4 +90,124 @@ class CookiePage extends StatelessWidget {
);
toast('hasCopiedToClipboard'.tr);
}

Future<void> _refreshIgneousCookie() async {
if (!userSetting.hasLoggedIn()) {
return;
}

await _initDio();

if (_refreshIgneousState == LoadingState.loading) {
return;
}

setStateSafely(() {
_refreshIgneousState = LoadingState.loading;
});

try {
Response response = await _dio!.request(
EHConsts.EXIndex,
options: Options(headers: {
'cookie': CookieUtil.parse2String(
[
Cookie('ipb_member_id', userSetting.ipbMemberId.value.toString()),
Cookie('ipb_pass_hash', userSetting.ipbPassHash.value!),
],
)
}),
);

log.info('Refresh igneous cookie, set-cookie: ${response.headers.value('set-cookie')}');

response.headers.value('set-cookie')?.split(';').forEach((cookie) {
String name = cookie.split('=')[0];
String value = cookie.split('=')[1];
if (name == EHConsts.igneousCookieName) {
ehRequest.storeEHCookies([Cookie(name, value)]);
}
});

toast('success'.tr);

setStateSafely(() {
_refreshIgneousState = LoadingState.success;
});
} on DioException catch (e) {
log.error('Refresh igneous failed: ${e.message}');
snack('refreshIgneousFailed'.tr, e.errorMsg ?? '');
setStateSafely(() {
_refreshIgneousState = LoadingState.error;
});
return;
} on EHSiteException catch (e) {
log.error('Refresh igneous failed: ${e.message}');
snack('refreshIgneousFailed'.tr, e.message);
setStateSafely(() {
_refreshIgneousState = LoadingState.error;
});
return;
} catch (e, s) {
log.error('Refresh igneous failed: $e');
snack('refreshIgneousFailed'.tr, e.toString());
setStateSafely(() {
_refreshIgneousState = LoadingState.error;
});
return;
}
}

Future<void> _initDio() async {
if (_dio != null) {
return;
}

_dio = Dio(BaseOptions(
connectTimeout: Duration(milliseconds: networkSetting.connectTimeout.value),
receiveTimeout: Duration(milliseconds: networkSetting.receiveTimeout.value),
));

EHIpProvider _ehIpProvider = RoundRobinIpProvider(NetworkSetting.host2IPs);

_dio!.interceptors.add(InterceptorsWrapper(
onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
if (networkSetting.enableDomainFronting.isFalse) {
handler.next(options);
return;
}

String rawPath = options.path;
String host = options.uri.host;
if (!_ehIpProvider.supports(host)) {
handler.next(options);
return;
}

String ip = _ehIpProvider.nextIP(host);
handler.next(options.copyWith(
path: rawPath.replaceFirst(host, ip),
headers: {...options.headers, 'host': host},
extra: options.extra..[EHRequest.domainFrontingExtraKey] = {'host': host, 'ip': ip},
));
},
onError: (DioException e, ErrorInterceptorHandler handler) {
if (!e.requestOptions.extra.containsKey(EHRequest.domainFrontingExtraKey)) {
handler.next(e);
return;
}

if (e.type == DioExceptionType.connectionTimeout || e.type == DioExceptionType.badResponse || e.type == DioExceptionType.connectionError) {
String host = e.requestOptions.extra[EHRequest.domainFrontingExtraKey]['host'];
String ip = e.requestOptions.extra[EHRequest.domainFrontingExtraKey]['ip'];
_ehIpProvider.addUnavailableIp(host, ip);
log.info('Refresh igneous, add unavailable host-ip: $host-$ip');
}

handler.next(e);
},
));

_dio!.interceptors.add(EHTimeoutTranslator());
}
}
3 changes: 0 additions & 3 deletions lib/src/pages/setting/account/setting_account_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ class SettingAccountPage extends StatelessWidget {
title: Text('login'.tr),
trailing: IconButton(onPressed: () => toRoute(Routes.login), icon: const Icon(Icons.keyboard_arrow_right)),
onTap: () => toRoute(Routes.login),
// onTap: () async {
// await ehRequest.requestLogout();
// },
);
}

Expand Down

0 comments on commit 5bbeef8

Please sign in to comment.