0

我有一个 IRC 机器人,我正在尝试获取游戏服务器(GTA SA 多人游戏)的信息。我有现成的查询,但我无法在我的机器人中实现它。如果我尝试加载相同的脚本,但没有将其放入机器人的结构中,它会起作用。它给我的错误是

NameError:名称'ip'未定义

我尝试在 中添加 ip 地址作为参数def(inp,say=None),但它仍然不起作用。那是代码:

from util import Query
from util import hook
import sys

@hook.command
def serverinfo(inp,ip="",port="",say=None):
    ip = "78.129.221.58"
    port = 7777 
if len(sys.argv) >= 3:
    ip = str(sys.argv[1])
    port = int(sys.argv[2])

query = Query(ip,port)
info = query.GetInformation()
say(info)
if info['players'] <= 100:
    say(query.GetPlayers())
    say(query.GetDetailedPlayers())
else: say('can\' get players because players is above 100')
say(query.Ping())
query.Close()

那是我导入的查询

import socket, struct, random, datetime
from cStringIO import StringIO

class Query:
    def __init__(self, ip, port):
        self.ip, self.port = socket.gethostbyname(ip), port
        self.data = StringIO("")
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.connect((ip, port))
        self.sock.settimeout(1)

    def CreatePacket(self, opcode):
        ips = self.ip.split('.');
        packet = "SAMP{0}{1}{2}{3}{4}{5}{6}".format(chr(int(ips[0])), chr(int(ips[1])), chr(int(ips[2])), chr(int(ips[3])), chr(self.port & 0xFF), chr(self.port >> 8 & 0xFF), opcode)
        if opcode == 'p':
            packet += struct.pack("BBBB", random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
        return packet

    def GetInformation(self):
        try:
            self.sock.send(self.CreatePacket('i'))
            info = {}
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            info['passworded'] = struct.unpack('?', self.data.read(1))[0]
            info['players'] = struct.unpack('h', self.data.read(2))[0]
            info['maxplayers'] = struct.unpack('h', self.data.read(2))[0]

            info['hostname'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
            info['gamemode'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
            info['mapname'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
        except socket.timeout:
            info['error'] = 1
        return info

    def GetRules(self):
        try:
            self.sock.send(self.CreatePacket('r'))
            rules = {}
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            rulecount = struct.unpack('h', self.data.read(2))[0]
            for i in range(rulecount):
                name = self.data.read(struct.unpack('b', self.data.read(1))[0])
                rules[name] = self.data.read(struct.unpack('b', self.data.read(1))[0])
        except socket.timeout:
            rules['error'] = 1
        return rules

    def GetPlayers(self):
        try:
            self.sock.send(self.CreatePacket('c'))
            players = []
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            playercount = struct.unpack('h', self.data.read(2))[0]
            for i in range(playercount):
                name = self.data.read(struct.unpack('b', self.data.read(1))[0])
                players.append([name, struct.unpack('i', self.data.read(4))[0]])
        except socket.timeout:
            players = {'error': 1}
        return players

    def GetDetailedPlayers(self):
        try:
            self.sock.send(self.CreatePacket('d'))
            players = []
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            playercount = struct.unpack('h', self.data.read(2))[0]
            for i in range(playercount):
                playerid = struct.unpack('b', self.data.read(1))[0]
                name = self.data.read(struct.unpack('b', self.data.read(1))[0])
                score = struct.unpack('i', self.data.read(4))[0]
                ping = struct.unpack('i', self.data.read(4))[0]
                players.append([playerid, name, score, ping])
        except socket.timeout:
            players = {'error': 1}
        return players

    def Close(self):
        self.sock.close()   

    def Ping(self):
        packet = self.CreatePacket('p')
        a = datetime.datetime.now()
        self.sock.send(packet)
        self.sock.recv(2048)
        b = datetime.datetime.now()
        c = b - a
        return int((c.days * 24 * 60 * 60 + c.seconds) * 1000 + c.microseconds / 1000.0)

class Rcon:
    def __init__(self, ip, port, password):
        self.ip, self.port, self.password = socket.gethostbyname(ip), port, password
        self.data = StringIO("")
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.connect((ip, port))
        self.sock.settimeout(0.5)

    def CreatePacket(self, opcode, password, command):
        ips = self.ip.split('.');
        packet = "SAMP{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}".format(chr(int(ips[0])), chr(int(ips[1])), chr(int(ips[2])), chr(int(ips[3])), chr(self.port & 0xFF), chr(self.port >> 8 & 0xFF), opcode, chr(len(password) & 0xFF), chr(len(password) >> 8 & 0xFF), password, chr(len(command) & 0xFF), chr(len(command) >> 8 & 0xFF), command)
        return packet

    def Send(self, command):
        self.sock.send(self.CreatePacket('x', self.password, command))
        output = []
        while 1:
            try:
                self.data = StringIO(self.sock.recv(2048))
                self.data.read(11)
                strlen = struct.unpack('h', self.data.read(2))[0]
                if strlen == 0: break
                output += [self.data.read(strlen)]
            except: break;
        return output

    def Close(self):
        self.sock.close()

有任何想法吗?

编辑:我做了一些更改后,给了我以下错误:

query = Query(ip,port)

TypeError:“模块”对象不可调用

我基本上已经更改了 ip 和端口的位置,将其移出 serverinfo 命令。

    from util import Query
from util import hook

ip = "78.129.221.58"
port = 7777
query = Query(ip,port)
info = query.GetInformation()

@hook.command
def serverinfo(inp,ip="",port="",say=None):
    say(info)
if info['players'] <= 100:
    say(query.GetPlayers())
    say(query.GetDetailedPlayers())
else: say('can\' get players because players are above 100')
say(query.Ping())
query.Close()
4

2 回答 2

0

有问题的行是这一行:

query = Query(ip,port)

如果使用命令行参数初始化失败或传入的参数不足,ip将不会初始化导致上述错误。

此外,测试脚本的更好方法是这样的:

def main():
    if len(sys.argv) >= 3:
        ip = str(sys.argv[1])
        port = int(sys.argv[2])
        query = Query(ip,port)
        # start using query
    else:
        raise Exception("Insufficient args passed in")
if __name__ == '__main__':
    main()

引发异常/错误或打印出某些内容可以保证您知道传入的参数不足。另外,也许将所有代码移出到某个函数的开放位置?

于 2013-01-06T07:05:51.563 回答
0

尝试将此添加到 python 代码的开头:

ip = "78.129.221.58"
port = 7777

尝试

query = Query.Query(ip, port)
于 2013-01-06T07:11:50.100 回答