Add discord webhooks
This commit is contained in:
parent
cbf0279c42
commit
a17e0452a0
6 changed files with 208 additions and 2 deletions
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:libac_dart/packets/packets.dart';
|
import 'package:libac_dart/packets/packets.dart';
|
||||||
import 'package:servermanager/packets/ClientPackets.dart';
|
import 'package:servermanager/packets/ClientPackets.dart';
|
||||||
import 'package:servermanager/pages/Constants.dart';
|
import 'package:servermanager/pages/Constants.dart';
|
||||||
|
import 'package:servermanager/pages/DiscordConfigPage.dart';
|
||||||
import 'package:servermanager/pages/GameServerPage.dart';
|
import 'package:servermanager/pages/GameServerPage.dart';
|
||||||
import 'package:servermanager/pages/ModManager.dart';
|
import 'package:servermanager/pages/ModManager.dart';
|
||||||
import 'package:servermanager/pages/autorestart.dart';
|
import 'package:servermanager/pages/autorestart.dart';
|
||||||
|
@ -33,6 +34,7 @@ class MyApp extends StatelessWidget {
|
||||||
"/server/ports": (context) => ServerSettingsPage(),
|
"/server/ports": (context) => ServerSettingsPage(),
|
||||||
"/server/mods": (context) => ModManager(settings: appSettings),
|
"/server/mods": (context) => ModManager(settings: appSettings),
|
||||||
"/server/mods/edit": (context) => ModPage(),
|
"/server/mods/edit": (context) => ModPage(),
|
||||||
|
"/server/discord": (context) => DiscordConfigPage()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
91
lib/pages/DiscordConfigPage.dart
Normal file
91
lib/pages/DiscordConfigPage.dart
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:servermanager/pages/Constants.dart';
|
||||||
|
import 'package:servermanager/structs/discordHookHelper.dart';
|
||||||
|
import 'package:servermanager/structs/settings.dart';
|
||||||
|
|
||||||
|
class DiscordConfigPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => DiscordConfigurationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiscordConfigurationState extends State<DiscordConfigPage> {
|
||||||
|
TextEditingController ServerNameController = TextEditingController();
|
||||||
|
TextEditingController URLController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
Settings settings = Settings();
|
||||||
|
final discord = settings.inst!.discord;
|
||||||
|
|
||||||
|
if (discord != null) {
|
||||||
|
ServerNameController.text = discord.serverName;
|
||||||
|
URLController.text = discord.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("Conan Exiles Server Manager - Discord Hook Settings"),
|
||||||
|
backgroundColor: Constants.TITLEBAR_COLOR,
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text(
|
||||||
|
"Discord Webhook has been successfully reset and will no longer be used")));
|
||||||
|
|
||||||
|
Settings settings = Settings();
|
||||||
|
settings.inst!.discord = null;
|
||||||
|
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.clear_all))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
floatingActionButton: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
DiscordHookProps(
|
||||||
|
url: URLController.text,
|
||||||
|
serverName: ServerNameController.text));
|
||||||
|
},
|
||||||
|
child: Text("Submit"),
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 256,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text("Server Name"),
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: ServerNameController,
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 256,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text("URL"),
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: URLController,
|
||||||
|
))
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:servermanager/structs/discordHookHelper.dart';
|
||||||
|
import 'package:servermanager/structs/settings.dart';
|
||||||
|
|
||||||
import '../structs/serversettings.dart';
|
import '../structs/serversettings.dart';
|
||||||
|
|
||||||
|
@ -106,6 +108,28 @@ class ServerSettingsState extends State<ServerSettingsPage> {
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: Text("Discord WebHook"),
|
||||||
|
onTap: () async {
|
||||||
|
var response =
|
||||||
|
await Navigator.pushNamed(context, "/server/discord");
|
||||||
|
|
||||||
|
if (response == null)
|
||||||
|
return;
|
||||||
|
else {
|
||||||
|
DiscordHookProps editResult =
|
||||||
|
response as DiscordHookProps;
|
||||||
|
Settings settings = Settings();
|
||||||
|
settings.inst!.discord = editResult;
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:libac_dart/utils/IOTools.dart';
|
||||||
import 'package:libac_dart/utils/TimeUtils.dart';
|
import 'package:libac_dart/utils/TimeUtils.dart';
|
||||||
import 'package:servermanager/game.dart';
|
import 'package:servermanager/game.dart';
|
||||||
import 'package:servermanager/structs/SessionData.dart';
|
import 'package:servermanager/structs/SessionData.dart';
|
||||||
|
import 'package:servermanager/structs/discordHookHelper.dart';
|
||||||
import 'package:servermanager/structs/mod.dart';
|
import 'package:servermanager/structs/mod.dart';
|
||||||
import 'package:servermanager/structs/settings.dart';
|
import 'package:servermanager/structs/settings.dart';
|
||||||
import 'package:servermanager/wine.dart';
|
import 'package:servermanager/wine.dart';
|
||||||
|
@ -130,6 +131,12 @@ class StateMachine {
|
||||||
PacketServer.socket!.close();
|
PacketServer.socket!.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DiscordHookHelper.sendWebHook(
|
||||||
|
settings.inst!.discord,
|
||||||
|
DiscordHookProps.OFFLINE_ALERT,
|
||||||
|
"Server is now offline",
|
||||||
|
"The server is shutting down");
|
||||||
|
|
||||||
changeState(States.Inactive);
|
changeState(States.Inactive);
|
||||||
} else if (currentState == States.Starting) {
|
} else if (currentState == States.Starting) {
|
||||||
// Server startup in progress
|
// Server startup in progress
|
||||||
|
@ -213,6 +220,12 @@ class StateMachine {
|
||||||
SessionData.timer = settings.inst!.timer.time.copy();
|
SessionData.timer = settings.inst!.timer.time.copy();
|
||||||
changeState(States.PreStart);
|
changeState(States.PreStart);
|
||||||
|
|
||||||
|
DiscordHookHelper.sendWebHook(
|
||||||
|
settings.inst!.discord,
|
||||||
|
DiscordHookProps.ONLINE_ALERT,
|
||||||
|
"Server is now starting up",
|
||||||
|
"The server is starting up now, it should appear on the server list in a few minutes");
|
||||||
|
|
||||||
resetKillswitch();
|
resetKillswitch();
|
||||||
SessionData.enableRestartTimer = settings.inst!.timer.enabled;
|
SessionData.enableRestartTimer = settings.inst!.timer.enabled;
|
||||||
|
|
||||||
|
@ -284,14 +297,24 @@ class StateMachine {
|
||||||
if (send && SessionData.enableRestartTimer) {
|
if (send && SessionData.enableRestartTimer) {
|
||||||
// Send the alert message
|
// Send the alert message
|
||||||
SessionData.CURRENT_INTERVAL = current;
|
SessionData.CURRENT_INTERVAL = current;
|
||||||
|
int alertColor = 0;
|
||||||
if (current.type == WarnType.Intrusive) {
|
if (current.type == WarnType.Intrusive) {
|
||||||
print("Sending alert '${current.warning}'");
|
print("Sending alert '${current.warning}'");
|
||||||
settings.sendRconCommand("broadcast ${current.warning}");
|
settings.sendRconCommand("broadcast ${current.warning}");
|
||||||
|
|
||||||
|
// Set discord alert color
|
||||||
|
alertColor = DiscordHookProps.ALERT_INTRUSIVE;
|
||||||
} else if (current.type == WarnType.NonIntrusive) {
|
} else if (current.type == WarnType.NonIntrusive) {
|
||||||
print("Sending chat message '${current.warning}'");
|
print("Sending chat message '${current.warning}'");
|
||||||
settings.sendRconCommand(
|
//settings.sendRconCommand(
|
||||||
"ast chat \"global\" \"${current.warning}\"");
|
// "ast chat \"global\" \"${current.warning}\"");
|
||||||
|
|
||||||
|
// Set discord alert color
|
||||||
|
alertColor = DiscordHookProps.ALERT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiscordHookHelper.sendWebHook(settings.inst!.discord, alertColor,
|
||||||
|
"Server Restart Alert", "${current.warning}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Shutdown Pending
|
// Check Shutdown Pending
|
||||||
|
|
57
lib/structs/discordHookHelper.dart
Normal file
57
lib/structs/discordHookHelper.dart
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:libac_dart/nbt/impl/CompoundTag.dart';
|
||||||
|
import 'package:libac_dart/nbt/impl/StringTag.dart';
|
||||||
|
|
||||||
|
class DiscordHookHelper {
|
||||||
|
static Future<void> sendWebHook(DiscordHookProps? props, int colorCode,
|
||||||
|
String title, String content) async {
|
||||||
|
if (props == null) return; // The webhook setting is not yet set up
|
||||||
|
var js = json.encode({
|
||||||
|
"content": "",
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
"title": title,
|
||||||
|
"description": content,
|
||||||
|
"color": colorCode,
|
||||||
|
"author": {"name": props.serverName}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attachments": []
|
||||||
|
});
|
||||||
|
|
||||||
|
Dio dio = Dio();
|
||||||
|
dio.post(props.url, data: js);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiscordHookProps {
|
||||||
|
String url;
|
||||||
|
String serverName;
|
||||||
|
|
||||||
|
DiscordHookProps({required this.url, required this.serverName});
|
||||||
|
|
||||||
|
CompoundTag serialize() {
|
||||||
|
CompoundTag ct = CompoundTag();
|
||||||
|
ct.put(TAG_URL, StringTag.valueOf(url));
|
||||||
|
ct.put(TAG_SERVER_NAME, StringTag.valueOf(serverName));
|
||||||
|
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DiscordHookProps deserialize(CompoundTag ct) {
|
||||||
|
return DiscordHookProps(
|
||||||
|
url: ct.get(TAG_URL)!.asString(),
|
||||||
|
serverName: ct.get(TAG_SERVER_NAME)!.asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
static const String TAG_URL = "url";
|
||||||
|
static const String TAG_SERVER_NAME = "serverName";
|
||||||
|
static const String TAG_NAME = "discord";
|
||||||
|
|
||||||
|
static const int ONLINE_ALERT = 1869056;
|
||||||
|
static const int OFFLINE_ALERT = 8716288;
|
||||||
|
static const int ALERT = 21893; // non-intrusive
|
||||||
|
static const int ALERT_INTRUSIVE = 6291589;
|
||||||
|
}
|
|
@ -5,11 +5,13 @@ import 'package:libac_dart/nbt/impl/ListTag.dart';
|
||||||
import 'package:libac_dart/utils/TimeUtils.dart';
|
import 'package:libac_dart/utils/TimeUtils.dart';
|
||||||
import 'package:servermanager/structs/autorestarts.dart';
|
import 'package:servermanager/structs/autorestarts.dart';
|
||||||
import 'package:servermanager/structs/credentials.dart';
|
import 'package:servermanager/structs/credentials.dart';
|
||||||
|
import 'package:servermanager/structs/discordHookHelper.dart';
|
||||||
import 'package:servermanager/structs/mod.dart';
|
import 'package:servermanager/structs/mod.dart';
|
||||||
import 'package:servermanager/structs/serversettings.dart';
|
import 'package:servermanager/structs/serversettings.dart';
|
||||||
|
|
||||||
class SettingsEntry {
|
class SettingsEntry {
|
||||||
List<Mod> mods = [];
|
List<Mod> mods = [];
|
||||||
|
DiscordHookProps? discord;
|
||||||
Credentials? steam_creds;
|
Credentials? steam_creds;
|
||||||
bool pterodactylMode = true; // Default is to be compatible
|
bool pterodactylMode = true; // Default is to be compatible
|
||||||
AutomaticRestartInfo timer =
|
AutomaticRestartInfo timer =
|
||||||
|
@ -33,6 +35,10 @@ class SettingsEntry {
|
||||||
st.pterodactylMode = NbtUtils.readBoolean(tag, "pterodactyl");
|
st.pterodactylMode = NbtUtils.readBoolean(tag, "pterodactyl");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tag.containsKey(DiscordHookProps.TAG_NAME))
|
||||||
|
st.discord = DiscordHookProps.deserialize(
|
||||||
|
tag.get(DiscordHookProps.TAG_NAME)!.asCompoundTag());
|
||||||
|
|
||||||
st.mods.clear();
|
st.mods.clear();
|
||||||
ListTag lMods = tag.get("mods") as ListTag;
|
ListTag lMods = tag.get("mods") as ListTag;
|
||||||
for (Tag tag in lMods.value) {
|
for (Tag tag in lMods.value) {
|
||||||
|
@ -55,6 +61,9 @@ class SettingsEntry {
|
||||||
}
|
}
|
||||||
tag.put("mods", lMods);
|
tag.put("mods", lMods);
|
||||||
|
|
||||||
|
if (discord != null)
|
||||||
|
tag.put(DiscordHookProps.TAG_NAME, discord!.serialize());
|
||||||
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue