chanserv.java

来自「这是整套横扫千军3D版游戏的源码」· Java 代码 · 共 1,468 行 · 第 1/4 页

JAVA
1,468
字号
				}
				root.appendChild(config.createTextNode(Misc.EOL + Misc.enumSpaces(4)));
				
			} catch (XPathExpressionException e) {
				e.printStackTrace();
				closeAndExit(1);
			}
			
			// ok save it now:
			config.normalize(); //*** is this needed?
	        DOMSource source = new DOMSource(config);
	        StreamResult result = new StreamResult(new FileOutputStream(fname));

	        TransformerFactory transFactory = TransformerFactory.newInstance();
	        Transformer transformer = transFactory.newTransformer();

	        transformer.transform(source, result);
	        
	        if (DEBUG) Log.log("Config file saved to " + fname);
		} catch (Exception e) {
			Log.error("Unable to save config file to " + fname + "! Ignoring ...");
		}
	}
	
	// multiple threads may call this method
	public static synchronized void sendLine(String s) {
		if (DEBUG) Log.log("Client: \"" + s + "\"");
		sockout.println(s);
	}
	
	private static boolean tryToConnect() {
        try {
        	Log.log("Connecting to " + serverAddress + ":" + serverPort + " ...");
            socket = new Socket(serverAddress, serverPort);
            sockout = new PrintWriter(socket.getOutputStream(), true);
            sockin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (UnknownHostException e) {
            Log.error("Unknown host error: " + serverAddress);
            return false;
        } catch (IOException e) {
            Log.error("Couldn't get I/O for the connection to: " + serverAddress);
            return false;
        }
		
        Log.log("Now connected to " + serverAddress);
        return true;
	}
	
	public static void messageLoop() {
		String line;
        while (true) {
        	try {
            	line = sockin.readLine();
        	} catch (IOException e) {
        		Log.error("Connection with server closed with exception.");
        		break;
        	}
        	if (line == null) break;
            if (DEBUG) Log.log("Server: \"" + line + "\"");
            
            // parse command and respond to it:
    		try {
    			configLock.acquire();
                execRemoteCommand(line);
    		} catch (InterruptedException e) {
    			//return ;
    		} finally {
    			configLock.release();	
    		}

        }

        try {
            sockout.close();
            sockin.close();
            socket.close();
        } catch (IOException e) {
        	// do nothing
        }
        Log.log("Connection with server closed.");
	}
	
	// processes messages that were only sent to server admins. "message" parameter must be a
	// message string withouth the "[broadcast to all admins]: " part.
	public static void processAdminBroadcast(String message) {
		Log.debug("admin broadcast: '" + message + "'");

		// let's check if some channel founder/operator has just renamed his account:
		if (message.matches("User <[^>]{1,}> has just renamed his account to <[^>]{1,}>")) {
			String oldNick = message.substring(message.indexOf('<')+1, message.indexOf('>')); 
			String newNick = message.substring(message.indexOf('<', message.indexOf('>'))+1, message.indexOf('>', message.indexOf('>')+1));

			// lets rename all founder/operator entries for this user:
			for (int i = 0; i < channels.size(); i++) {
				Channel chan = (Channel)channels.get(i);
				if (chan.isFounder(oldNick)) {
					chan.renameFounder(newNick);
					Log.log("Founder <" + oldNick + "> of #" + chan.name + " renamed to <" + newNick + ">");
				}
				if (chan.isOperator(oldNick)) {
					chan.renameOperator(oldNick, newNick);
					Log.log("Operator <" + oldNick + "> of #" + chan.name + " renamed to <" + newNick + ">");
				}
			}
		}
	}
	
	public static boolean execRemoteCommand(String command) {
		if (command.trim().equals("")) return false;
		
		// try to extract message ID if present:
		if (command.charAt(0) == '#') try {
			if (!command.matches("^#\\d+\\s[\\s\\S]*")) return false; // malformed command
			int ID = Integer.parseInt(command.substring(1).split("\\s")[0]);
			// remove ID field from the rest of command:
			command = command.replaceFirst("#\\d+\\s", "");
			// forward the command to the waiting thread:
			synchronized (remoteAccessServer.threads) {
				for (int i = 0; i < remoteAccessServer.threads.size(); i++) {
					if (((RemoteClientThread)remoteAccessServer.threads.get(i)).ID == ID) {
						((RemoteClientThread)remoteAccessServer.threads.get(i)).replyQueue.put(command);
						return true;
					}
				}
			}
			return false; // no suitable thread found! Perhaps thread already finished before it could read the response (not a problem)
		} catch (NumberFormatException e) {
			return false; // this means that the command is malformed
		} catch (PatternSyntaxException e) {
			return false; // this means that the command is malformed
		}
		
		String[] commands = command.split(" ");
		commands[0] = commands[0].toUpperCase();
		
		if (commands[0].equals("TASSERVER")) {
			sendLine("LOGIN " + username + " " + password + " 0 * ChanServ " + VERSION);
		} else if (commands[0].equals("ACCEPTED")) {
			Log.log("Login accepted.");
			// join registered and static channels:
			for (int i = 0; i < channels.size(); i++)
				sendLine("JOIN " + ((Channel)channels.get(i)).name);
		} else if (commands[0].equals("DENIED")) {
			Log.log("Login denied. Reason: " + Misc.makeSentence(commands, 1));
			closeAndExit();
		} else if (commands[0].equals("AGREEMENT")) {
			// not done yet. Should respond with CONFIRMAGREEMENT and then resend LOGIN command.
			Log.log("Server is requesting agreement confirmation. Cancelling ...");
			closeAndExit();
		} else if (commands[0].equals("ADDUSER")) {
			clients.add(new Client(commands[1]));
		} else if (commands[0].equals("REMOVEUSER")) {
			for (int i = 0; i < clients.size(); i++) if (((Client)clients.get(i)).name.equals(commands[1])) {
				clients.remove(i);
				break;
			}
		} else if (commands[0].equals("CLIENTSTATUS")) {
			for (int i = 0; i < clients.size(); i++) if (((Client)clients.get(i)).name.equals(commands[1])) {
				Client client = (Client)clients.get(i); 
				client.setStatus(Integer.parseInt(commands[2]));
				AntiSpamSystem.processClientStatusChange(client);
				break;
			}
		} else if (commands[0].equals("JOIN")) {
			Log.log("Joined #" + commands[1]);
			Channel chan = getChannel(commands[1]);
			if (chan == null) return false; // this could happen just after we unregistered the channel (since there is always some lag between us and the server)
			chan.joined = true;
			chan.clearClients();
			// set topic, lock channel, ... :
			if (!chan.isStatic) {
				if (!chan.key.equals(""))
					sendLine("SETCHANNELKEY " + chan.name + " " + chan.key);
				if (chan.topic.equals(""))
					sendLine("CHANNELTOPIC " + chan.name + " *");
				else
					sendLine("CHANNELTOPIC " + chan.name + " " + chan.topic);
			}
		} else if (commands[0].equals("CLIENTS")) { 
			Channel chan = getChannel(commands[1]);
			if (chan == null) return false; // this could happen just after we unregistered the channel (since there is always some lag between us and the server)
			for (int i = 2; i < commands.length; i++) {
				chan.addClient(commands[i]);
			}
		} else if (commands[0].equals("JOINED")) {
			Channel chan = getChannel(commands[1]);
			if (chan == null) return false; // this could happen just after we unregistered the channel (since there is always some lag between us and the server)
			chan.addClient(commands[2]);
			Log.toFile(chan.logFileName, "* " + commands[2] + " has joined " + "#" + chan.name);
		} else if (commands[0].equals("LEFT")) { 
			Channel chan = getChannel(commands[1]);
			if (chan == null) return false; // this could happen just after we unregistered the channel (since there is always some lag between us and the server)
			chan.removeClient(commands[2]);
			String out = "* " + commands[2] + " has left " + "#" + chan.name;
			if (commands.length > 3)
				out = out + " (" + Misc.makeSentence(commands, 3) + ")";
			Log.toFile(chan.logFileName, out);
		} else if (commands[0].equals("JOINFAILED")) {
			channels.add(new Channel(commands[1]));
			Log.log("Failed to join #" + commands[1] + ". Reason: " + Misc.makeSentence(commands, 2));
		} else if (commands[0].equals("CHANNELTOPIC")) {
			Channel chan = getChannel(commands[1]);
			if (chan == null) return false; // this could happen just after we unregistered the channel (since there is always some lag between us and the server)
			chan.topic = Misc.makeSentence(commands, 4);
			Log.toFile(chan.logFileName, "* Channel topic is '" + chan.topic + "' set by " + commands[2]);
		} else if (commands[0].equals("SAID")) {
			Channel chan = getChannel(commands[1]);
			if (chan == null) return false; // this could happen just after we unregistered the channel (since there is always some lag between us and the server)
			String user = commands[2];
			String msg = Misc.makeSentence(commands, 3);
			if (chan.antispam) AntiSpamSystem.processUserMsg(chan.name, user, msg);
			Log.toFile(chan.logFileName, "<" + user + "> " + msg);
			if ((msg.length() > 0) && (msg.charAt(0) == '!')) processUserCommand(msg.substring(1, msg.length()), getClient(user), chan);
		} else if (commands[0].equals("SAIDEX")) {
			Channel chan = getChannel(commands[1]);
			if (chan == null) return false; // this could happen just after we unregistered the channel (since there is always some lag between us and the server)
			String user = commands[2];
			String msg = Misc.makeSentence(commands, 3);
			if (chan.antispam) AntiSpamSystem.processUserMsg(chan.name, user, msg);
			Log.toFile(chan.logFileName, "* " + user + " " + msg);
		} else if (commands[0].equals("SAIDPRIVATE")) {
			
			String user = commands[1];
			String msg = Misc.makeSentence(commands, 2);
			
			Log.toFile(user + ".log", "<" + user + "> " + msg);
			if ((msg.length() > 0) && (msg.charAt(0)) == '!') processUserCommand(msg.substring(1, msg.length()), getClient(user), null);
		} else if (commands[0].equals("SERVERMSG")) {
			Log.log("Message from server: " + Misc.makeSentence(commands, 1));
			if (Misc.makeSentence(commands, 1).startsWith("[broadcast to all admins]")) processAdminBroadcast(Misc.makeSentence(commands, 1).substring("[broadcast to all admins]: ".length(), Misc.makeSentence(commands, 1).length()));
		} else if (commands[0].equals("SERVERMSGBOX")) {
			Log.log("MsgBox from server: " + Misc.makeSentence(commands, 1));
		} else if (commands[0].equals("CHANNELMESSAGE")) {
			Channel chan = getChannel(commands[1]);
			if (chan != null) {
				String out = "* Channel message: " + Misc.makeSentence(commands, 2);
				Log.toFile(chan.logFileName, out);
			}
		} else if (commands[0].equals("BROADCAST")) {
			Log.log("*** Broadcast from server: " + Misc.makeSentence(commands, 1));
		} else if (commands[0].equals("MUTELISTBEGIN")) {
			lastMuteList.clear();
			lastMuteListChannel = commands[1]; 
		} else if (commands[0].equals("MUTELIST")) {
			lastMuteList.add(Misc.makeSentence(commands, 1));
		} else if (commands[0].equals("MUTELISTEND")) {
			int i = 0;
			while (i < forwardMuteList.size()) {
				MuteListRequest request = (MuteListRequest)forwardMuteList.get(i); 
				if (!request.chanName.equals(lastMuteListChannel)) {
					i++;
					continue;
				}
				Client target = getClient(request.sendTo);
				if (target == null) { // user who made the request has already gone offline!
					forwardMuteList.remove(i);
					continue; 
				}
				if (System.currentTimeMillis() - request.requestTime > 10000) { // this request has already expired
					forwardMuteList.remove(i);
					continue; 
				}
				// forward the mute list to the one who requested it:
				if (lastMuteList.size() == 0) sendMessage(target, getChannel(request.replyToChan), "Mute list for #" + request.chanName + " is empty!");
				else {
					sendMessage(target, getChannel(request.replyToChan), "Mute list for #" + request.chanName+ " (" + lastMuteList.size() + " entries):");
					for (int j = 0; j < lastMuteList.size(); j++) {
						sendMessage(target, getChannel(request.replyToChan), (String)lastMuteList.get(j));		
					}
				}
				forwardMuteList.remove(i);
			}
		}

		
		
		return true;
	}
	
	/* If the command was issued from a private chat, then "channel" parameter should be null */
	public static void processUserCommand(String command, Client client, Channel channel) {
		if (command.trim().equals("")) return ;
		String[] params = command.split(" ");
		params[0] = params[0].toUpperCase(); // params[0] is the base command
		
		// remove all empty tokens to avoid any problems while parsing commands later on:
		{
			boolean done = false;
			while (!done) {
				for (int i = 0; i < params.length; i++)
					if (params[i].equals("")) {
						params = (String[])Misc.removeFromObjectArray(i, params);
						break;
					} else if (i == params.length-1) done = true;
			}
		}

		if (params[0].equals("HELP")) {
			// force the message to be sent to private chat rather than to the channel (to avoid unneccessary bloating the channel):
			sendMessage(client, null, "Hello, " + client.name + "!");
			sendMessage(client, null, "I am an automated channel service bot,");
			sendMessage(client, null, "for the full list of commands, see http://taspring.clan-sy.com/dl/ChanServCommands.html");
			sendMessage(client, null, "If you want to go ahead and register a new channel, please contact one of the server moderators!");
		} else if (params[0].equals("INFO")) {
			// if the command was issued from a channel:
			if (channel != null) { // insert <channame> parameter so we don't have to handle two different situations for each command
				params = (String[])Misc.insertIntoObjectArray("#" + channel.name, 1, params);
			}
			
			if (params.length != 2) {
				sendMessage(client, channel, "Error: Invalid params!");
				return ;
			}
			
			if (params[1].charAt(0) != '#') {
				sendMessage(client, channel, "Error: Bad channel name (forgot #?)");
				return ;
			}
			
			String chanName = params[1].substring(1, params[1].length());
			Channel chan = getChannel(chanName);
			if (chan == null) {
				sendMessage(client, channel, "Channel #" + chanName + " is not registered!");
				return ;
			}

			if (chan.isStatic) {
				sendMessage(client, channel, "Channel #" + chanName + " is registered as a static channel, no further info available!");
				return ;
			}

			String respond = "Channel #" + chan.name + " info: Anti-spam protection is " + (chan.antispam ? "on" : "off") + ". Founder is <" + chan.founder + ">, ";
			Vector ops = chan.getOperatorList();
			if (ops.size() == 0) respond = respond + "no operators are registered.";
			else if (ops.size() == 1) respond = respond + "1 registered operator is <" + (String)ops.get(0) + ">.";
			else {
				respond = respond + ops.size() + " registered operators are ";
				for (int i = 0; i < ops.size()-1; i++)
					respond = respond + "<" + (String)ops.get(i) + ">, ";
				respond = respond + "<" + (String)ops.get(ops.size()-1) + ">.";
			}
				
			sendMessage(client, channel, respond);
		} else if (params[0].equals("REGISTER")) {
			if (!client.isModerator()) {
				sendMessage(client, channel, "Sorry, you'll have to contact one of the server moderators to register a channel for you!");
				return ;
			}
			
			if (params.length != 3) {
				sendMessage(client, channel, "Error: Invalid params!");
				return ;
			}
				
			if (params[1].charAt(0) != '#') {
				sendMessage(client, channel, "Error: Bad channel name (forgot #?)");
				return ;
			}
				
			String chanName = params[1].substring(1, params[1].length());
			String valid = Channel.isChanNameValid(chanName);
			if (valid != null) {
				sendMessage(client, channel, "Error: Bad channel name (" + valid + ")");
				return ;
			}
			
			for (int i = 0; i < channels.size(); i++) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?