diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs
index 4fd20273..ed79492e 100644
--- a/TShockAPI/Rest/RestManager.cs
+++ b/TShockAPI/Rest/RestManager.cs
@@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Linq;
using HttpServer;
@@ -36,395 +37,393 @@ namespace TShockAPI
public void RegisterRestfulCommands()
{
- Rest.Register(new RestCommand("/status", Status) {RequiresToken = false});
- Rest.Register(new RestCommand("/tokentest", TokenTest) {RequiresToken = true});
+ // Server Commands
+ Rest.Register(new RestCommand("/v2/server/broadcast", ServerBroadcast));
+ Rest.Register(new RestCommand("/v2/server/off", ServerOff));
+ Rest.Register(new RestCommand("/v2/server/rawcmd", ServerCommand));
+ Rest.Register(new RestCommand("/v2/server/status", ServerStatusV2) { RequiresToken = false });
+ Rest.Register(new RestCommand("/tokentest", ServerTokenTest));
+ Rest.Register(new RestCommand("/status", ServerStatus) { RequiresToken = false });
- Rest.Register(new RestCommand("/v2/users/activelist", UserListV2) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/users/read", UserInfoV2) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/users/destroy", UserDestroyV2) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/users/update", UserUpdateV2) { RequiresToken = true });
+ // User Commands
+ Rest.Register(new RestCommand("/v2/users/activelist", UserActiveListV2));
+ Rest.Register(new RestCommand("/v2/users/create", UserCreateV2));
+ Rest.Register(new RestCommand("/v2/users/list", UserListV2));
+ Rest.Register(new RestCommand("/v2/users/read", UserInfoV2));
+ Rest.Register(new RestCommand("/v2/users/destroy", UserDestroyV2));
+ Rest.Register(new RestCommand("/v2/users/update", UserUpdateV2));
- Rest.Register(new RestCommand("/bans/create", BanCreate) {RequiresToken = true});
- Rest.Register(new RestCommand("/v2/bans/read", BanInfoV2) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/bans/destroy", BanDestroyV2) { RequiresToken = true });
+ // Ban Commands
+ Rest.Register(new RestCommand("/bans/create", BanCreate));
+ Rest.Register(new RestCommand("/v2/bans/list", BanListV2));
+ Rest.Register(new RestCommand("/v2/bans/read", BanInfoV2));
+ Rest.Register(new RestCommand("/v2/bans/destroy", BanDestroyV2));
- Rest.Register(new RestCommand("/v2/lists/bans", BanListIPs) { RequiresToken = true });
- Rest.Register(new RestCommand("/lists/players", PlayerList) {RequiresToken = true});
- Rest.Register(new RestCommand("/v2/lists/players", PlayerListV2) { RequiresToken = true });
+ // World Commands
+ Rest.Register(new RestCommand("/world/read", WorldRead));
+ Rest.Register(new RestCommand("/world/meteor", WorldMeteor));
+ Rest.Register(new RestCommand("/world/bloodmoon/{bool}", WorldBloodmoon));
+ Rest.Register(new RestCommand("/v2/world/save", WorldSave));
+ Rest.Register(new RestCommand("/v2/world/autosave/state/{bool}", WorldChangeSaveSettings));
+ Rest.Register(new RestCommand("/v2/world/butcher", WorldButcher));
- Rest.Register(new RestCommand("/world/read", WorldRead) {RequiresToken = true});
- Rest.Register(new RestCommand("/world/meteor", WorldMeteor) {RequiresToken = true});
- Rest.Register(new RestCommand("/world/bloodmoon/{bool}", WorldBloodmoon) {RequiresToken = true});
- Rest.Register(new RestCommand("/v2/world/save", WorldSave) { RequiresToken = true});
- Rest.Register(new RestCommand("/v2/world/autosave/state/{bool}", ChangeWorldSaveSettings) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/world/butcher", Butcher) {RequiresToken = true});
+ // Player Commands
+ Rest.Register(new RestCommand("/lists/players", PlayerList));
+ Rest.Register(new RestCommand("/v2/players/list", PlayerListV2));
+ Rest.Register(new RestCommand("/v2/players/read", PlayerReadV2));
+ Rest.Register(new RestCommand("/v2/players/kick", PlayerKickV2));
+ Rest.Register(new RestCommand("/v2/players/ban", PlayerBanV2));
+ Rest.Register(new RestCommand("/v2/players/kill", PlayerKill));
+ Rest.Register(new RestCommand("/v2/players/mute", PlayerMute));
+ Rest.Register(new RestCommand("/v2/players/unmute", PlayerUnMute));
- Rest.Register(new RestCommand("/v2/players/read", PlayerReadV2) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/players/kick", PlayerKickV2) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/players/ban", PlayerBanV2) { RequiresToken = true });
- Rest.Register(new RestCommand("/v2/players/kill", PlayerKill) {RequiresToken = true});
- Rest.Register(new RestCommand("/v2/players/mute", PlayerMute) {RequiresToken = true});
- Rest.Register(new RestCommand("/v2/players/unmute", PlayerUnMute) {RequiresToken = true});
-
- Rest.Register(new RestCommand("/v2/server/broadcast", Broadcast) { RequiresToken = true});
- Rest.Register(new RestCommand("/v2/server/off", Off) {RequiresToken = true});
- Rest.Register(new RestCommand("/v2/server/rawcmd", ServerCommand) {RequiresToken = true});
+ // Group Commands
+ Rest.Register(new RestCommand("/v2/groups/list", GroupList));
+ Rest.Register(new RestCommand("/v2/groups/read", GroupInfo));
+ Rest.Register(new RestCommand("/v2/groups/destroy", GroupDestroy));
+ Rest.Register(new RestCommand("/v2/groups/create", GroupCreate));
+ Rest.Register(new RestCommand("/v2/groups/update", GroupUpdate));
}
#region RestServerMethods
private object ServerCommand(RestVerbs verbs, IParameterCollection parameters)
{
- if (parameters["cmd"] != null && parameters["cmd"].Trim() != "")
- {
- TSRestPlayer tr = new TSRestPlayer();
- RestObject ro = new RestObject("200");
- Commands.HandleCommand(tr, parameters["cmd"]);
- foreach (string s in tr.GetCommandOutput())
- {
- ro.Add("response", s);
- }
- return ro;
- }
- RestObject fail = new RestObject("400");
- fail["response"] = "Missing or blank cmd parameter.";
- return fail;
+ if (string.IsNullOrWhiteSpace(parameters["cmd"]))
+ return RestMissingParam("cmd");
+
+ TSRestPlayer tr = new TSRestPlayer();
+ Commands.HandleCommand(tr, parameters["cmd"]);
+ return RestResponse(string.Join("\n", tr.GetCommandOutput()));
}
- private object Off(RestVerbs verbs, IParameterCollection parameters)
+ private object ServerOff(RestVerbs verbs, IParameterCollection parameters)
{
- bool confirm;
- bool.TryParse(parameters["confirm"], out confirm);
- bool nosave;
- bool.TryParse(parameters["nosave"], out nosave);
+ if (!GetBool(parameters["confirm"], false))
+ return RestInvalidParam("confirm");
- if (confirm == true)
+ if (!GetBool(parameters["nosave"], false))
+ WorldGen.saveWorld();
+ Netplay.disconnect = true;
+
+ // Inform players the server is shutting down
+ var msg = string.IsNullOrWhiteSpace(parameters["message"]) ? "Server is shutting down" : parameters["message"];
+ foreach (TSPlayer player in TShock.Players.Where(p => null != p))
{
- if (!nosave)
- WorldGen.saveWorld();
- Netplay.disconnect = true;
- RestObject reply = new RestObject("200");
- reply["response"] = "The server is shutting down.";
- return reply;
+ TShock.Utils.ForceKick(player, msg);
}
- RestObject fail = new RestObject("400");
- fail["response"] = "Invalid/missing confirm switch, and/or missing nosave switch.";
- return fail;
+ return RestResponse("The server is shutting down");
}
- private object Broadcast(RestVerbs verbs, IParameterCollection parameters)
+ private object ServerBroadcast(RestVerbs verbs, IParameterCollection parameters)
{
- if (parameters["msg"] != null && parameters["msg"].Trim() != "")
- {
- TShock.Utils.Broadcast(parameters["msg"]);
- RestObject reply = new RestObject("200");
- reply["response"] = "The message was broadcasted successfully.";
- return reply;
- }
- RestObject fail = new RestObject("400");
- fail["response"] = "Broadcast failed.";
- return fail;
+ var msg = parameters["msg"];
+ if (string.IsNullOrWhiteSpace(msg))
+ return RestMissingParam("msg");
+ TShock.Utils.Broadcast(msg);
+ return RestResponse("The message was broadcasted successfully");
}
- #endregion
-
- #region RestMethods
-
- private object TokenTest(RestVerbs verbs, IParameterCollection parameters)
- {
- return new Dictionary
- {{"status", "200"}, {"response", "Token is valid and was passed through correctly."}};
- }
-
- private object Status(RestVerbs verbs, IParameterCollection parameters)
+ private object ServerStatus(RestVerbs verbs, IParameterCollection parameters)
{
if (TShock.Config.EnableTokenEndpointAuthentication)
- return new RestObject("403") {Error = "Server settings require a token for this API call."};
+ return RestError("Server settings require a token for this API call");
- var activeplayers = Main.player.Where(p => p != null && p.active).ToList();
- string currentPlayers = string.Join(", ", activeplayers.Select(p => p.name));
+ var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
+ return new RestObject()
+ {
+ {"name", TShock.Config.ServerNickname},
+ {"port", Convert.ToString(TShock.Config.ServerPort)},
+ {"playercount", Convert.ToString(activeplayers.Count())},
+ {"players", string.Join(", ", activeplayers.Select(p => p.name))},
+ };
+ }
- var ret = new RestObject("200");
- ret["name"] = TShock.Config.ServerNickname;
- ret["port"] = Convert.ToString(TShock.Config.ServerPort);
- ret["playercount"] = Convert.ToString(activeplayers.Count());
- ret["players"] = currentPlayers;
+ private object ServerStatusV2(RestVerbs verbs, IParameterCollection parameters)
+ {
+ if (TShock.Config.EnableTokenEndpointAuthentication)
+ return RestError("Server settings require a token for this API call");
- ret["maxplayers"] = TShock.Config.MaxSlots;
+ var ret = new RestObject()
+ {
+ {"name", TShock.Config.ServerNickname},
+ {"port", TShock.Config.ServerPort},
+ {"playercount", Main.player.Where(p => null != p && p.active).Count()},
+ {"maxplayers", TShock.Config.MaxSlots},
+ {"world", Main.worldName}
+ };
+
+ if (GetBool(parameters["players"], false))
+ {
+ var players = new ArrayList();
+ foreach (TSPlayer tsPlayer in TShock.Players.Where(p => null != p))
+ {
+ var p = PlayerFilter(tsPlayer, parameters);
+ if (null != p)
+ players.Add(p);
+ }
+ ret.Add("players", players);
+ }
+
+ if (GetBool(parameters["rules"], false))
+ {
+ var rules = new Dictionary();
+ rules.Add("AutoSave", TShock.Config.AutoSave);
+ rules.Add("DisableBuild", TShock.Config.DisableBuild);
+ rules.Add("DisableClownBombs", TShock.Config.DisableClownBombs);
+ rules.Add("DisableDungeonGuardian", TShock.Config.DisableDungeonGuardian);
+ rules.Add("DisableInvisPvP", TShock.Config.DisableInvisPvP);
+ rules.Add("DisableSnowBalls", TShock.Config.DisableSnowBalls);
+ rules.Add("DisableTombstones", TShock.Config.DisableTombstones);
+ rules.Add("EnableWhitelist", TShock.Config.EnableWhitelist);
+ rules.Add("HardcoreOnly", TShock.Config.HardcoreOnly);
+ rules.Add("PvPMode", TShock.Config.PvPMode);
+ rules.Add("SpawnProtection", TShock.Config.SpawnProtection);
+ rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
+
+ ret.Add("rules", rules);
+ }
return ret;
}
+ private object ServerTokenTest(RestVerbs verbs, IParameterCollection parameters)
+ {
+ return RestResponse("Token is valid and was passed through correctly");
+ }
+
#endregion
#region RestUserMethods
+ private object UserActiveListV2(RestVerbs verbs, IParameterCollection parameters)
+ {
+ return new RestObject() { { "activeusers", string.Join("\t", TShock.Players.Where(p => null != p && null != p.UserAccountName && p.Active).Select(p => p.UserAccountName)) } };
+ }
+
private object UserListV2(RestVerbs verbs, IParameterCollection parameters)
{
- string playerlist = "";
- foreach (var TSPlayer in TShock.Players)
+ return new RestObject() { { "users", TShock.Users.GetUsers().Select(p => new Dictionary(){
+ {"name", p.Name},
+ {"id", p.ID},
+ {"group", p.Group},
+ {"ip", p.Address},
+ }) } };
+ }
+
+ private object UserCreateV2(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var username = parameters["user"];
+ if (string.IsNullOrWhiteSpace(username))
+ return RestMissingParam("user");
+
+ var group = parameters["group"];
+ if (string.IsNullOrWhiteSpace(group))
+ return RestMissingParam("group");
+
+ var password = parameters["password"];
+ if (string.IsNullOrWhiteSpace(password))
+ return RestMissingParam("password");
+
+ // NOTE: ip can be blank
+ User user = new User(parameters["ip"], username, password, group);
+ try
{
- if (TSPlayer == null)
- {
- continue;
- }
- playerlist += playerlist == "" ? TSPlayer.UserAccountName : "\t" + TSPlayer.UserAccountName;
+ TShock.Users.AddUser(user);
}
- var returnBlock = new Dictionary();
- returnBlock.Add("status", "200");
- returnBlock.Add("activeusers", playerlist);
- return returnBlock;
+ catch (Exception e)
+ {
+ return RestError(e.Message);
+ }
+
+ return RestResponse("User was successfully created");
}
private object UserUpdateV2(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
+ var ret = UserFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
var password = parameters["password"];
var group = parameters["group"];
+ if (string.IsNullOrWhiteSpace(group) && string.IsNullOrWhiteSpace(password))
+ return RestMissingParam("group", "password");
- if (group == null && password == null)
+ User user = (User)ret;
+ var response = new RestObject();
+ if (!string.IsNullOrWhiteSpace(password))
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "No parameters were passed.");
- return returnBlock;
+ try
+ {
+ TShock.Users.SetUserPassword(user, password);
+ response.Add("password-response", "Password updated successfully");
+ }
+ catch (Exception e)
+ {
+ return RestError("Failed to update user password (" + e.Message + ")");
+ }
}
- var user = TShock.Users.GetUserByName(parameters["user"]);
- if (user == null)
+ if (!string.IsNullOrWhiteSpace(group))
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "The specefied user doesn't exist.");
- return returnBlock;
+ try
+ {
+ TShock.Users.SetUserGroup(user, group);
+ response.Add("group-response", "Group updated successfully");
+ }
+ catch (Exception e)
+ {
+ return RestError("Failed to update user group (" + e.Message + ")");
+ }
}
- if (password != null)
- {
- TShock.Users.SetUserPassword(user, password);
- returnBlock.Add("password-response", "Password updated successfully.");
- }
-
- if (group != null)
- {
- TShock.Users.SetUserGroup(user, group);
- returnBlock.Add("group-response", "Group updated successfully.");
- }
-
- returnBlock.Add("status", "200");
- return returnBlock;
+ return response;
}
private object UserDestroyV2(RestVerbs verbs, IParameterCollection parameters)
{
- var user = TShock.Users.GetUserByName(parameters["user"]);
- if (user == null)
- {
- return new Dictionary {{"status", "400"}, {"error", "The specified user account does not exist."}};
- }
- var returnBlock = new Dictionary();
+ var ret = UserFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
try
{
- TShock.Users.RemoveUser(user);
+ TShock.Users.RemoveUser((User)ret);
}
- catch (Exception)
+ catch (Exception e)
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "The specified user was unable to be removed.");
- return returnBlock;
+ return RestError(e.Message);
}
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "User deleted successfully.");
- return returnBlock;
+
+ return RestResponse("User deleted successfully");
}
private object UserInfoV2(RestVerbs verbs, IParameterCollection parameters)
{
- var user = TShock.Users.GetUserByName(parameters["user"]);
- if (user == null)
- {
- return new Dictionary {{"status", "400"}, {"error", "The specified user account does not exist."}};
- }
+ var ret = UserFind(parameters);
+ if (ret is RestObject)
+ return ret;
- var returnBlock = new Dictionary();
- returnBlock.Add("status", "200");
- returnBlock.Add("group", user.Group);
- returnBlock.Add("id", user.ID.ToString());
- return returnBlock;
+ User user = (User)ret;
+ return new RestObject() { { "group", user.Group }, { "id", user.ID.ToString() } };
}
#endregion
#region RestBanMethods
- private object BanListIPs(RestVerbs verbs, IParameterCollection parameters)
- {
- RestObject returnItem = new RestObject("200");
- returnItem.Add("bans", TShock.Bans.GetBans());
-
- return returnItem;
- }
-
private object BanCreate(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
var ip = parameters["ip"];
var name = parameters["name"];
- var reason = parameters["reason"];
- if (ip == null && name == null)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Required parameters were missing from this API endpoint.");
- return returnBlock;
- }
-
- if (ip == null)
- {
- ip = "";
- }
-
- if (name == null)
- {
- name = "";
- }
-
- if (reason == null)
- {
- reason = "";
- }
+ if (string.IsNullOrWhiteSpace(ip) && string.IsNullOrWhiteSpace(name))
+ return RestMissingParam("ip", "name");
try
{
- TShock.Bans.AddBan(ip, name, reason);
+ TShock.Bans.AddBan(ip, name, parameters["reason"], true);
}
- catch (Exception)
+ catch (Exception e)
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "The specified ban was unable to be created.");
- return returnBlock;
+ return RestError(e.Message);
}
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Ban created successfully.");
- return returnBlock;
+ return RestResponse("Ban created successfully");
}
private object BanDestroyV2(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
-
- var type = parameters["type"];
- if (type == null)
- {
- returnBlock.Add("Error", "Invalid Type");
- return returnBlock;
- }
-
- var ban = new Ban();
- if (type == "ip") ban = TShock.Bans.GetBanByIp(parameters["user"]);
- else if (type == "name") ban = TShock.Bans.GetBanByName(parameters["user"]);
- else
- {
- returnBlock.Add("Error", "Invalid Type");
- return returnBlock;
- }
-
- if (ban == null)
- {
- return new Dictionary {{"status", "400"}, {"error", "The specified ban does not exist."}};
- }
+ var ret = BanFind(parameters);
+ if (ret is RestObject)
+ return ret;
try
{
- TShock.Bans.RemoveBan(ban.IP);
+ Ban ban = (Ban)ret;
+ switch (parameters["type"])
+ {
+ case "ip":
+ if (!TShock.Bans.RemoveBan(ban.IP, false, false, true))
+ return RestResponse("Failed to delete ban (already deleted?)");
+ break;
+ case "name":
+ if (!TShock.Bans.RemoveBan(ban.Name, true, GetBool(parameters["caseinsensitive"], true)))
+ return RestResponse("Failed to delete ban (already deleted?)");
+ break;
+ default:
+ return RestError("Invalid Type: '" + parameters["type"] + "'");
+ }
+
}
- catch (Exception)
+ catch (Exception e)
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "The specified ban was unable to be removed.");
- return returnBlock;
+ return RestError(e.Message);
}
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Ban deleted successfully.");
- return returnBlock;
+
+ return RestResponse("Ban deleted successfully");
}
private object BanInfoV2(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
+ var ret = BanFind(parameters);
+ if (ret is RestObject)
+ return ret;
- var type = parameters["type"];
- if (type == null)
+ Ban ban = (Ban)ret;
+ return new RestObject() {
+ {"name", null == ban.Name ? "" : ban.Name},
+ {"ip", null == ban.IP ? "" : ban.IP},
+ {"reason", null == ban.Reason ? "" : ban.Reason},
+ };
+ }
+
+ private object BanListV2(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var banList = new ArrayList();
+ foreach (var ban in TShock.Bans.GetBans())
{
- returnBlock.Add("Error", "Invalid Type");
- return returnBlock;
+ banList.Add(
+ new Dictionary
+ {
+ {"name", null == ban.Name ? "" : ban.Name},
+ {"ip", null == ban.IP ? "" : ban.IP},
+ {"reason", null == ban.Reason ? "" : ban.Reason},
+ }
+ );
}
- var ban = new Ban();
- if (type == "ip") ban = TShock.Bans.GetBanByIp(parameters["user"]);
- else if (type == "name") ban = TShock.Bans.GetBanByName(parameters["user"]);
- else
- {
- returnBlock.Add("Error", "Invalid Type");
- return returnBlock;
- }
-
- if (ban == null)
- {
- return new Dictionary { { "status", "400" }, { "error", "The specified ban does not exist." } };
- }
-
- returnBlock.Add("status", "200");
- returnBlock.Add("name", ban.Name);
- returnBlock.Add("ip", ban.IP);
- returnBlock.Add("reason", ban.Reason);
- return returnBlock;
+ return new RestObject() { { "bans", banList } };
}
#endregion
#region RestWorldMethods
- private object ChangeWorldSaveSettings(RestVerbs verbs, IParameterCollection parameters)
+ private object WorldChangeSaveSettings(RestVerbs verbs, IParameterCollection parameters)
{
- bool state;
- bool.TryParse(verbs["state"], out state);
+ bool autoSave;
+ if (!bool.TryParse(verbs["bool"], out autoSave))
+ return RestInvalidParam("state");
+ TShock.Config.AutoSave = autoSave;
- if (state == true)
- {
- TShock.Config.AutoSave = true;
- }
- else
- {
- TShock.Config.AutoSave = false;
- }
-
- RestObject rj = new RestObject("200");
- rj["response"] = "Value changed";
- rj["state"] = state;
-
- return rj;
+ return RestResponse("AutoSave has been set to " + autoSave);
}
private object WorldSave(RestVerbs verbs, IParameterCollection parameters)
{
TShock.Utils.SaveWorld();
- RestObject rj = new RestObject("200");
- rj["response"] = "World saved.";
- return rj;
+ return RestResponse("World saved");
}
- private object Butcher(RestVerbs verbs, IParameterCollection parameters)
+ private object WorldButcher(RestVerbs verbs, IParameterCollection parameters)
{
bool killFriendly;
if (!bool.TryParse(parameters["killfriendly"], out killFriendly))
- {
- RestObject fail = new RestObject("400");
- fail["response"] = "The given value for killfriendly wasn't a boolean value.";
- return fail;
- }
+ return RestInvalidParam("killfriendly");
+
if (killFriendly)
- {
killFriendly = !killFriendly;
- }
int killcount = 0;
for (int i = 0; i < Main.npc.Length; i++)
@@ -436,54 +435,38 @@ namespace TShockAPI
}
}
- RestObject rj = new RestObject("200");
- rj["response"] = killcount + " NPCs have been killed.";
- return rj;
+ return RestResponse(killcount + " NPCs have been killed");
}
private object WorldRead(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- returnBlock.Add("status", "200");
- returnBlock.Add("name", Main.worldName);
- returnBlock.Add("size", Main.maxTilesX + "*" + Main.maxTilesY);
- returnBlock.Add("time", Main.time);
- returnBlock.Add("daytime", Main.dayTime);
- returnBlock.Add("bloodmoon", Main.bloodMoon);
- returnBlock.Add("invasionsize", Main.invasionSize);
- return returnBlock;
+ return new RestObject()
+ {
+ {"name", Main.worldName},
+ {"size", Main.maxTilesX + "*" + Main.maxTilesY},
+ {"time", Main.time},
+ {"daytime", Main.dayTime},
+ {"bloodmoon", Main.bloodMoon},
+ {"invasionsize", Main.invasionSize}
+ };
}
private object WorldMeteor(RestVerbs verbs, IParameterCollection parameters)
{
- if (WorldGen.genRand == null)
+ if (null == WorldGen.genRand)
WorldGen.genRand = new Random();
WorldGen.dropMeteor();
- var returnBlock = new Dictionary {{"status", "200"}, {"response", "Meteor has been spawned."}};
- return returnBlock;
+ return RestResponse("Meteor has been spawned");
}
private object WorldBloodmoon(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- var bloodmoonVerb = verbs["bool"];
bool bloodmoon;
- if (bloodmoonVerb == null)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "No parameter was passed.");
- return returnBlock;
- }
- if (!bool.TryParse(bloodmoonVerb, out bloodmoon))
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Unable to parse parameter.");
- return returnBlock;
- }
+ if (!bool.TryParse(verbs["bool"], out bloodmoon))
+ return RestInvalidParam("bloodmoon");
Main.bloodMoon = bloodmoon;
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Blood Moon has been set to " + bloodmoon);
- return returnBlock;
+
+ return RestResponse("Blood Moon has been set to " + bloodmoon);
}
#endregion
@@ -492,190 +475,342 @@ namespace TShockAPI
private object PlayerUnMute(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- var playerParam = parameters["player"];
- var found = TShock.Utils.FindPlayer(playerParam);
- var reason = parameters["reason"];
- if (found.Count == 0)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " was not found");
- }
- else if (found.Count > 1)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " matches " + playerParam.Count() + " players");
- }
- else if (found.Count == 1)
- {
- var player = found[0];
- player.mute = false;
- player.SendMessage("You have been remotely unmuted.");
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Player " + player.Name + " was muted.");
- }
- return returnBlock;
+ return PlayerSetMute(parameters, false);
}
private object PlayerMute(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- var playerParam = parameters["player"];
- var found = TShock.Utils.FindPlayer(playerParam);
- var reason = parameters["reason"];
- if (found.Count == 0)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " was not found");
- }
- else if (found.Count > 1)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " matches " + playerParam.Count() + " players");
- }
- else if (found.Count == 1)
- {
- var player = found[0];
- player.mute = true;
- player.SendMessage("You have been remotely muted.");
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Player " + player.Name + " was muted.");
- }
- return returnBlock;
- }
-
- private object PlayerListV2(RestVerbs verbs, IParameterCollection parameters)
- {
- RestObject returnBlock = new RestObject("200");
- returnBlock.Add("players", TShock.Players.Where(p => p != null && p.Active));
- return returnBlock;
+ return PlayerSetMute(parameters, true);
}
private object PlayerList(RestVerbs verbs, IParameterCollection parameters)
{
- var activeplayers = Main.player.Where(p => p != null && p.active).ToList();
- string currentPlayers = string.Join(", ", activeplayers.Select(p => p.name));
- var ret = new RestObject("200");
- ret["players"] = currentPlayers;
- ret.Add("deprecated", "This endpoint is deprecated and has been replaced with /v2/lists/players.");
- return ret;
+ var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
+ return new RestObject() { { "players", string.Join(", ", activeplayers.Select(p => p.name)) } };
+ }
+
+ private object PlayerListV2(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var playerList = new ArrayList();
+ foreach (TSPlayer tsPlayer in TShock.Players.Where(p => null != p))
+ {
+ var p = PlayerFilter(tsPlayer, parameters);
+ if (null != p)
+ playerList.Add(p);
+ }
+ return new RestObject() { { "players", playerList } };
}
private object PlayerReadV2(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- var playerParam = parameters["player"];
- var found = TShock.Utils.FindPlayer(playerParam);
- if (found.Count == 0)
+ var ret = PlayerFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ TSPlayer player = (TSPlayer)ret;
+ var activeItems = player.TPlayer.inventory.Where(p => p.active).ToList();
+ return new RestObject()
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " was not found");
- }
- else if (found.Count > 1)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " matches " + playerParam.Count() + " players");
- }
- else if (found.Count == 1)
- {
- var player = found[0];
- returnBlock.Add("status", "200");
- returnBlock.Add("nickname", player.Name);
- returnBlock.Add("username", player.UserAccountName == null ? "" : player.UserAccountName);
- returnBlock.Add("ip", player.IP);
- returnBlock.Add("group", player.Group.Name);
- returnBlock.Add("position", player.TileX + "," + player.TileY);
- var activeItems = player.TPlayer.inventory.Where(p => p.active).ToList();
- returnBlock.Add("inventory", string.Join(", ", activeItems.Select(p => (p.name + ":" + p.stack))));
- returnBlock.Add("buffs", string.Join(", ", player.TPlayer.buffType));
- }
- return returnBlock;
+ {"nickname", player.Name},
+ {"username", null == player.UserAccountName ? "" : player.UserAccountName},
+ {"ip", player.IP},
+ {"group", player.Group.Name},
+ {"position", player.TileX + "," + player.TileY},
+ {"inventory", string.Join(", ", activeItems.Select(p => (p.name + ":" + p.stack)))},
+ {"buffs", string.Join(", ", player.TPlayer.buffType)}
+ };
}
private object PlayerKickV2(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- var playerParam = parameters["player"];
- if (playerParam == null)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Unspecified name.");
- return returnBlock;
- }
- var found = TShock.Utils.FindPlayer(playerParam);
- var reason = parameters["reason"];
- if (found.Count == 0)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " was not found");
- }
- else if (found.Count > 1)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " matches " + playerParam.Count() + " players");
- }
- else if (found.Count == 1)
- {
- var player = found[0];
- TShock.Utils.ForceKick(player, reason == null ? "Kicked via web" : reason);
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Player " + player.Name + " was kicked");
- }
- return returnBlock;
+ var ret = PlayerFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ TSPlayer player = (TSPlayer)ret;
+ TShock.Utils.ForceKick(player, null == parameters["reason"] ? "Kicked via web" : parameters["reason"]);
+ return RestResponse("Player " + player.Name + " was kicked");
}
private object PlayerBanV2(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- var playerParam = parameters["player"];
- var found = TShock.Utils.FindPlayer(playerParam);
- var reason = parameters["reason"];
- if (found.Count == 0)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " was not found");
- }
- else if (found.Count > 1)
- {
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " matches " + playerParam.Count() + " players");
- }
- else if (found.Count == 1)
- {
- var player = found[0];
- TShock.Bans.AddBan(player.IP, player.Name, reason == null ? "Banned via web" : reason);
- TShock.Utils.ForceKick(player, reason == null ? "Banned via web" : reason);
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Player " + player.Name + " was banned");
- }
- return returnBlock;
+ var ret = PlayerFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ TSPlayer player = (TSPlayer)ret;
+ var reason = null == parameters["reason"] ? "Banned via web" : parameters["reason"];
+ TShock.Bans.AddBan(player.IP, player.Name, reason);
+ TShock.Utils.ForceKick(player, reason);
+ return RestResponse("Player " + player.Name + " was banned");
}
private object PlayerKill(RestVerbs verbs, IParameterCollection parameters)
{
- var returnBlock = new Dictionary();
- var playerParam = parameters["player"];
- var found = TShock.Utils.FindPlayer(playerParam);
- var from = verbs["from"];
- if (found.Count == 0)
+ var ret = PlayerFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ TSPlayer player = (TSPlayer)ret;
+ player.DamagePlayer(999999);
+ var from = string.IsNullOrWhiteSpace(parameters["from"]) ? "Server Admin" : parameters["from"];
+ player.SendMessage(string.Format("{0} just killed you!", from));
+ return RestResponse("Player " + player.Name + " was killed");
+ }
+
+ #endregion
+
+ #region RestGroupMethods
+
+ private object GroupList(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var groups = new ArrayList();
+ foreach (Group group in TShock.Groups)
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " was not found");
+ groups.Add(new Dictionary {{"name", group.Name}, {"parent", group.ParentName}, {"chatcolor", group.ChatColor}});
}
- else if (found.Count > 1)
+ return new RestObject() { { "groups", groups } };
+ }
+
+ private object GroupInfo(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var ret = GroupFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ Group group = (Group)ret;
+ return new RestObject() {
+ {"name", group.Name},
+ {"parent", group.ParentName},
+ {"chatcolor", group.ChatColor},
+ {"permissions", group.permissions},
+ {"negatedpermissions", group.negatedpermissions}
+ };
+ }
+
+ private object GroupDestroy(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var ret = GroupFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ Group group = (Group)ret;
+ try
{
- returnBlock.Add("status", "400");
- returnBlock.Add("error", "Name " + playerParam + " matches " + playerParam.Count() + " players");
+ TShock.Groups.DeleteGroup(group.Name, true);
}
- else if (found.Count == 1)
+ catch (Exception e)
{
- var player = found[0];
- player.DamagePlayer(999999);
- player.SendMessage(string.Format("{0} just killed you!", from));
- returnBlock.Add("status", "200");
- returnBlock.Add("response", "Player " + player.Name + " was killed.");
+ return RestError(e.Message);
}
- return returnBlock;
+
+ return RestResponse("Group '" + group.Name + "' deleted successfully");
+ }
+
+ private object GroupCreate(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var name = parameters["group"];
+ if (string.IsNullOrWhiteSpace(name))
+ return RestMissingParam("group");
+ try
+ {
+ TShock.Groups.AddGroup(name, parameters["parent"], parameters["permissions"], parameters["chatcolor"], true);
+ }
+ catch (Exception e)
+ {
+ return RestError(e.Message);
+ }
+
+ return RestResponse("Group '" + name + "' created successfully");
+ }
+
+ private object GroupUpdate(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var ret = GroupFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ Group group = (Group)ret;
+ var parent = (null == parameters["parent"]) ? group.ParentName : parameters["parent"];
+ var chatcolor = (null == parameters["chatcolor"]) ? group.ChatColor : parameters["chatcolor"];
+ var permissions = (null == parameters["permissions"]) ? group.Permissions : parameters["permissions"];
+ try
+ {
+ TShock.Groups.UpdateGroup(group.Name, parent, permissions, chatcolor);
+ }
+ catch (Exception e)
+ {
+ return RestError(e.Message);
+ }
+
+ return RestResponse("Group '" + group.Name + "' updated successfully");
+ }
+
+ #endregion
+
+ #region Utility Methods
+
+ private RestObject RestError(string message, string status = "400")
+ {
+ return new RestObject(status) {Error = message};
+ }
+
+ private RestObject RestResponse(string message, string status = "200")
+ {
+ return new RestObject(status) {Response = message};
+ }
+
+ private RestObject RestMissingParam(string var)
+ {
+ return RestError("Missing or empty " + var + " parameter");
+ }
+
+ private RestObject RestMissingParam(params string[] vars)
+ {
+ return RestMissingParam(string.Join(", ", vars));
+ }
+
+ private RestObject RestInvalidParam(string var)
+ {
+ return RestError("Missing or invalid " + var + " parameter");
+ }
+
+ private bool GetBool(string val, bool def)
+ {
+ bool ret;
+ return bool.TryParse(val, out ret) ? ret : def;
+ }
+
+ private object PlayerFind(IParameterCollection parameters)
+ {
+ string name = parameters["player"];
+ if (string.IsNullOrWhiteSpace(name))
+ return RestMissingParam("player");
+
+ var found = TShock.Utils.FindPlayer(name);
+ switch(found.Count)
+ {
+ case 1:
+ return found[0];
+ case 0:
+ return RestError("Player " + name + " was not found");
+ default:
+ return RestError("Player " + name + " matches " + found.Count + " players");
+ }
+ }
+
+ private object UserFind(IParameterCollection parameters)
+ {
+ string name = parameters["user"];
+ if (string.IsNullOrWhiteSpace(name))
+ return RestMissingParam("user");
+
+ User user;
+ string type = parameters["type"];
+ try
+ {
+ switch (type)
+ {
+ case null:
+ case "name":
+ type = "name";
+ user = TShock.Users.GetUserByName(name);
+ break;
+ case "id":
+ user = TShock.Users.GetUserByID(Convert.ToInt32(name));
+ break;
+ case "ip":
+ user = TShock.Users.GetUserByIP(name);
+
+ break;
+ default:
+ return RestError("Invalid Type: '" + type + "'");
+ }
+ }
+ catch (Exception e)
+ {
+ return RestError(e.Message);
+ }
+
+ if (null == user)
+ return RestError(String.Format("User {0} '{1}' doesn't exist", type, name));
+
+ return user;
+ }
+
+ private object BanFind(IParameterCollection parameters)
+ {
+ string name = parameters["ban"];
+ if (string.IsNullOrWhiteSpace(name))
+ return RestMissingParam("ban");
+
+ string type = parameters["type"];
+ if (string.IsNullOrWhiteSpace(type))
+ return RestMissingParam("type");
+
+ Ban ban;
+ switch (type)
+ {
+ case "ip":
+ ban = TShock.Bans.GetBanByIp(name);
+ break;
+ case "name":
+ ban = TShock.Bans.GetBanByName(name, GetBool(parameters["caseinsensitive"], true));
+ break;
+ default:
+ return RestError("Invalid Type: '" + type + "'");
+ }
+
+ if (null == ban)
+ return RestError("Ban " + type + " '" + name + "' doesn't exist");
+
+ return ban;
+ }
+
+ private object GroupFind(IParameterCollection parameters)
+ {
+ var name = parameters["group"];
+ if (string.IsNullOrWhiteSpace(name))
+ return RestMissingParam("group");
+
+ var group = TShock.Groups.GetGroupByName(name);
+ if (null == group)
+ return RestError("Group '" + name + "' doesn't exist");
+
+ return group;
+ }
+
+ private Dictionary PlayerFilter(TSPlayer tsPlayer, IParameterCollection parameters)
+ {
+ var player = new Dictionary
+ {
+ {"nickname", tsPlayer.Name},
+ {"username", null == tsPlayer.UserAccountName ? "" : tsPlayer.UserAccountName},
+ {"ip", tsPlayer.IP},
+ {"group", tsPlayer.Group.Name},
+ {"active", tsPlayer.Active},
+ {"state", tsPlayer.State},
+ {"team", tsPlayer.Team},
+ };
+ foreach (IParameter filter in parameters)
+ {
+ if (player.ContainsKey(filter.Name) && !player[filter.Name].Equals(filter.Value))
+ return null;
+ }
+ return player;
+ }
+
+ private object PlayerSetMute(IParameterCollection parameters, bool mute)
+ {
+ var ret = PlayerFind(parameters);
+ if (ret is RestObject)
+ return ret;
+
+ TSPlayer player = (TSPlayer)ret;
+ player.mute = mute;
+ var verb = mute ? "muted" : "unmuted";
+ player.SendMessage("You have been remotely " + verb);
+ return RestResponse("Player " + player.Name + " was " + verb);
}
#endregion