1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-07-04 19:08:55 -05:00

-added !ip command (prints a client's external IP)

-fixed up the findall command
-moved aliases to the manager
-added admins page to view privileged users
-fixed refactoring mistake with messages
This commit is contained in:
RaidMax
2017-08-17 18:28:08 -05:00
parent 7c0ad5c021
commit 6a94882d20
15 changed files with 276 additions and 105 deletions

View File

@ -158,6 +158,9 @@
<Content Include="version.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="webfront\admins.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="webfront\bans.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@ -45,23 +45,41 @@ namespace IW4MAdmin
querySet = System.Web.HttpUtility.ParseQueryString(SharedLibrary.Utilities.StripIllegalCharacters(request.QueryString));
querySet.Set("IP", IP);
SharedLibrary.HttpResponse requestedPage = WebService.GetPage(request.Path, querySet, request.Headers);
var headers = new HttpResponseHead()
try
{
Status = "200 OK",
Headers = new Dictionary<string, string>()
SharedLibrary.HttpResponse requestedPage = WebService.GetPage(request.Path, querySet, request.Headers);
var headers = new HttpResponseHead()
{
Status = "200 OK",
Headers = new Dictionary<string, string>()
{
{ "Content-Type", requestedPage.contentType },
{ "Content-Length", requestedPage.content.Length.ToString() },
{ "Access-Control-Allow-Origin", "*" },
}
};
};
foreach (var key in requestedPage.additionalHeaders.Keys)
headers.Headers.Add(key, requestedPage.additionalHeaders[key]);
foreach (var key in requestedPage.additionalHeaders.Keys)
headers.Headers.Add(key, requestedPage.additionalHeaders[key]);
response.OnResponse(headers, new BufferedProducer(requestedPage.content));
response.OnResponse(headers, new BufferedProducer(requestedPage.content));
}
catch (Exception e)
{
ApplicationManager.GetInstance().Logger.WriteError($"Webfront error during request: {e.Message}");
response.OnResponse(new HttpResponseHead()
{
Status = "500 Internal Server Error",
Headers = new Dictionary<string, string>()
{
{ "Content-Type", "text/html" },
{ "Content-Length", "0"},
}
}, new BufferedProducer(""));
}
}
}

View File

@ -161,6 +161,7 @@ namespace IW4MAdmin
Commands.Add(new CExecuteRCON("rcon", "send rcon command to server. syntax: !rcon <command>", "rcon", Player.Permission.Owner, 1, false));
Commands.Add(new CFindAllPlayers("findall", "find a player by their aliase(s). syntax: !findall <player>", "fa", Player.Permission.Moderator, 1, false));
Commands.Add(new CPlugins("plugins", "view all loaded plugins. syntax: !plugins", "p", Player.Permission.Administrator, 0, false));
Commands.Add(new CIP("ip", "view your external IP address. syntax: !ip", "getexternalip", Player.Permission.User, 0, false));
foreach (Command C in SharedLibrary.Plugins.PluginImporter.ActiveCommands)
Commands.Add(C);
@ -247,5 +248,49 @@ namespace IW4MAdmin
return ActiveClients;
}
public IList<Player> GetAliasClients(Player Origin)
{
List<int> databaseIDs = new List<int>();
foreach (Aliases A in GetAliases(Origin))
databaseIDs.Add(A.Number);
return GetClientDatabase().GetPlayers(databaseIDs);
}
public IList<Aliases> GetAliases(Player Origin)
{
List<Aliases> allAliases = new List<Aliases>();
if (Origin == null)
return allAliases;
Aliases currentIdentityAliases = GetAliasesDatabase().GetPlayerAliases(Origin.DatabaseID);
if (currentIdentityAliases == null)
return allAliases;
GetAliases(allAliases, currentIdentityAliases);
if (Origin.Alias != null)
allAliases.Add(Origin.Alias);
return allAliases;
}
private void GetAliases(List<Aliases> returnAliases, Aliases currentAlias)
{
foreach (String IP in currentAlias.IPS)
{
List<Aliases> Matching = GetAliasesDatabase().GetPlayerAliases(IP);
foreach (Aliases I in Matching)
{
if (!returnAliases.Contains(I) && returnAliases.Find(x => x.Number == I.Number) == null)
{
returnAliases.Add(I);
GetAliases(returnAliases, I);
}
}
}
}
}
}

View File

@ -15,40 +15,6 @@ namespace IW4MAdmin
{
public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg) { }
private void GetAliases(List<Aliases> returnAliases, Aliases currentAlias)
{
foreach(String IP in currentAlias.IPS)
{
List<Aliases> Matching = Manager.GetAliasesDatabase().GetPlayerAliases(IP);
foreach(Aliases I in Matching)
{
if (!returnAliases.Contains(I) && returnAliases.Find(x => x.Number == I.Number) == null)
{
returnAliases.Add(I);
GetAliases(returnAliases, I);
}
}
}
}
public override List<Aliases> GetAliases(Player Origin)
{
List<Aliases> allAliases = new List<Aliases>();
if (Origin == null)
return allAliases;
Aliases currentIdentityAliases = Manager.GetAliasesDatabase().GetPlayerAliases(Origin.DatabaseID);
if (currentIdentityAliases == null)
return allAliases;
GetAliases(allAliases, currentIdentityAliases);
if (Origin.Alias != null)
allAliases.Add(Origin.Alias);
return allAliases;
}
override public async Task<bool> AddPlayer(Player P)
{
if (P.ClientID < 0 || P.ClientID > (Players.Count-1) || P.Ping < 1 || P.Ping == 999) // invalid index
@ -123,7 +89,7 @@ namespace IW4MAdmin
return true;
}
var newPlayerAliases = GetPlayerAliases(NewPlayer);
var newPlayerAliases = Manager.GetAliasClients(NewPlayer);
foreach (Player aP in newPlayerAliases) // lets check their aliases
{
@ -153,7 +119,6 @@ namespace IW4MAdmin
if (NewPlayer.Level > Player.Permission.Moderator)
await NewPlayer.Tell("There are ^5" + Reports.Count + " ^7recent reports!");
ClientNum++;
return true;
}
@ -168,7 +133,7 @@ namespace IW4MAdmin
//Remove player by CLIENT NUMBER
override public async Task RemovePlayer(int cNum)
{
if (cNum >= 0 && cNum < Players.Count)
if (cNum >= 0)
{
Player Leaving = Players[cNum];
Leaving.Connections++;
@ -177,8 +142,6 @@ namespace IW4MAdmin
Logger.WriteInfo($"Client {Leaving.Name}::{Leaving.NetworkID} disconnecting...");
await ExecuteEvent(new Event(Event.GType.Disconnect, "", Leaving, null, this));
Players[cNum] = null;
ClientNum--;
}
}
@ -315,7 +278,7 @@ namespace IW4MAdmin
}
}
async Task PollPlayersAsync()
async Task<int> PollPlayersAsync()
{
var CurrentPlayers = await this.GetStatusAsync();
@ -327,6 +290,8 @@ namespace IW4MAdmin
foreach (var P in CurrentPlayers)
await AddPlayer(P);
return CurrentPlayers.Count;
}
long l_size = -1;
@ -349,7 +314,7 @@ namespace IW4MAdmin
try
{
await PollPlayersAsync();
ClientNum = await PollPlayersAsync();
if (ConnectionErrors > 0)
{
@ -389,10 +354,10 @@ namespace IW4MAdmin
playerCountStart = DateTime.Now;
}
if (LastMessage.TotalSeconds > MessageTime && BroadcastMessages.Count > 0 && Players.Count > 0)
if (LastMessage.TotalSeconds > MessageTime && BroadcastMessages.Count > 0 && ClientNum > 0)
{
await Broadcast(Utilities.ProcessMessageToken(Manager.GetMessageTokens(), BroadcastMessages[NextMessage]));
NextMessage = NextMessage == (BroadcastMessages.Count - 1) ? 0 : NextMessage++;
Console.WriteLine(Utilities.ProcessMessageToken(Manager.GetMessageTokens(), BroadcastMessages[NextMessage]));
NextMessage = NextMessage == (BroadcastMessages.Count - 1) ? 0 : NextMessage + 1;
start = DateTime.Now;
}

View File

@ -29,6 +29,8 @@ namespace IW4MAdmin
SharedLibrary.WebService.PageList.Add(new WebConsole());
SharedLibrary.WebService.PageList.Add(new ConsoleJSON());
SharedLibrary.WebService.PageList.Add(new PubbansJSON());
SharedLibrary.WebService.PageList.Add(new AdminsJSON());
SharedLibrary.WebService.PageList.Add(new Admins());
Thread scheduleThread = new Thread(() => { ScheduleThreadStart(webScheduler, webService); })
{
@ -521,6 +523,69 @@ namespace IW4MAdmin
}
}
class Admins : HTMLPage
{
public override string GetName()
{
return "Admins";
}
public override string GetPath()
{
return "/Admins";
}
public override string GetContent(System.Collections.Specialized.NameValueCollection querySet, IDictionary<string, string> headers)
{
StringBuilder S = new StringBuilder();
S.Append(LoadHeader());
IFile admins = new IFile("webfront\\admins.html");
S.Append(admins.GetText());
admins.Close();
S.Append(LoadFooter());
return S.ToString();
}
}
class AdminsJSON : IPage
{
public string GetName()
{
return "Admins Json";
}
public string GetPath()
{
return "/GetAdmins";
}
public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary<string, string> headers)
{
var Admins = ApplicationManager.GetInstance().GetClientDatabase().GetAdmins().OrderByDescending(a => a.Level);
HttpResponse resp = new HttpResponse()
{
contentType = GetContentType(),
content = Newtonsoft.Json.JsonConvert.SerializeObject(Admins, Newtonsoft.Json.Formatting.Indented),
additionalHeaders = new Dictionary<string, string>()
};
return resp;
}
public string GetContentType()
{
return "application/json";
}
public bool Visible()
{
return false;
}
}
class PubbansJSON : IPage
{
public string GetName()
@ -604,7 +669,7 @@ namespace IW4MAdmin
return false;
}
}
class GetPlayer : IPage
{
public string GetContentType()
@ -631,7 +696,8 @@ namespace IW4MAdmin
contentType = GetContentType(),
additionalHeaders = new Dictionary<string, string>()
};
bool authed = ApplicationManager.GetInstance().GetClientDatabase().GetAdmins().FindAll(x => x.IP == querySet["IP"]).Count > 0;
bool authed = ApplicationManager.GetInstance().GetClientDatabase().GetAdmins().FindAll(x => x.IP == querySet["IP"] && x.Level > Player.Permission.Trusted).Count > 0
|| querySet["IP"] == "127.0.0.1";
bool recent = false;
if (querySet["id"] != null)
@ -675,7 +741,7 @@ namespace IW4MAdmin
if (!recent)
{
foreach (var a in ApplicationManager.GetInstance().Servers.First().GetAliases(pp))
foreach (var a in ApplicationManager.GetInstance().GetAliases(pp))
{
eachPlayer.playerAliases = a.Names;
eachPlayer.playerIPs = a.IPS;
@ -765,4 +831,11 @@ namespace IW4MAdmin
{
public List<string> Result;
}
[Serializable]
class PrivilegedUsers
{
public Player.Permission Permission { get; set; }
public List<Player> Players { get; set; }
}
}

Binary file not shown.

View File

@ -3,8 +3,13 @@ CHANGELOG:
-works: with COD, WaW, MW3, BO1 (preliminary without extensive testing)
-fixed the issue with webfront chat history
-fixed console issue of spamming 'polling rate decreased' when server goes offline
-'unknown' admin in webfront defaults to 'IW4MAdmin'
-'unknown' admin in webfront defaults to 'IW4MAdmin' (refactoring mistake)
-streamlined the async server initialization
-added !ip command (prints a client's external IP)
-fixed up the findall command
-moved aliases to the manager
-added admins page to view privileged users
-fixed refactoring mistake with messages
VERSION 1.3

View File

@ -0,0 +1,71 @@
<script>
function printPlayer(player, i)
{
var p = "";
p +=
"<div class=\"playerInfo table alternate_" + i % 2 + "\"> \
<div class=\"tableCell\"><a href=\"/players?id=" + player['playerID'] + "\">" + player['playerName'] + "</a></div> \
<div class=\"tableCell\">" + formatHidden(player['playerAliases'], player.authed) + "</div> \
<div class=\"tableCell\">" + formatHidden(player['playerIPs'], player.authed) + "</div> \
<div class=\"tableCell\">" + getColorForLevel(player['playerLevel'], player['playerLevel']) + "</div> \
<div class=\"tableCell\">" + player['playerConnections'] + "</div>";
if (player.showV2Features)
{
p +=
"<div class=\"tableCell actionButton\" style='width: 2em;'> \
<a target=\"_blank\" href='http://server.nbsclan.org/screen.php?id=" + player.forumID + "&name=" + player.playerName + "'> \
<i class=\"fa fa-camera\" aria-hidden=\"true\"></i> \
</a> \
<a target=\"_blank\" href='https://v2.mcsebi.ru/memberlist.php?mode=viewprofile&u=" + player.forumID + "'> \
<i class=\"fa fa-user tableCell\" aria-hidden=\"true\"></i> \
</a> \
</div> ";
}
else
{
p+=
"<div class=\"tableCell\" style='width: 2em;'><i class=\"fa fa-ban\" aria-hidden=\"true\"></i></div>"
}
p +=
"<div class=\"tableCell alignRight\">" + checkJustNow(player['lastSeen']) + "</div> \
</div>";
$("#playersTable").append(p);
}
function getAdmins() {
$.getJSON('/GetAdmins', function(result) {
$.each(result, function(i, player) {
printPlayer(player, i);
});
}).done(function (data) { $(".loader").fadeOut(); });
}
$( document ).ready(function() {
getAdmins();
});
</script>
<div class="playerSearchWrap">
<input type="button" class="searchButton" name="Search" value="Search"/>
<input type="text" class="search" placeholder="Player Name..."/>
</div>
<div class="contentHeader table">
<div class="contentColumn tableCell">Name</div>
<div class="contentColumn tableCell">Aliases</div>
<div class="contentColumn tableCell">IP</div>
<div class="contentColumn tableCell">Level</div>
<div class="contentColumn tableCell">Connections</div>
<div class="contentColumn tableCell" style="width: 1em;">V2</div>
<div class="contentColumn tableCell alignRight">Last Seen</div>
</div>
<div id="playersTable">
</div>
<hr/>