mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Function for interactive login in the browser [BETA]
This commit is contained in:
parent
a35eece00c
commit
86b3f20c34
2
.gitignore
vendored
2
.gitignore
vendored
@ -78,3 +78,5 @@ android/key.properties
|
||||
**/pb_data
|
||||
|
||||
tm.json
|
||||
.local-chrome
|
||||
.vs
|
@ -325,5 +325,6 @@
|
||||
"connect_client_alert": "You're being controlled by {client}",
|
||||
"this_device": "This Device",
|
||||
"remote": "Remote",
|
||||
"stats": "Stats"
|
||||
"stats": "Stats",
|
||||
"continue_in_browser": "Continue in browser"
|
||||
}
|
@ -325,5 +325,6 @@
|
||||
"add_library_location": "Añadir a la biblioteca",
|
||||
"remove_library_location": "Eliminar de la biblioteca",
|
||||
"local_tab": "Local",
|
||||
"stats": "Estadísticas"
|
||||
"stats": "Estadísticas",
|
||||
"continue_in_browser": "Continuar en el navegador"
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:puppeteer/protocol/network.dart';
|
||||
import 'package:puppeteer/puppeteer.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
|
||||
import 'package:spotube/provider/authentication_provider.dart';
|
||||
@ -16,8 +18,12 @@ class TokenLoginForm extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, ref) {
|
||||
final authenticationNotifier = ref.watch(authenticationProvider.notifier);
|
||||
final directCodeController = useTextEditingController();
|
||||
final platform = Theme.of(context).platform;
|
||||
final isDesktop =
|
||||
platform == TargetPlatform.linux || platform == TargetPlatform.windows;
|
||||
|
||||
final isLoading = useState(false);
|
||||
final showManualConf = useState(false);
|
||||
|
||||
return ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
@ -25,46 +31,115 @@ class TokenLoginForm extends HookConsumerWidget {
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
controller: directCodeController,
|
||||
decoration: InputDecoration(
|
||||
hintText: context.l10n.spotify_cookie("\"sp_dc\""),
|
||||
labelText: context.l10n.cookie_name_cookie("sp_dc"),
|
||||
),
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
FilledButton(
|
||||
onPressed: isLoading.value
|
||||
? null
|
||||
: () async {
|
||||
try {
|
||||
isLoading.value = true;
|
||||
if (directCodeController.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(context.l10n.fill_in_all_fields),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
final cookieHeader =
|
||||
"sp_dc=${directCodeController.text.trim()}";
|
||||
Visibility(
|
||||
visible: showManualConf.value,
|
||||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
controller: directCodeController,
|
||||
decoration: InputDecoration(
|
||||
hintText: context.l10n.spotify_cookie("\"sp_dc\""),
|
||||
labelText: context.l10n.cookie_name_cookie("sp_dc"),
|
||||
),
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
FilledButton(
|
||||
onPressed: isLoading.value
|
||||
? null
|
||||
: () async {
|
||||
try {
|
||||
isLoading.value = true;
|
||||
if (directCodeController.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content:
|
||||
Text(context.l10n.fill_in_all_fields),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
final cookieHeader =
|
||||
"sp_dc=${directCodeController.text.trim()}";
|
||||
|
||||
authenticationNotifier.setCredentials(
|
||||
await AuthenticationCredentials.fromCookie(
|
||||
cookieHeader),
|
||||
);
|
||||
if (context.mounted) {
|
||||
onDone?.call();
|
||||
}
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
},
|
||||
child: Text(context.l10n.submit),
|
||||
)
|
||||
authenticationNotifier.setCredentials(
|
||||
await AuthenticationCredentials.fromCookie(
|
||||
cookieHeader),
|
||||
);
|
||||
if (context.mounted) {
|
||||
onDone?.call();
|
||||
}
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
},
|
||||
child: Text(context.l10n.submit),
|
||||
)
|
||||
],
|
||||
)),
|
||||
Visibility(
|
||||
visible: isDesktop && !showManualConf.value,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 48.0,
|
||||
child: ElevatedButton(
|
||||
onPressed: isLoading.value
|
||||
? null
|
||||
: () async {
|
||||
final browser =
|
||||
await puppeteer.launch(headless: false);
|
||||
try {
|
||||
List<Cookie> cookies = [];
|
||||
final page = await browser.newPage();
|
||||
|
||||
await page.goto(
|
||||
'https://accounts.spotify.com/en/login',
|
||||
wait: Until.domContentLoaded);
|
||||
|
||||
while (browser.isConnected) {
|
||||
cookies = await page.cookies();
|
||||
for (final cookie in cookies) {
|
||||
if (cookie.name == "sp_dc") {
|
||||
await browser.close();
|
||||
final cookieHeader =
|
||||
"sp_dc=${cookie.value.trim()}";
|
||||
|
||||
authenticationNotifier.setCredentials(
|
||||
await AuthenticationCredentials
|
||||
.fromCookie(cookieHeader),
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
onDone?.call();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
showManualConf.value = true;
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
await browser.close();
|
||||
}
|
||||
},
|
||||
style: ButtonStyle(
|
||||
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(15.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Text(context.l10n.continue_in_browser),
|
||||
),
|
||||
),
|
||||
],
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
|
14
pubspec.lock
14
pubspec.lock
@ -1258,18 +1258,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.1"
|
||||
version: "4.9.0"
|
||||
json_serializable:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: json_serializable
|
||||
sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969
|
||||
sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.7.1"
|
||||
version: "6.8.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1711,13 +1711,13 @@ packages:
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
puppeteer:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: puppeteer
|
||||
sha256: "6833edca01b1e9dcdd9a6e41bad84b706dfba4366d095c4edff64b00c02ac472"
|
||||
sha256: c45c51b4ad8d70acdffeb1cfb9d16b60a7eaab7bfef314dd5b02c3607269b556
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.8.0"
|
||||
version: "3.11.0"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -121,6 +121,7 @@ dependencies:
|
||||
tray_manager: ^0.2.2
|
||||
http: ^1.2.1
|
||||
riverpod: ^2.5.1
|
||||
puppeteer: ^3.11.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.11
|
||||
|
@ -1 +1,101 @@
|
||||
{}
|
||||
{
|
||||
"ar": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"bn": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"ca": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"cs": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"de": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"eu": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"fa": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"fi": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"hi": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"id": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"it": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"ja": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"ka": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"ko": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"ne": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"nl": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"pl": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"th": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"tr": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"uk": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"vi": [
|
||||
"continue_in_browser"
|
||||
],
|
||||
|
||||
"zh": [
|
||||
"continue_in_browser"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user