mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-24 05:03:34 -04:00
452 lines
18 KiB
C#
452 lines
18 KiB
C#
/*
|
|
Copyright 2011 MCGalaxy
|
|
|
|
Dual-licensed under the Educational Community License, Version 2.0 and
|
|
the GNU General Public License, Version 3 (the "Licenses"); you may
|
|
not use this file except in compliance with the Licenses. You may
|
|
obtain a copy of the Licenses at
|
|
|
|
http://www.opensource.org/licenses/ecl2.php
|
|
http://www.gnu.org/licenses/gpl-3.0.html
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the Licenses are distributed on an "AS IS"
|
|
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
or implied. See the Licenses for the specific language governing
|
|
permissions and limitations under the Licenses.
|
|
*/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Sharkbite.Irc;
|
|
|
|
namespace MCGalaxy {
|
|
public sealed class ForgeBot {
|
|
public static readonly string ColorSignal = "\x03";
|
|
public static readonly string ColorSignal2 = "\x030";
|
|
public static readonly string ResetSignal = "\x0F";
|
|
private Connection connection;
|
|
private List<string> banCmd;
|
|
private string channel, opchannel;
|
|
private string nick;
|
|
private string server;
|
|
private bool reset = false;
|
|
private byte retries = 0;
|
|
public string usedCmd = "";
|
|
public ForgeBot(string channel, string opchannel, string nick, string server) {
|
|
/*if (!File.Exists("Sharkbite.Thresher.dll"))
|
|
{
|
|
Server.irc = false;
|
|
Server.s.Log("[IRC] The IRC dll was not found!");
|
|
return;
|
|
}*/
|
|
this.channel = channel.Trim(); this.opchannel = opchannel.Trim(); this.nick = nick.Replace(" ", ""); this.server = server;
|
|
banCmd = new List<string>();
|
|
if (Server.irc) {
|
|
|
|
ConnectionArgs con = new ConnectionArgs(nick, server);
|
|
con.Port = Server.ircPort;
|
|
connection = new Connection(con, false, false);
|
|
|
|
// Regster events for outgoing
|
|
Player.PlayerChat += new Player.OnPlayerChat(Player_PlayerChat);
|
|
Player.PlayerConnect += new Player.OnPlayerConnect(Player_PlayerConnect);
|
|
Player.PlayerDisconnect += new Player.OnPlayerDisconnect(Player_PlayerDisconnect);
|
|
|
|
// Regster events for incoming
|
|
connection.Listener.OnNick += new NickEventHandler(Listener_OnNick);
|
|
connection.Listener.OnRegistered += new RegisteredEventHandler(Listener_OnRegistered);
|
|
connection.Listener.OnPublic += new PublicMessageEventHandler(Listener_OnPublic);
|
|
connection.Listener.OnPrivate += new PrivateMessageEventHandler(Listener_OnPrivate);
|
|
connection.Listener.OnError += new ErrorMessageEventHandler(Listener_OnError);
|
|
connection.Listener.OnQuit += new QuitEventHandler(Listener_OnQuit);
|
|
connection.Listener.OnJoin += new JoinEventHandler(Listener_OnJoin);
|
|
connection.Listener.OnPart += new PartEventHandler(Listener_OnPart);
|
|
connection.Listener.OnDisconnected += new DisconnectedEventHandler(Listener_OnDisconnected);
|
|
|
|
// Load banned commands list
|
|
if (File.Exists("text/ircbancmd.txt")) // Backwards compatibility
|
|
{
|
|
using (StreamWriter sw = File.CreateText("text/irccmdblacklist.txt")) {
|
|
sw.WriteLine("#Here you can put commands that cannot be used from the IRC bot.");
|
|
sw.WriteLine("#Lines starting with \"#\" are ignored.");
|
|
foreach (string line in File.ReadAllLines("text/ircbancmd.txt"))
|
|
sw.WriteLine(line);
|
|
}
|
|
File.Delete("text/ircbancmd.txt");
|
|
}
|
|
else {
|
|
if (!File.Exists("text/irccmdblacklist.txt")) File.WriteAllLines("text/irccmdblacklist.txt", new String[] { "#Here you can put commands that cannot be used from the IRC bot.", "#Lines starting with \"#\" are ignored." });
|
|
foreach (string line in File.ReadAllLines("text/irccmdblacklist.txt"))
|
|
if (line[0] != '#') banCmd.Add(line);
|
|
}
|
|
}
|
|
}
|
|
public void Say(string message, bool opchat = false, bool color = true) {
|
|
if (!Server.irc || !IsConnected()) return;
|
|
StringBuilder sb = new StringBuilder(message);
|
|
|
|
if(String.IsNullOrEmpty(message.Trim()))
|
|
message = ".";
|
|
|
|
if (color) {
|
|
for (int i = 0; i < 10; i++) {
|
|
sb.Replace("%" + i, ColorSignal + c.MCtoIRC("&" + i));
|
|
sb.Replace("&" + i, ColorSignal + c.MCtoIRC("&" + i));
|
|
}
|
|
for (char ch = 'a'; ch <= 'f'; ch++) {
|
|
sb.Replace("%" + ch, ColorSignal + c.MCtoIRC("&" + ch));
|
|
sb.Replace("&" + ch, ColorSignal + c.MCtoIRC("&" + ch));
|
|
}
|
|
}
|
|
sb.Replace("%r", ResetSignal);
|
|
|
|
connection.Sender.PublicMessage(opchat ? opchannel : channel, sb.ToString());
|
|
}
|
|
public void Pm(string user, string message) {
|
|
if (Server.irc && IsConnected())
|
|
connection.Sender.PrivateMessage(user, message);
|
|
}
|
|
public void Reset() {
|
|
if (!Server.irc) return;
|
|
reset = true;
|
|
retries = 0;
|
|
Disconnect("IRC Bot resetting...");
|
|
Connect();
|
|
}
|
|
void Listener_OnJoin(UserInfo user, string channel) {
|
|
doJoinLeaveMessage(user.Nick, "joined", channel);
|
|
}
|
|
void Listener_OnPart(UserInfo user, string channel, string reason) {
|
|
if (user.Nick == nick) return;
|
|
doJoinLeaveMessage(user.Nick, "left", channel);
|
|
}
|
|
|
|
private void doJoinLeaveMessage(string who, string verb, string channel) {
|
|
Server.s.Log(String.Format("{0} has {1} channel {2}", who, verb, channel));
|
|
Player.GlobalMessage(String.Format("{0}[IRC] {1} has {2} the{3} channel", Server.IRCColour, who, verb, (channel == opchannel ? " operator" : "")));
|
|
}
|
|
void Player_PlayerDisconnect(Player p, string reason) {
|
|
if (Server.irc && IsConnected())
|
|
if (Server.guestLeaveNotify == false && p.group.Permission <= LevelPermission.Guest) {
|
|
return;
|
|
}
|
|
connection.Sender.PublicMessage(channel, p.name + " left the game (" + reason + ")");
|
|
}
|
|
|
|
void Player_PlayerConnect(Player p) {
|
|
if (Server.irc && IsConnected())
|
|
if (Server.guestJoinNotify == false && p.group.Permission <= LevelPermission.Guest) {
|
|
return;
|
|
}
|
|
connection.Sender.PublicMessage(channel, p.name + " joined the game");
|
|
}
|
|
|
|
void Listener_OnQuit(UserInfo user, string reason) {
|
|
if (user.Nick == nick) return;
|
|
Server.s.Log(user.Nick + " has left IRC");
|
|
Player.GlobalMessage(Server.IRCColour + user.Nick + Server.DefaultColor + " has left IRC");
|
|
}
|
|
|
|
void Listener_OnError(ReplyCode code, string message) {
|
|
Server.s.Log("IRC Error: " + message);
|
|
}
|
|
|
|
void Listener_OnPrivate(UserInfo user, string message) {
|
|
if (!Server.ircControllers.Contains(user.Nick)) { Pm(user.Nick, "You are not an IRC controller!"); return; }
|
|
if (message.Split(' ')[0] == "resetbot" || banCmd.Contains(message.Split(' ')[0])) { Pm(user.Nick, "You cannot use this command from IRC!"); return; }
|
|
if (Player.CommandHasBadColourCodes(null, message)) { Pm(user.Nick, "Your command had invalid color codes!"); return; }
|
|
|
|
Command cmd = Command.all.Find(message.Split(' ')[0]);
|
|
if (cmd != null) {
|
|
Server.s.Log("IRC Command: /" + message);
|
|
usedCmd = user.Nick;
|
|
try { cmd.Use(new Player("IRC"), message.Split(' ').Length > 1 ? message.Substring(message.IndexOf(' ')).Trim() : ""); }
|
|
catch { Pm(user.Nick, "Failed command!"); }
|
|
usedCmd = "";
|
|
}
|
|
else
|
|
Pm(user.Nick, "Unknown command!");
|
|
}
|
|
|
|
void Listener_OnPublic(UserInfo user, string channel, string message) {
|
|
//string allowedchars = "1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./!@#$%^*()_+QWERTYUIOPASDFGHJKL:\"ZXCVBNM<>? ";
|
|
// Allowed chars are any ASCII char between 20h/32 and 7Ah/122 inclusive, except for 26h/38 (&) and 60h/96 (`)
|
|
if(message.StartsWith(".who") || message.StartsWith(".players"))
|
|
{
|
|
CmdPlayers();
|
|
}
|
|
if(message.StartsWith(".x"))
|
|
{
|
|
if (Server.ircControllers.Contains(user.Nick))
|
|
{
|
|
if (message.Split(' ')[1] == "resetbot" || banCmd.Contains(message.Split(' ')[0])) { Server.IRC.Say("You cannot use this command from IRC!"); return; }
|
|
if (Player.CommandHasBadColourCodes(null, message)) { Server.IRC.Say("Your command had invalid color codes!"); return; }
|
|
|
|
Command cmd = Command.all.Find(message.Split(' ')[1]);
|
|
if (cmd != null)
|
|
{
|
|
Server.s.Log("IRC Command: /" + message.Replace(".x ", ""));
|
|
usedCmd = user.Nick;
|
|
try { cmd.Use(new Player("IRC"), message.Split(new char[]{' '}, 3)[2].Trim()); }
|
|
catch (Exception e) { Logger.WriteError(e); }
|
|
usedCmd = "";
|
|
}
|
|
else
|
|
Server.IRC.Say("Unknown command!");
|
|
}
|
|
}
|
|
for (byte i = 10; i < 16; i++)
|
|
message = message.Replace(ColorSignal2 + i, c.IRCtoMC(i).Replace("&", "%"));
|
|
for (byte i = 0; i < 10; i++)
|
|
message = message.Replace(ColorSignal2 + i, c.IRCtoMC(i).Replace("&", "%"));
|
|
for (byte i = 10; i < 16; i++)
|
|
message = message.Replace(ColorSignal + i, c.IRCtoMC(i).Replace("&", "%"));
|
|
for (byte i = 0; i < 10; i++)
|
|
message = message.Replace(ColorSignal + i, c.IRCtoMC(i).Replace("&", "%"));
|
|
message.Replace(ResetSignal, "%f");
|
|
message = message.MCCharFilter();
|
|
|
|
if(String.IsNullOrEmpty(message.Trim()))
|
|
message = ".";
|
|
|
|
|
|
if (channel == opchannel) {
|
|
Server.s.Log(String.Format("(OPs): [IRC] {0}: {1}", user.Nick, message));
|
|
Player.GlobalMessageOps(String.Format("To Ops &f-{0}[IRC] {1}&f- {2}", Server.IRCColour, user.Nick, Server.profanityFilter ? ProfanityFilter.Parse(message) : message));
|
|
}
|
|
else {
|
|
Server.s.Log(String.Format("[IRC] {0}: {1}", user.Nick, message));
|
|
Player.GlobalMessage(String.Format("{0}[IRC] {1}: &f{2}", Server.IRCColour, user.Nick, Server.profanityFilter ? ProfanityFilter.Parse(message) : message));
|
|
}
|
|
}
|
|
|
|
void Listener_OnRegistered() {
|
|
Server.s.Log("Connected to IRC!");
|
|
reset = false;
|
|
retries = 0;
|
|
if (Server.ircIdentify && Server.ircPassword != "") {
|
|
Server.s.Log("Identifying with NickServ");
|
|
connection.Sender.PrivateMessage("nickserv", "IDENTIFY " + Server.ircPassword);
|
|
}
|
|
|
|
Server.s.Log("Joining channels...");
|
|
|
|
if (!String.IsNullOrEmpty(channel))
|
|
connection.Sender.Join(channel);
|
|
if (!String.IsNullOrEmpty(opchannel))
|
|
connection.Sender.Join(opchannel);
|
|
}
|
|
|
|
void Listener_OnDisconnected() {
|
|
if (!reset && retries < 3) { retries++; Connect(); }
|
|
}
|
|
|
|
void Listener_OnNick(UserInfo user, string newNick) {
|
|
//Player.GlobalMessage(Server.IRCColour + "[IRC] " + user.Nick + " changed nick to " + newNick);
|
|
|
|
if (newNick.Trim() == "") {
|
|
this.Pm(user.Nick, "You cannot have that username");
|
|
return;
|
|
}
|
|
|
|
string key;
|
|
if (newNick.Split('|').Length == 2) {
|
|
key = newNick.Split('|')[1];
|
|
if (key != null && key != "") {
|
|
switch (key) {
|
|
case "AFK":
|
|
Player.GlobalMessage("[IRC] " + Server.IRCColour + user.Nick + Server.DefaultColor + " is AFK"); Server.ircafkset.Add(user.Nick); break;
|
|
case "Away":
|
|
Player.GlobalMessage("[IRC] " + Server.IRCColour + user.Nick + Server.DefaultColor + " is Away"); Server.ircafkset.Add(user.Nick); break;
|
|
}
|
|
}
|
|
}
|
|
else if (Server.ircafkset.Contains(newNick)) {
|
|
Player.GlobalMessage("[IRC] " + Server.IRCColour + newNick + Server.DefaultColor + " is back");
|
|
Server.ircafkset.Remove(newNick);
|
|
}
|
|
else
|
|
Player.GlobalMessage("[IRC] " + Server.IRCColour + user.Nick + Server.DefaultColor + " is now known as " + newNick);
|
|
}
|
|
void Player_PlayerChat(Player p, string message) {
|
|
|
|
|
|
if (String.IsNullOrEmpty(message.Trim())) {
|
|
Player.SendMessage(p, "You cannot send that message");
|
|
return;
|
|
}
|
|
|
|
|
|
if (Server.ircColorsEnable == true && Server.irc && IsConnected())
|
|
Say(p.color + p.prefix + p.DisplayName + ": &0" + message, p.opchat);
|
|
if (Server.ircColorsEnable == false && Server.irc && IsConnected())
|
|
Say(p.DisplayName + ": " + "%r" + message, p.opchat);
|
|
}
|
|
public void Connect() {
|
|
if (!Server.irc || Server.shuttingDown) return;
|
|
|
|
/*new Thread(new ThreadStart(delegate
|
|
{
|
|
try { connection.Connect(); }
|
|
catch (Exception e)
|
|
{
|
|
Server.s.Log("Failed to connect to IRC");
|
|
Server.ErrorLog(e);
|
|
}
|
|
})).Start();*/
|
|
|
|
Server.s.Log("Connecting to IRC...");
|
|
|
|
try { connection.Connect(); }
|
|
catch (Exception e) {
|
|
Server.s.Log("Failed to connect to IRC!");
|
|
Server.ErrorLog(e);
|
|
}
|
|
}
|
|
public void Disconnect(string reason) {
|
|
if (IsConnected()) { connection.Disconnect(reason); Server.s.Log("Disconnected from IRC!"); }
|
|
}
|
|
public bool IsConnected() {
|
|
if (!Server.irc) return false;
|
|
try { return connection.Connected; }
|
|
catch { return false; }
|
|
}
|
|
#region Commands
|
|
struct playergroups { public Group group; public List<string> players; }
|
|
public static void CmdPlayers()
|
|
{
|
|
//Was lazy
|
|
string message = "";
|
|
try
|
|
{
|
|
List<playergroups> playerList = new List<playergroups>();
|
|
|
|
foreach (Group grp in Group.GroupList)
|
|
{
|
|
if (grp.name != "nobody")
|
|
{
|
|
if (String.IsNullOrEmpty(message) || !Group.Exists(message))
|
|
{
|
|
playergroups groups;
|
|
groups.group = grp;
|
|
groups.players = new List<string>();
|
|
playerList.Add(groups);
|
|
}
|
|
else
|
|
{
|
|
Group grp2 = Group.Find(message);
|
|
if (grp2 != null && grp == grp2)
|
|
{
|
|
playergroups groups;
|
|
groups.group = grp;
|
|
groups.players = new List<string>();
|
|
playerList.Add(groups);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
string devs = "";
|
|
string mods = "";
|
|
string gcmods = "";
|
|
int totalPlayers = 0;
|
|
foreach (Player pl in Player.players)
|
|
{
|
|
if (String.IsNullOrEmpty(message) || !Group.Exists(message) || Group.Find(message) == pl.group)
|
|
{
|
|
totalPlayers++;
|
|
string foundName = pl.name;
|
|
|
|
if (Server.afkset.Contains(pl.name))
|
|
{
|
|
foundName = pl.name + "-afk";
|
|
}
|
|
|
|
if (pl.muted) foundName += "[muted]";
|
|
|
|
|
|
if (pl.isDev)
|
|
{
|
|
if (pl.voice)
|
|
devs += " " + "&f+" + Server.DefaultColor + foundName + " (" + pl.level.name + "),";
|
|
else
|
|
devs += " " + foundName + " (" + pl.level.name + "),";
|
|
}
|
|
if (pl.isMod)
|
|
{
|
|
if (pl.voice)
|
|
mods += " " + "&f+" + Server.DefaultColor + foundName + " (" + pl.level.name + "),";
|
|
else
|
|
mods += " " + foundName + " (" + pl.level.name + "),";
|
|
}
|
|
if (pl.isGCMod)
|
|
{
|
|
if (pl.voice)
|
|
gcmods += " " + "&f+" + Server.DefaultColor + foundName + " (" + pl.level.name + "),";
|
|
else
|
|
gcmods += " " + foundName + " (" + pl.level.name + "),";
|
|
}
|
|
|
|
if (pl.voice)
|
|
playerList.Find(grp => grp.group == pl.group).players.Add("&f+" + Server.DefaultColor + foundName + " (" + pl.level.name + ")");
|
|
else
|
|
playerList.Find(grp => grp.group == pl.group).players.Add(foundName + " (" + pl.level.name + ")");
|
|
}
|
|
}
|
|
|
|
Server.IRC.Say("There are %a" + totalPlayers + Server.DefaultColor + " players online.", false, true);
|
|
bool staff = devs.Length > 0 || mods.Length > 0 || gcmods.Length > 0;
|
|
if (staff) Server.IRC.Say("%cMCGalaxy Staff Online:", false, true);
|
|
if (devs.Length > 0)
|
|
{
|
|
Server.IRC.Say("#%9MCGalaxy Devs:" + Server.DefaultColor + devs.Trim(','), false, true);
|
|
}
|
|
if (mods.Length > 0) {
|
|
Server.IRC.Say("#%2MCGalaxy Mods:" + Server.DefaultColor + mods.Trim(','), false, true);
|
|
}
|
|
if (gcmods.Length > 0) {
|
|
Server.IRC.Say("#%6MCGalaxy GCMods:" + Server.DefaultColor + gcmods.Trim(','), false, true);
|
|
}
|
|
if (staff) Server.IRC.Say("%aNormal Players Online:", false, true);
|
|
for (int i = playerList.Count - 1; i >= 0; i--)
|
|
{
|
|
playergroups groups = playerList[i];
|
|
if (groups.players.Count > 0 || Server.showEmptyRanks)
|
|
{
|
|
string appendString = "";
|
|
foreach (string player in groups.players)
|
|
appendString += ", " + player;
|
|
|
|
if (appendString != "")
|
|
appendString = appendString.Remove(0, 2);
|
|
appendString = ":" + groups.group.color + getPlural(groups.group.trueName) + ": " + appendString;
|
|
|
|
Server.IRC.Say(appendString, false, true);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) { Server.ErrorLog(e); }
|
|
}
|
|
|
|
public static string getPlural(string groupName)
|
|
{
|
|
try
|
|
{
|
|
string last2 = groupName.Substring(groupName.Length - 2).ToLower();
|
|
if ((last2 != "ed" || groupName.Length <= 3) && last2[1] != 's')
|
|
{
|
|
return groupName + "s";
|
|
}
|
|
return groupName;
|
|
}
|
|
catch
|
|
{
|
|
return groupName;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|