ConanServerManager/lib/steamcmd.dart
2023-11-01 03:28:33 -07:00

291 lines
11 KiB
Dart

import 'dart:io';
import 'package:archive/archive_io.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hive_flutter/adapters.dart';
import 'package:servermanager/credentials.dart';
import 'package:servermanager/dialogbox.dart';
import 'package:servermanager/settings.dart';
class SteamCMD extends StatefulWidget {
Settings settings;
SteamCMD({super.key, required this.settings});
@override
SteamCMDState createState() => SteamCMDState(settings: settings);
}
class SteamCMDState extends State<SteamCMD> {
final String windows =
"https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip";
final String linux =
"https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz";
final String Base2FAPath =
"https://github.com/zontreck/steamcmd-2fa/releases/download/0.2.0/steamcmd-2fa";
Settings settings = Settings();
SteamCMDState({required this.settings});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Conan Exiles Server Manager - Steam Command"),
backgroundColor: Color.fromARGB(255, 100, 0, 0),
),
body: SingleChildScrollView(
child: Column(
children: [
ListTile(
title: Text("Download/Initialize SteamCmd"),
leading: Icon(CupertinoIcons.cloud_download),
subtitle: Text(
"Creates the steamcmd folder, and downloads the steamcmd bootstrap. Then performs the initial update."),
onTap: () {
showDialog(
context: context,
builder: (X) => InputBox(
"",
promptText:
"This action will delete any existing copy of SteamCMD and download a fresh copy. \nAre you sure?",
changed: (X) {},
onSubmit: () async {
// Yes, Proceed
var x = Directory(settings.steamcmd_path);
try {
await x.delete(recursive: true);
} catch (e) {}
await x.create(recursive: true);
Directory.current = Directory(settings.steamcmd_path);
final dio = Dio();
Process proc;
if (Platform.isWindows) {
// Download zip file
final path = settings.steamcmd_path +
Platform.pathSeparator +
"windows.zip";
final reply = await dio.download(windows, path);
final bytes = File(path).readAsBytesSync();
final arc = ZipDecoder().decodeBytes(bytes);
for (final file in arc) {
final name = file.name;
if (file.isFile) {
final data = file.content as List<int>;
File(name)
..createSync(recursive: true)
..writeAsBytesSync(data);
} else {
Directory(name).create(recursive: true);
}
}
Process.runSync("echo", ["X", ">", "cxinit"]);
proc =
await Process.start("steamcmd.exe", ["+quit"]);
} else {
// Download tgz file
final path = settings.steamcmd_path +
Platform.pathSeparator +
"linux.tgz";
final reply = await dio.download(linux, path);
final bytes = File(path).readAsBytesSync();
final arc = GZipDecoder().decodeBytes(bytes);
final arc2 = TarDecoder().decodeBytes(arc);
for (final file in arc2) {
final name = file.name;
if (file.isFile) {
final data = file.content as List<int>;
File(name)
..createSync(recursive: true)
..writeAsBytesSync(data);
} else {
Directory(name).create(recursive: true);
}
}
Process.runSync("chmod", ["+x", "steamcmd.sh"]);
Process.runSync(
"chmod", ["+x", "linux32/steamcmd"]);
Process.runSync("touch", ["cxinit"]);
proc =
await Process.start("./steamcmd.sh", ["+quit"]);
}
Directory.current = Directory(settings.game_path);
},
onCancel: () {},
isDefault: false,
hasInputField: false,
));
},
),
ListTile(
title: Text("Download SteamCmd-2fa"),
leading: Icon(CupertinoIcons.lock_shield_fill),
subtitle: Text(
"Downloads a modified version of steamcmd-2fa from https://github.com/zontreck/steamcmd-2fa"),
onTap: () async {
final dio = Dio();
await dio.download(
Base2FAPath + (Platform.isWindows ? ".exe" : ""),
settings.steamcmd_path +
Platform.pathSeparator +
(Platform.isWindows
? "steamcmd-2fa.exe"
: "steamcmd-2fa"));
if (!Platform.isWindows)
var proc = await Process.start("chmod", [
"+x",
settings.steamcmd_path +
Platform.pathSeparator +
"steamcmd-2fa"
]);
}),
ListTile(
title: Text("Credentials"),
leading: Icon(Icons.key_sharp),
subtitle: Text("Steam Credentials"),
onTap: () async {
var creds = await Navigator.pushNamed(context, "/steamcmd/creds",
arguments: settings.steam_creds);
if (creds != null) {
Credentials cred = creds as Credentials;
setState(() {
settings.steam_creds = cred;
settings.Write();
});
}
},
),
],
)),
);
}
}
// Returns a Credentials Object
class CredentialsPrompt extends StatelessWidget {
TextEditingController username = TextEditingController();
TextEditingController password = TextEditingController();
TextEditingController secret = TextEditingController();
bool initialInitDone = false;
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as Credentials?;
if (args != null) {
if (!initialInitDone) {
username.text = args.username;
password.text = args.password;
secret.text = args.secret;
initialInitDone = true;
}
}
return Scaffold(
appBar: AppBar(
title:
Text("Conan Exiles Server Manager - Steam Command - Credentials"),
backgroundColor: Color.fromARGB(255, 100, 0, 0),
),
body: WillPopScope(
child: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
children: [
Row(
children: [
SizedBox(
width: 150,
child: Row(
children: [
Icon(Icons.person),
Text("Username:"),
],
)),
Expanded(
child: TextField(
controller: username,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4))),
),
)
],
),
SizedBox(
height: 16,
),
Row(
children: [
SizedBox(
width: 150,
child: Row(
children: [
Icon(Icons.key),
Text("Password:"),
],
)),
Expanded(
child: TextField(
controller: password,
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4))),
),
)
],
),
SizedBox(
height: 16,
),
Row(
children: [
SizedBox(
width: 150,
child: Row(
children: [
Icon(Icons.dangerous),
Text("Secret:"),
],
)),
Expanded(
child: TextField(
controller: secret,
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4)),
hintText:
"2FA Shared Secret Code (Do Not Share With Others!)"),
))
],
)
],
)),
onWillPop: () async {
Navigator.pop(
context,
Credentials(
username: username.text,
password: password.text,
secret: secret.text));
return true;
},
));
}
}