示例#1
0
 def restart_redis(self):
     try:
         subprocess.run("sudo service redis restart",
                        shell=True,
                        check=True)
     except subprocess.CalledProcessError:
         Logger.error("重启redis失败")
示例#2
0
 def restart_ssh(self):
     try:
         subprocess.run("sudo /etc/init.d/sshresart",
                        shell=True,
                        check=True)
     except subprocess.CalledProcessError:
         Logger.error("重启失败")
示例#3
0
 def install_mosquitto(self):
     Logger.info("准备安装Mosquitto Broker")
     try:
         subprocess.run("sudo apt install mosquitto mosquitto-clients",
                        shell=True,
                        check=True)
         mqtt_user_name = input("请输入MQTT用户名:")
         subprocess.run("sudo mosquitto_passwd -c /etc/mosquitto/passwd " +
                        mqtt_user_name,
                        shell=True,
                        check=True)
         try:
             with open("/etc/mosquitto/conf.d/default.conf", "w+") as f:
                 f.write("allow_anonymous false\n"
                         "password_file /etc/mosquitto/pwfile\n"
                         "listener 1883\n")
                 Logger.info("写入MQTT配置成功!")
         except FileNotFoundError:
             Logger.error("未发现mqtt配置文件,请重新安装...")
     except subprocess.CalledProcessError:
         Logger.error("安装失败,请重新安装")
     finally:
         Logger.info("重启MQTT服务")
         subprocess.run("sudo systemctl restart mosquitto",
                        shell=True,
                        check=True)
示例#4
0
 def install_redis(self):
     try:
         subprocess.run("sudo apt install redis-server",
                        shell=True,
                        check=True)
     except subprocess.CalledProcessError:
         Logger.error("安装redis失败")
示例#5
0
    def startListening(self):
        # _thread.start_new_thread(self.makeItems, ())
        try:
            self.clientSocket.connect((self.IP, self.PORT))
            self.hasConnected = True
            self.clientSocket.send(str.encode(f'USERNAME<>{Username}'))
            Logger.log('Connected to server correctly.')
            # self.clientSocket.send(str.encode('CLIENT_INFORMATION<>' + str(clientInformation)))
        except Exception as e:
            self.notificationText.set('Could not connect to the local server.')
            self.Window.after(3000, lambda: self.notificationText.set(''))
            Logger.error(e)
            Logger.log('Failed to connect to the local game server.', 'ERROR')
        if self.hasConnected:
            while True:
                try:
                    receive_data = self.clientSocket.recv(35)
                    # print(receive_data.decode())
                    arguments = receive_data.decode().split('<>')
                    if arguments[0] == 'CONN_ERROR':
                        Logger.log('Server rejected connection based on client information.', 'DISCONNECT')
                        Logger.log(arguments[1])
                        break
                    elif arguments[0] == 'CONN_SUCCESS':
                        Logger.log(arguments[1])
                    elif arguments[0] == 'SERVER_INFORMATION':
                        serverInfo = ast.literal_eval(str(arguments[1]))
                        serverData = []
                        for field in ['Server Name', 'Uptime', 'Minimum Version', 'Server Version']:
                            serverData.append(serverInfo['Server Information'][field])
                            Logger.log(f'{field}: {str(serverInfo["Server Information"][field])}', 'SERVER')
                    elif arguments[0] == 'ITEM':
                        # print(receive_data.decode())
                        posArgs2 = receive_data.decode().strip('ITEM<>')
                        posArgs2 = posArgs2.split(',')
                        self.createItem(float(posArgs2[0]), float(posArgs2[1]))
                    elif arguments[0] == 'USER_LIST':
                        all_users = arguments[1].split(';')
                        for user in all_users:
                            if user is not '':
                                Logger.log(user, 'USER LIST')
                    elif arguments[0] == 'BALL':
                        posArgs3 = receive_data.decode().strip('BALL<>')
                        posArgs3 = posArgs3.split(',')
                        self.drawBullet(posArgs3[0], posArgs3[1], posArgs3[2], posArgs3[3], posArgs3[4])
                    elif arguments[0] == 'POSITION':
                        # print(receive_data.decode())
                        userName = arguments[1]
                        if userName != Username:
                            posArgs = receive_data.decode().strip('POSITION<>' + userName)
                            posArgs = posArgs.split(',')
                            self.setOLoc(posArgs[0], posArgs[1], userName)

                except Exception as e:
                    self.notificationText.set('Lost connection to the game server.')
                    self.Window.after(3000, lambda: self.notificationText.set(''))
                    Logger.error(e)
                    Logger.log('Lost connection to the game server or received invalid data.', 'ERROR')
                    break
示例#6
0
 def send(self, m):
     print('HOST', m)
     try:
         for connectedSocket in self.LIST:
             if connectedSocket != self.gameSocket:
                 connectedSocket.send(str.encode(str(self.randomID) + m))
     except Exception as error:
         Logger.error(error)
示例#7
0
 def connect(self):
     try:
         self.gameSocket.connect(('127.0.0.1', 6969))
         self.gameSocket.settimeout(None)
         return True
     except Exception as e:
         Logger.error(e)
         return False
示例#8
0
 def set_timezone(self):
     try:
         Logger.info("开始设置中国时区")
         subprocess.run("timedatectl set-timezone Asia/Shanghai",
                        shell=True,
                        check=True)
         subprocess.run("date -R", shell=True)
     except subprocess.CalledProcessError:
         Logger.error("时区设置错误")
示例#9
0
 def broadcast(self, message):
     global tempMsg
     try:
         for connectedSocket in self.LIST:
             if connectedSocket != self.serverSocket:
                 connectedSocket.send(str.encode(message))
         if message != tempMsg:
             Logger.log(message.rstrip().lstrip(), 'BROADCAST')
             tempMsg = message
     except Exception as error:
         Logger.error(error)
示例#10
0
 def update_source_list(self):
     Logger.info("准备更新软件包列表")
     try:
         subprocess.run("sudo apt update", shell=True, check=True)
         Logger.info("软件包列表更新完毕")
         Logger.info("是否更新软件(y or n, default: n)")
         confirm = input("(不输入可直接回车使用默认值)>")
         if confirm == "y" or confirm == "Y":
             self.upgrade_software()
     except subprocess.CalledProcessError:
         Logger.error("更新失败")
示例#11
0
    def get_python_version(self):
        try:
            Logger.info("Python3版本")
            subprocess.run("python3 -V", shell=True, check=True)
        except subprocess.CalledProcessError:
            Logger.error("没有找到Python3")

        try:
            Logger.info("Python2版本")
            subprocess.run("python2 -V", shell=True, check=True)
        except subprocess.CalledProcessError:
            Logger.error("没有找到Python2")
示例#12
0
    def collisionDetection(self):
        while True:
            time.sleep(1 / self.tickrate * 1.5)
            while self.bullet is not None:

                try:

                    diffX = self.locations[self.locIndex][0] - 1.00
                    diffY = self.locations[self.locIndex][1] - 1.00

                    if diffX < 0:
                        diffX = diffX * -1

                    if diffY < 0:
                        diffY = diffY * -1

                    diffXItem = float(self.newLX) - 1
                    diffYItem = float(self.newLY) - 1

                    if 1 < float(self.newLX) or float(self.newLX) < 0:
                        self.bullet.place_forget()
                        self.bullet = None
                        print('bullet out of bounds')
                    if 1 < float(self.newLY) or float(self.newLY) < 0:
                        self.bullet.place_forget()
                        self.bullet = None
                        print('bullet out of bounds')

                    if diffXItem < 0:
                        diffXItem = diffXItem * -1

                    if diffYItem < 0:
                        diffYItem = diffYItem * -1

                    # print(diffX, diffY, diffXItem, diffYItem)

                    if self.bullet.cget("foreground") != self.playerColours[
                            self.locIndex]:

                        if diffXItem - 0.08 < diffX < diffXItem + 0.08:
                            if diffYItem - 0.08 < diffY < diffYItem + 0.08:
                                self.notificationText.set('You were hit!')
                                self.bullet.place_forget()
                                self.bullet = None
                                self.Window.after(
                                    3000,
                                    lambda: self.notificationText.set(''))

                except Exception as e:
                    Logger.error(e)
示例#13
0
    def start_capture(self, input_path: str) -> (int, int):
        """ Begin the video capture, returning the estimated frame length and rate. """

        if not os.path.exists(input_path):
            message = "The specified input file {} does not exist.".format(
                input_path)
            Logger.error(message)
            raise FileNotFoundError(message)

        self.cap = cv2.VideoCapture(input_path)
        self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
        frame_length = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
        frame_rate = int(self.cap.get(cv2.CAP_PROP_FPS))
        return frame_length, frame_rate
示例#14
0
 def listen(self):
     while True:
         try:
             data = self.gameSocket.recv(40, ).decode()
         except Exception as e:
             Logger.error(e)
             break
         if data:
             print(data)
             arguments = data.split(';')
             if arguments[0] != str(self.randomID):
                 if arguments[1] == str(self.gameInstance.getPage()):
                     self.gameInstance.getPlayer().setLocation(
                         round(float(arguments[2]), 2),
                         round(float(arguments[3]), 2))
                 else:
                     self.gameInstance.getPlayer().hide()
示例#15
0
    def install_java(self):
        try:
            # 文件存在不需要重复下载
            if os.path.exists('jdk-8u231-linux-x64.tar.gz'):
                subprocess.run('sudo mkdir /usr/lib/jvm',
                               shell=True,
                               check=True)
                subprocess.run(
                    'sudo tar -zxvf jdk-8u231-linux-x64.tar.gz -C /usr/lib/jvm'
                )
            else:
                Logger.info('开始下载jdk8')
                subprocess.run(
                    'sudo wget https://github.com/morestart/auto_deploy/releases/download/1.0/jdk-8u231'
                    '-linux-x64.tar.gz',
                    shell=True,
                    check=True)
                subprocess.run('sudo mkdir /usr/lib/jvm',
                               shell=True,
                               check=True)
                subprocess.run(
                    'sudo tar -zxvf jdk-8u231-linux-x64.tar.gz -C /usr/lib/jvm'
                )

                with open('sudo nano ~/.bashrc', 'a+') as f:
                    f.writelines('\n')
                    f.writelines('export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_231')
                    f.writelines('\n')
                    f.writelines('export JRE_HOME=${JAVA_HOME}/jre')
                    f.writelines('\n')
                    f.writelines(
                        'export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib')
                    f.writelines('\n')
                    f.writelines('export PATH=${JAVA_HOME}/bin:$PATH')
                subprocess.run('source ~/.bashrc', shell=True)
                subprocess.run(
                    'sudo update-alternatives --install /usr/bin/java java '
                    '/usr/lib/jvm/jdk1.8.0_231/bin/java 300',
                    shell=True)
                subprocess.run('java -version', shell=True)

        except subprocess.CalledProcessError:
            Logger.error('下载jdk8失败')
示例#16
0
 def listen(self):
     while True:
         try:
             read_sockets, write_sockets, error_sockets = select.select(
                 self.LIST, [], [])
             for sock in read_sockets:
                 if sock == self.gameSocket:
                     sockfd, address = self.gameSocket.accept()
                     self.LIST.append(sockfd)
                     Logger.log(
                         f'Client [{address[0]}:{address[1]}] connected to the server.',
                         'CONNECT')
                 else:
                     try:
                         receivedData = sock.recv(40, ).decode()
                     except:
                         try:
                             try:
                                 disconnected_user = self.connectedUsers[
                                     address]
                                 del self.connectedUsers[address]
                             except:
                                 disconnected_user = '******'
                             Logger.log(
                                 f'Client [{address[0]}:{address[1]}] ({disconnected_user}) disconnected from the server.',
                                 'DISCONNECT')
                         except Exception as error:
                             Logger.error(error)
                         sock.close()
                         self.LIST.remove(sock)
                         continue
                     if receivedData:
                         arguments = receivedData.split(';')
                         if arguments[0] != str(self.randomID):
                             if arguments[1] == str(
                                     self.gameInstance.getPage()):
                                 self.otherPlayer.setLocation(
                                     round(float(arguments[2]), 2),
                                     round(float(arguments[3]), 2))
                             else:
                                 self.otherPlayer.hide()
         except Exception as error:
             Logger.error(error)
示例#17
0
    def install_ssh(self):
        try:
            Logger.info("开始安装ssh-server")
            subprocess.run("sudo apt install openssh-server",
                           shell=True,
                           check=True)

            try:
                Logger.info("启动ssh-server")
                subprocess.run("sudo /etc/init.d/ssh start",
                               shell=True,
                               check=True)
                Logger.info("写入自启配置")
                # 写入自启动配置
                with open("/etc/rc.local", 'a+') as f:
                    f.writelines('\n')
                    f.writelines('/etc/init.d/ssh start')
                Logger.info("自启配置写入成功")
            except subprocess.CalledProcessError:
                Logger.error("启动失败")

        except subprocess.CalledProcessError:
            Logger.error("安装失败,请重新安装")
示例#18
0
 def start_emqx(self):
     try:
         subprocess.run("sudo emqx start", shell=True, check=True)
     except subprocess.CalledProcessError:
         Logger.error('启动失败')
示例#19
0
 def get_emq_status(self):
     try:
         subprocess.run("sudo emqx_ctl status", shell=True, check=True)
     except subprocess.CalledProcessError:
         Logger.error('查询状态失败')
示例#20
0
 def receive(self):
     Logger.log(f'Started listening for connections at [{self.EXTERNAL_IP}:{self.PORT}]')
     Logger.log(f'Accepting local connections at [127.0.0.1:{self.PORT}]')
     while self.serverStatus:
         try:
             read_sockets, write_sockets, error_sockets = select.select(self.LIST, [], [])
             for sock in read_sockets:
                 if sock == self.serverSocket:
                     sockfd, address = self.serverSocket.accept()
                     self.LIST.append(sockfd)
                     Logger.log(f'Client [{address[0]}:{address[1]}] connected to the server.', 'CONNECT')
                 else:
                     try:
                         receivedData = sock.recv(self.BUFFER_SIZE, )
                     except:
                         try:
                             try:
                                 disconnected_user = self.connectedUsers[address]
                                 del self.connectedUsers[address]
                                 del self.extendedUsers[disconnected_user]
                             except:
                                 disconnected_user = '******'
                             Logger.log(f'Client [{address[0]}:{address[1]}] ({disconnected_user}) disconnected from the server.', 'DISCONNECT')
                             self.broadcast(f'({disconnected_user}) left the server')
                             self.broadcast(f'LEFT<>{disconnected_user}')
                         except Exception as error:
                             Logger.error(error)
                         sock.close()
                         self.LIST.remove(sock)
                         continue
                     if receivedData:
                         arguments = receivedData.decode().split('<>')
                         if 'DISCONNECT' in receivedData.decode():
                             try:
                                 disconnected_user = self.connectedUsers[address]
                                 del self.connectedUsers[address]
                                 del self.extendedUsers[disconnected_user]
                             except:
                                 disconnected_user = '******'
                             Logger.log(f'Client [{address[0]}:{address[1]}] ({disconnected_user}) disconnected from the server.', 'DISCONNECT')
                             Logger.log(f'Received quit command from client [{address[0]}:{address[1]}]')
                             self.broadcast(f'({disconnected_user}) left the server')
                             self.broadcast(f'LEFT<>{disconnected_user}')
                             sock.close()
                             self.LIST.remove(sock)
                             continue
                         elif arguments[0] == 'USERNAME':
                             self.connectedUsers[address] = arguments[1]
                             self.extendedUsers[arguments[1]] = sock
                             Logger.log(f'Allowed connection from [{address[0]}:{address[1]}] ({arguments[1]})', 'CONNECT')
                         elif arguments[0] == 'CONNECT4':
                             self.handle_game_commands(arguments, sock, self.connectedUsers[address])
                         elif arguments[0] == 'ONLINE':
                             userList = ''
                             for user in self.connectedUsers:
                                 userList = userList + self.connectedUsers[user] + ';'
                             sock.send(str.encode('USER_LIST<>' + userList))
                             Logger.log(f'[{address[0]}:{address[1]}] ({self.connectedUsers[address]}) requested user list.')
                             Logger.log(f'Current connected users: {userList.replace(";", " ")}')
                         elif arguments[0] == 'CLIENT_INFORMATION':
                             Logger.log(f'Received client information from [{address[0]}:{address[1]}]')
                             clientInformation = ast.literal_eval(arguments[1])
                             clientData = []
                             for field in ['Username', 'Version', 'Rank']:
                                 clientData.append(str([clientInformation['Client Information'][field]][0]))
                             if clientData[0] == '' or clientData[0] == ' ':
                                 sock.send(b'CONN_ERROR<>Invalid username (username not allowed)')
                                 Logger.log(f'Rejected connection from [{address[0]}:{address[1]}] due to invalid username.')
                                 sock.close()
                                 self.LIST.remove(sock)
                             else:
                                 userListByName = []
                                 for user in self.connectedUsers:
                                     userListByName.append(self.connectedUsers[user])
                                 if clientData[0] in userListByName:
                                     sock.send(b'CONN_ERROR<>A user with that name is already connected (use a different username)')
                                     Logger.log(f'Rejected connection from [{address[0]}:{address[1]}] ({clientData[0]}) due to duplicate username.', 'DISCONNECT')
                                     sock.close()
                                     self.LIST.remove(sock)
                                 else:
                                     if float(clientData[1]) < self.MIN_VERSION:
                                         sock.send(str.encode(f'CONN_ERROR<>Client is out of date (latest version is {str(self.MIN_VERSION)})'))
                                         Logger.log(f'Rejected connection from [{address[0]}:{address[1]}] ({clientData[0]}) due to outdated client [{clientData[1]}]', 'DISCONNECT')
                                         sock.close()
                                         self.LIST.remove(sock)
                                     else:
                                         self.connectedUsers[address] = clientData[0]
                                         self.extendedUsers[clientData[0]] = sock
                                         sock.send(b'CONN_SUCCESS<>Successfully connected to the server.')
                                         Logger.log(f'Allowed connection from [{address[0]}:{address[1]}] ({clientData[0]}) [{clientData[1]}]', 'CONNECT')
                                         time.sleep(0.10)
                                         start_dt = datetime.strptime(self.serverInformation['Server Information']['Uptime'], '%H:%M:%S')
                                         end_dt = datetime.strptime(datetime.now().strftime('%H:%M:%S'), '%H:%M:%S')
                                         diff = (end_dt - start_dt)
                                         serverInformationTemp = self.serverInformation
                                         serverInformationTemp['Server Information']['Uptime'] = str(diff)
                                         time.sleep(0.10)
                                         sock.send(str.encode(f'SERVER_INFORMATION<>{str(serverInformationTemp)}'))
                                         Logger.log(f'Sent server information to client [{address[0]}:{address[1]}] ({clientData[0]})')
                                         self.serverInformation['Server Information']['Uptime'] = self.LAUNCH_TIME
                         else:
                             self.broadcast(receivedData.decode())
         except Exception as error:
             Logger.error(error)
示例#21
0
                    challengedSocket.send(str.encode('CONNECT4<>CHALLENGED<>' + name))
                else:
                    sender.send(b'GAME_ERROR<>MEMBER_NOT_FOUND')
            elif args[1] == 'ACCEPTED':
                time.sleep(0.1)
                challengedSocket = self.extendedUsers[args[2]]
                challengedSocket.send(str.encode('<>'.join(args)))

    def broadcast(self, message):
        global tempMsg
        try:
            for connectedSocket in self.LIST:
                if connectedSocket != self.serverSocket:
                    connectedSocket.send(str.encode(message))
            if message != tempMsg:
                Logger.log(message.rstrip().lstrip(), 'BROADCAST')
                tempMsg = message
        except Exception as error:
            Logger.error(error)


tempMsg = ''


if __name__ == '__main__':
    try:
        Server = GameServer()
        Server.run()
    except Exception as e:
        Logger.error(e)
示例#22
0
class CommandManager:
    PRIVATE_CHANNEL = "priv"
    ORG_CHANNEL = "org"
    PRIVATE_MESSAGE = "msg"

    def __init__(self):
        self.handlers = collections.defaultdict(list)
        self.logger = Logger("command_manager")
        self.channels = {}
        self.ignore_regexes = [
            re.compile(" is AFK \(Away from keyboard\) since ", re.IGNORECASE),
            re.compile("I am away from my keyboard right now", re.IGNORECASE),
            re.compile("Unknown command or access denied!", re.IGNORECASE),
            re.compile("I am responding", re.IGNORECASE),
            re.compile("I only listen", re.IGNORECASE),
            re.compile("Error!", re.IGNORECASE),
            re.compile("Unknown command input", re.IGNORECASE),
            re.compile("You have been auto invited", re.IGNORECASE),
        ]

    def inject(self, registry):
        self.db = registry.get_instance("db")
        self.util: Util = registry.get_instance("util")
        self.access_manager: AccessManager = registry.get_instance("access_manager")
        self.bot: Mangopie = registry.get_instance("mangopie")
        self.character_manager: CharacterManager = registry.get_instance("character_manager")
        self.setting_manager: SettingManager = registry.get_instance("setting_manager")
        self.command_alias_manager = registry.get_instance("command_alias_manager")

    def pre_start(self):
        self.bot.add_packet_handler(server_packets.PrivateMessage.id, self.handle_private_message)
        self.bot.add_packet_handler(server_packets.PrivateChannelMessage.id, self.handle_private_channel_message)
        self.register_command_channel("Private Message", self.PRIVATE_MESSAGE)
        self.register_command_channel("Org Channel", self.ORG_CHANNEL)
        self.register_command_channel("Private Channel", self.PRIVATE_CHANNEL)

    def start(self):
        # process decorators
        for _, inst in Registry.get_all_instances().items():
            for name, method in get_attrs(inst).items():
                if hasattr(method, "command"):
                    cmd_name, params, access_level, description, help_file, sub_command = getattr(method, "command")
                    handler = getattr(inst, name)
                    module = self.util.get_module_name(handler)
                    help_text = self.get_help_file(module, help_file)
                    self.register(handler, cmd_name, params, access_level, description, module, help_text, sub_command)

    def register(self, handler, command, params, access_level, description, module, help_text=None, sub_command=None):
        command = command.lower()
        if sub_command:
            sub_command = sub_command.lower()
        else:
            sub_command = ""
        access_level = access_level.lower()
        module = module.lower()
        command_key = self.get_command_key(command, sub_command)

        if help_text is None:
            help_text = self.generate_help(command, description, params)

        if not self.access_manager.get_access_level_by_label(access_level):
            self.logger.error("Could not add command '%s': could not find access level '%s'" % (command, access_level))
            return

        for channel, label in self.channels.items():
            row = self.db.find('command_config', {"command": command, "sub_command": sub_command, 'channel': channel})

            if row is None:
                # add new command commands
                self.db.insert('command_config',
                               {'command': command, 'sub_command': sub_command, 'access_level': access_level,
                                'channel': channel, 'module': module, 'verified': 1, 'enabled': 1})

            elif 'verified' in row and row['verified']:
                if row['module'] != module:
                    self.logger.warning("module different for different forms of command '%s' and sub_command '%s'" % (
                        command, sub_command))
            else:
                # mark command as verified
                self.db.update('command_config',
                               {'module': module, 'command': command, 'channel': channel, 'access_level': access_level,
                                'sub_command': sub_command},
                               {'verified': 1})

        # save reference to command handler
        r = re.compile(self.get_regex_from_params(params), re.IGNORECASE)
        self.handlers[command_key].append(
            {"regex": r, "callback": handler, "help": help_text, "description": description, "params": params})

    def handle_private_message(self, packet: server_packets.PrivateMessage):
        # since the command symbol is not required for private messages,
        # the command_str must have length of at least 1 in order to be valid,
        # otherwise it is ignored
        if len(packet.message) < 1 or not self.bot.is_ready():
            return

        for regex in self.ignore_regexes:
            if regex.search(packet.message):
                return

        if packet.message[:1] == '!':
            command_str = packet.message[1:]
        else:
            command_str = packet.message

        self.process_command(
            command_str,
            "msg",
            packet.char_id,
            lambda msg: self.bot.send_private_message(packet.char_id, msg))

    def handle_private_channel_message(self, packet: server_packets.PrivateChannelMessage):
        # since the command symbol is required in the private channel,
        # the command_str must have length of at least 2 in order to be valid,
        # otherwise it is ignored
        if len(packet.message) < 2:
            return

        symbol = packet.message[:1]
        command_str = packet.message[1:]
        if symbol == self.setting_manager.get(
                "symbol").get_value() and packet.private_channel_id == self.bot.char_id:
            self.process_command(
                command_str,
                "priv",
                packet.char_id,
                lambda msg: self.bot.send_private_channel_message(msg))

    def process_command(self, message: str, channel: str, char_id, reply):
        try:
            command_str, command_args = self.get_command_parts(message)

            # check for command alias
            command_alias = self.command_alias_manager.check_for_alias(command_str)

            if command_alias:
                command_str, command_args = self.get_command_parts(
                    command_alias + " " + command_args if command_args else command_alias)

            cmd_configs = self.get_command_configs(command_str, channel, 1)
            cmd_configs = list(cmd_configs)
            if cmd_configs:
                # given a list of cmd_configs that are enabled, see if one has regex that matches incoming command_str
                cmd_config, matches, handler = self.get_matches(cmd_configs, command_args)
                if matches:
                    if self.access_manager.check_access(char_id, cmd_config['access_level']):
                        sender = MapObject(
                            {"name": self.character_manager.resolve_char_to_name(char_id), "char_id": char_id})
                        handler["callback"](channel, sender, reply, self.process_matches(matches, handler["params"]))
                    else:
                        self.access_denied_response(char_id, cmd_config, reply)
                else:
                    # handlers were found, but no handler regex matched
                    help_text = self.get_help_text(char_id, command_str, channel)
                    if help_text:
                        reply(self.format_help_text(command_str, help_text))
                    else:
                        reply("Error! Invalid syntax.")
            else:
                reply("Error! Unknown command.")
        except Exception as e:
            self.logger.error("error processing command: %s" % message, e)
            reply("There was an error processing your request.")

    def get_help_text(self, char, command_str, channel):
        data = self.db.find_all('command_config', {'command': command_str, 'channel': channel, 'enabled': 1})
        # filter out commands that character does not have access level for
        data = filter(lambda row: self.access_manager.check_access(char, row['access_level']), data)

        def read_help_text(row):
            command_key = self.get_command_key(row['command'], row['sub_command'])
            return filter(lambda x: x is not None, map(lambda handler: handler["help"], self.handlers[command_key]))

        content = "\n\n".join(flatmap(read_help_text, data))
        return content if content else None

    def get_help_file(self, module, help_file):
        if help_file:
            try:
                help_file = "./" + module.replace(".", "/") + "/" + help_file
                with open(help_file) as f:
                    return f.read().strip()
            except FileNotFoundError as e:
                self.logger.error("Error reading help file", e)
        return None

    def format_help_text(self, topic, help_text):
        return ChatBlob("Help (" + topic + ")", help_text)

    def generate_help(self, command, description, params):
        return description + ":\n" + "<tab><symbol>" + command + " " + " ".join(map(lambda x: x.get_name(), params))

    def access_denied_response(self, char_id, cmd_config, reply):
        reply("Error! Access denied.")

    def get_command_key(self, command, sub_command):
        if sub_command:
            return command + ":" + sub_command
        else:
            return command

    def get_command_key_parts(self, command_str):
        parts = command_str.split(":", 1)
        if len(parts) == 2:
            return parts[0], parts[1]
        else:
            return parts[0], ""

    def get_matches(self, cmd_configs, command_args):
        if command_args:
            command_args = " " + command_args

        for row in cmd_configs:
            command_key = self.get_command_key(row['command'], row['sub_command'])
            handlers = self.handlers[command_key]
            for handler in handlers:
                matches = handler["regex"].match(command_args)
                if matches:
                    return row, matches, handler
        return None, None, None

    def process_matches(self, matches, params):
        groups = list(matches.groups())

        processed = []
        for param in params:
            processed.append(param.process_matches(groups))
        return processed

    def format_matches(self, command_args, matches):
        # convert matches to list
        m = list(matches.groups())
        m.insert(0, command_args)

        # strip leading spaces for each group, if they group exists
        return list(map(lambda x: x[1:] if x else x, m))

    def get_command_parts(self, message):
        parts = message.split(" ", 1)
        if len(parts) == 2:
            return parts[0].lower(), parts[1]
        else:
            return parts[0].lower(), ""

    def get_command_configs(self, command, channel=None, enabled=1, sub_command=None):
        query = {"command": command}
        if channel:
            query['channel'] = channel
        if enabled:
            query['enabled'] = enabled
        if sub_command:
            query['sub_command'] = sub_command
        return self.db.find_all('command_config', query)

    def get_handlers(self, command_key):
        return self.handlers.get(command_key, None)

    def register_command_channel(self, label, value):
        if value in self.channels:
            self.logger.error("Could not register command channel '%s': command channel already registered" % value)
            return

        self.logger.debug("Registering command channel '%s'" % value)
        self.channels[value] = label

    def is_command_channel(self, channel):
        return channel in self.channels

    def get_regex_from_params(self, params):
        # params must be wrapped with line-beginning and line-ending anchors in order to match
        # when no params are specified (eg. "^$")
        return "^" + "".join(map(lambda x: x.get_regex(), params)) + "$"
示例#23
0
class Cutout:
    def __init__(self, survey, position, radius, **kwargs):
        self.survey = survey
        self.position = position
        self.ra = self.position.ra.to_value(u.deg)
        self.dec = self.position.dec.to_value(u.deg)
        self.radius = radius
        self.basesurvey = kwargs.get('basesurvey', 'racsI')
        self.psf = kwargs.get('psf')
        self.cmap = kwargs.get('cmap', 'gray_r')
        self.color = 'k' if self.cmap == 'hot' else 'black'
        self.band = kwargs.get('band', 'g')

        level = 'DEBUG' if kwargs.get('verbose') else 'INFO'
        self.logger = Logger(__name__, kwargs.get('log'),
                             streamlevel=level).logger
        self.logger.propagate = False

        self.kwargs = kwargs

        try:
            self._get_cutout()
        except Exception as e:
            msg = f"{survey} failed: {e}"
            raise FITSException(msg)
        finally:
            if 'racs' not in self.survey and 'vast' not in self.survey:
                self.plot_sources = False
                self.plot_neighbours = False

    def __repr__(self):
        return f"Cutout({self.survey}, ra={self.ra:.2f}, dec={self.dec:.2f})"

    def _get_source(self):
        try:
            pattern = re.compile(r'\S*(\d{4}[+-]\d{2}[AB])\S*')
            selpath = SURVEYS.loc[self.survey]['selavy']
            sel = glob.glob(f'{selpath}/*components.txt')
            sel = [s for s in sel if pattern.sub(r'\1', self.filepath) in s]

            if len(sel) > 1:
                df = pd.concat([pd.read_fwf(s, skiprows=[
                    1,
                ]) for s in sel])
            else:
                df = pd.read_fwf(sel[0], skiprows=[
                    1,
                ])
            coords = SkyCoord(df.ra_deg_cont, df.dec_deg_cont, unit=u.deg)
            d2d = self.position.separation(coords)
            df['d2d'] = d2d
            sources = df.iloc[np.where(d2d.deg < 0.5 * self.radius)[0]]
            sources = sources.sort_values('d2d', ascending=True)

            if any(sources.d2d < self.pos_err / 3600):
                self.source = sources.iloc[0]
                self.neighbours = sources.iloc[1:]
                self.plot_sources = True
            else:
                self.source = None
                self.neighbours = sources
                self.plot_sources = False

            self.plot_neighbours = self.kwargs.get('neighbours', True)

            self.logger.debug(f'Source: \n {self.source}')
            if len(self.neighbours) > 0:
                nn = self.neighbours.iloc[0]
                self.logger.debug(
                    f'Nearest neighbour coords: \n {nn.ra_deg_cont, nn.dec_deg_cont}'
                )
                self.logger.debug(
                    f'Nearest 5 Neighbours \n {self.neighbours.head()}')

        except IndexError:
            self.plot_sources = False
            self.plot_neighbours = False
            self.logger.warning('No nearby sources found.')

    def _get_cutout(self):

        if not os.path.exists(cutout_cache + self.survey):
            msg = f"{cutout_cache}{self.survey} cutout directory does not exist, creating."
            self.logger.info(msg)
            os.makedirs(cutout_cache + self.survey)

        if os.path.isfile(self.survey):
            self._get_local_cutout()
        elif 'racs' in self.survey or 'vast' in self.survey or 'vlass' in self.survey:
            self._get_local_cutout()
        elif self.survey == 'skymapper':
            self._get_skymapper_cutout()
        elif self.survey == 'panstarrs':
            self._get_panstarrs_cutout()
        elif self.survey == 'decam':
            self._get_decam_cutout()
        else:
            self._get_skyview_cutout()

    def _get_local_cutout(self):
        """Fetch cutout data via local FITS images (e.g. RACS / VLASS)."""

        fields = self._find_image()
        assert len(
            fields
        ) > 0, f"No fields located at {self.position.ra:.2f}, {self.position.dec:.2f}"
        closest = fields[fields.dist_field_centre ==
                         fields.dist_field_centre.min()].iloc[0]
        image_path = SURVEYS.loc[self.survey]['images']

        if self.survey == 'vlass':
            filepath = f'{closest.epoch}/{closest.tile}/{closest.image}/{closest.filename}'
            image_path = vlass_path
        elif 'racs' in self.survey:
            pol = self.survey[-1]
            if on_system == 'ada':
                filepath = f'RACS_test4_1.05_{closest.field}.fits'
            else:
                filepath = f'RACS_{closest.field}.EPOCH00.{pol}.fits'
        elif 'vast' in self.survey:
            pattern = re.compile(r'vastp(\dx*)([IV])')
            epoch = pattern.sub(r'\1', self.survey)
            pol = pattern.sub(r'\2', self.survey)
            filepath = f'VAST_{closest.field}.EPOCH0{epoch}.{pol}.fits'
        else:
            filepath = f'*{closest.field}*0.restored.fits'

        try:
            self.filepath = glob.glob(image_path + filepath)[0]
        except IndexError:
            raise FITSException(
                f'Could not match {self.survey} image filepath: \n{image_path + filepath}'
            )

        with fits.open(self.filepath) as hdul:
            self.header, data = hdul[0].header, hdul[0].data
            wcs = WCS(self.header, naxis=2)
            self.mjd = Time(self.header['DATE']).mjd

            try:
                cutout = Cutout2D(data[0, 0, :, :],
                                  self.position,
                                  self.radius * u.deg,
                                  wcs=wcs)
            except IndexError:
                cutout = Cutout2D(data,
                                  self.position,
                                  self.radius * u.deg,
                                  wcs=wcs)
            self.data = cutout.data * 1000
            self.wcs = cutout.wcs

        if 'racs' in self.survey or 'vast' in self.survey:
            self.pos_err = SURVEYS.loc[self.basesurvey].pos_err
            self._get_source()
        else:
            # Probably using vlass, yet to include aegean catalogs
            self.plot_sources = False
            self.plot_neighbours = False

    def _get_panstarrs_cutout(self):
        """Fetch cutout data via PanSTARRS DR2 API."""
        path = cutout_cache + 'panstarrs/{}_{}arcmin_{}_{}.fits'.format(
            self.band,
            '{:.3f}',
            '{:.3f}',
            '{:.3f}',
        )
        imgpath = path.format(self.radius * 60, self.ra, self.dec)
        if not os.path.exists(imgpath):
            pixelrad = int(self.radius * 120 * 120)
            service = "https://ps1images.stsci.edu/cgi-bin/ps1filenames.py"
            url = (
                f"{service}?ra={self.ra}&dec={self.dec}&size={pixelrad}&format=fits"
                f"&filters=grizy")
            table = Table.read(url, format='ascii')

            msg = f"No PS1 image at {self.position.ra:.2f}, {self.position.dec:.2f}"
            assert len(table) > 0, msg

            urlbase = (
                f"https://ps1images.stsci.edu/cgi-bin/fitscut.cgi?"
                f"ra={self.ra}&dec={self.dec}&size={pixelrad}&format=fits&red="
            )

            flist = ["yzirg".find(x) for x in table['filter']]
            table = table[np.argsort(flist)]

            for row in table:
                self.mjd = row['mjd']
                filt = row['filter']
                url = urlbase + row['filename']
                path = cutout_cache + 'panstarrs/{}_{}arcmin_{}_{}.fits'.format(
                    filt,
                    '{:.3f}',
                    '{:.3f}',
                    '{:.3f}',
                )
                path = path.format(self.radius * 60, self.ra, self.dec)

                img = requests.get(url, allow_redirects=True)

                if not os.path.exists(path):
                    with open(path, 'wb') as f:
                        f.write(img.content)

        with fits.open(imgpath) as hdul:
            self.header, self.data = hdul[0].header, hdul[0].data
            self.wcs = WCS(self.header, naxis=2)

    def _get_skymapper_cutout(self):
        """Fetch cutout data via Skymapper API."""

        path = cutout_cache + self.survey + '/dr2_jd{:.3f}_{:.3f}arcmin_{:.3f}_{:.3f}'
        linka = 'http://api.skymapper.nci.org.au/aus/siap/dr2/'
        linkb = 'query?POS={:.5f},{:.5f}&SIZE={:.3f}&BAND=all&RESPONSEFORMAT=CSV'
        linkc = '&VERB=3&INTERSECT=covers'
        sm_query = linka + linkb + linkc

        link = linka + 'get_image?IMAGE={}&SIZE={}&POS={},{}&FORMAT=fits'

        table = requests.get(sm_query.format(self.ra, self.dec, self.radius))
        df = pd.read_csv(io.StringIO(table.text))
        assert len(
            df
        ) > 0, f'No Skymapper image at {self.position.ra:.2f}, {self.position.dec:.2f}'

        df = df[df.band == 'z']
        self.mjd = df.iloc[0]['mjd_obs']
        link = df.iloc[0].get_image

        img = requests.get(link)

        path = path.format(self.mjd, self.radius * 60, self.ra, self.dec)

        if not os.path.exists(path):
            with open(path, 'wb') as f:
                f.write(img.content)

        with fits.open(path) as hdul:
            self.header, self.data = hdul[0].header, hdul[0].data
            self.wcs = WCS(self.header, naxis=2)

    def _get_decam_cutout(self):
        """Fetch cutout data via DECam LS API."""
        size = int(self.radius * 3600 / 0.262)
        if size > 512:
            size = 512
            maxradius = size * 0.262 / 3600
            self.logger.warning(
                f"Using maximum DECam LS cutout radius of {maxradius:.3f} deg")

        link = f"http://legacysurvey.org/viewer/fits-cutout?ra={self.ra}&dec={self.dec}"
        link += f"&size={size}&layer=dr8&pixscale=0.262&bands={self.band}"
        img = requests.get(link)

        path = cutout_cache + self.survey + '/dr8_jd{:.3f}_{:.3f}arcmin_{:.3f}_{:.3f}_{}band'
        path = path.format(self.mjd, self.radius * 60, self.ra, self.dec,
                           self.band)
        if not os.path.exists(path):
            with open(path, 'wb') as f:
                f.write(img.content)

        with fits.open(path) as hdul:
            self.header, self.data = hdul[0].header, hdul[0].data
            self.wcs = WCS(self.header, naxis=2)

        msg = f"No DECam LS image at {self.position.ra:.2f}, {self.position.dec:.2f}"
        assert self.data is not None, msg

    def _get_skyview_cutout(self):
        """Fetch cutout data via SkyView API."""

        sv = SkyView()
        path = cutout_cache + self.survey + '/{:.3f}arcmin_{:.3f}_{:.3f}.fits'
        path = path.format(self.radius * 60, self.ra, self.dec)
        progress = self.kwargs.get('progress', False)

        if not os.path.exists(path):
            skyview_key = SURVEYS.loc[self.survey].sv
            try:
                hdul = sv.get_images(position=self.position,
                                     survey=[skyview_key],
                                     radius=self.radius * u.deg,
                                     show_progress=progress)[0][0]
            except IndexError:
                raise FITSException('Skyview image list returned empty.')
            except ValueError:
                raise FITSException(
                    f'{self.survey} is not a valid SkyView survey.')
            except HTTPError:
                raise FITSException('No response from Skyview server.')

            with open(path, 'wb') as f:
                hdul.writeto(f)

        with fits.open(path) as hdul:
            self.header, self.data = hdul[0].header, hdul[0].data
            self.wcs = WCS(self.header, naxis=2)

            try:
                self.mjd = Time(self.header['DATE']).mjd
            except KeyError:
                try:
                    self.epoch = self.kwargs.get('epoch')
                    msg = "Could not detect epoch, PM correction disabled."
                    assert self.epoch is not None, msg
                    self.mjd = self.epoch if self.epoch > 3000 else Time(
                        self.epoch, format='decimalyear').mjd
                except AssertionError as e:
                    if self.kwargs.get('pm'):
                        self.logger.warning(e)
                    self.mjd = None

            self.data *= 1000

    def _find_image(self):
        """Return DataFrame of survey fields containing coord."""

        survey = self.survey.replace('I', '').replace('V', '')
        try:
            image_df = pd.read_csv(aux_path + f'{survey}_fields.csv')
        except FileNotFoundError:
            raise FITSException(f"Missing field metadata csv for {survey}.")

        beam_centre = SkyCoord(ra=image_df['cr_ra_pix'],
                               dec=image_df['cr_dec_pix'],
                               unit=u.deg)
        image_df['dist_field_centre'] = beam_centre.separation(
            self.position).deg

        pbeamsize = 1 * u.degree if self.survey == 'vlass' else 5 * u.degree
        return image_df[image_df.dist_field_centre < pbeamsize].reset_index(
            drop=True)

    def _obfuscate(self):
        """Remove all coordinates and identifying information."""
        lon = self.ax.coords[0]
        lat = self.ax.coords[1]
        lon.set_ticks_visible(False)
        lon.set_ticklabel_visible(False)
        lat.set_ticks_visible(False)
        lat.set_ticklabel_visible(False)
        lon.set_axislabel('')
        lat.set_axislabel('')

    def _plot_setup(self, fig, ax):
        """Create figure and determine normalisation parameters."""
        if ax:
            self.fig = fig
            self.ax = ax
        else:
            self.fig = plt.figure()
            self.ax = self.fig.add_subplot(111, projection=self.wcs)

        if self.kwargs.get('grid', True):
            self.ax.coords.grid(color='white', alpha=0.5)
        self.ax.set_xlabel('RA (J2000)')
        self.ax.set_ylabel('Dec (J2000)')

        if self.kwargs.get('title', True):
            self.ax.set_title(SURVEYS.loc[self.survey]['name'],
                              fontdict={
                                  'fontsize': 20,
                                  'fontweight': 10
                              })
        if self.kwargs.get('obfuscate', False):
            self._obfuscate()

        if self.kwargs.get('annotation'):
            color = 'white' if self.cmap == 'hot' else 'k'
            self.ax.text(0.05,
                         0.85,
                         self.kwargs.get('annotation'),
                         color=color,
                         weight='bold',
                         transform=self.ax.transAxes)

    def _add_cornermarker(self, ra, dec, span, offset):
        color = 'white' if self.cmap != 'gray_r' else 'r'
        cosdec = np.cos(np.radians(dec))
        raline = Line2D(
            xdata=[ra + offset / cosdec, ra + span / cosdec],
            ydata=[dec, dec],
            color=color,
            linewidth=2,
            path_effects=[pe.Stroke(linewidth=3, foreground='k'),
                          pe.Normal()],
            transform=self.ax.get_transform('world'))
        decline = Line2D(
            xdata=[ra, ra],
            ydata=[dec + offset, dec + span],
            color=color,
            linewidth=2,
            path_effects=[pe.Stroke(linewidth=3, foreground='k'),
                          pe.Normal()],
            transform=self.ax.get_transform('world'))
        self.ax.add_artist(raline)
        self.ax.add_artist(decline)

    def plot(self, fig=None, ax=None):
        """Plot survey data and position overlay."""
        self.sign = self.kwargs.get('sign', 1)
        self._plot_setup(fig, ax)
        self.data *= self.sign
        absmax = max(self.data.max(), self.data.min(), key=abs)
        self.logger.debug(f"Max flux in cutout: {absmax:.2f} mJy.")
        rms = np.sqrt(np.mean(np.square(self.data)))
        self.logger.debug(f"RMS flux in cutout: {rms:.2f} mJy.")

        assert (sum((~np.isnan(self.data).flatten())) > 0 and sum(self.data.flatten()) != 0), \
            f"No data in {self.survey}"

        if self.kwargs.get('maxnorm'):
            self.norm = ImageNormalize(self.data,
                                       interval=ZScaleInterval(),
                                       vmax=self.data.max(),
                                       clip=True)
        else:
            self.norm = ImageNormalize(self.data,
                                       interval=ZScaleInterval(contrast=0.2),
                                       clip=True)

        self.im = self.ax.imshow(self.data, cmap=self.cmap, norm=self.norm)

        if self.kwargs.get('bar', True):
            try:
                self.fig.colorbar(self.im,
                                  label=r'Flux Density (mJy beam$^{-1}$)',
                                  ax=self.ax)
            except UnboundLocalError:
                self.logger.error(
                    "Colorbar failed. Upgrade to recent version of astropy ")

        if self.psf:
            try:
                self.bmaj = self.header['BMAJ'] * 3600
                self.bmin = self.header['BMIN'] * 3600
                self.bpa = self.header['BPA']
            except KeyError:
                self.logger.warning('Header did not contain PSF information.')
                try:
                    self.bmaj = self.psf[0]
                    self.bmin = self.psf[1]
                    self.bpa = 0
                    self.logger.warning(
                        'Using supplied BMAJ/BMin. Assuming BPA=0')
                except ValueError:
                    self.logger.error('No PSF information supplied.')

            rhs = self.wcs.wcs_pix2world(self.data.shape[0], 0, 1)
            lhs = self.wcs.wcs_pix2world(0, 0, 1)

            # Offset PSF marker by the major axis in pixel coordinates
            try:
                cdelt = self.header['CDELT1']
            except KeyError:
                cdelt = self.header['CD1_1']
            beamavg = (self.bmaj + self.bmin) / 2
            beamsize_pix = beamavg / abs(cdelt) / 3600
            ax_len_pix = abs(lhs[0] - rhs[0]) / abs(cdelt) / 3600
            beam = self.wcs.wcs_pix2world(beamsize_pix, beamsize_pix, 1)
            self.beamx = beam[0]
            self.beamy = beam[1]

            self.beam = Ellipse((self.beamx, self.beamy),
                                self.bmin / 3600,
                                self.bmaj / 3600,
                                -self.bpa,
                                facecolor='white',
                                edgecolor='k',
                                transform=self.ax.get_transform('world'),
                                zorder=10)
            self.ax.add_patch(self.beam)

            # Optionally plot square around the PSF
            # Set size to greater of 110% PSF size or 10% ax length
            if self.kwargs.get('beamsquare', False):
                boxsize = max(beamsize_pix * 1.15, ax_len_pix * .1)
                offset = beamsize_pix - boxsize / 2
                self.square = Rectangle(
                    (offset, offset),
                    boxsize,
                    boxsize,
                    facecolor='white',
                    edgecolor='k',
                    # transform=self.ax.get_transform('world'),
                    zorder=5)
                self.ax.add_patch(self.square)

        if self.plot_sources:
            if self.kwargs.get('corner'):
                self._add_cornermarker(
                    self.source.ra_deg_cont, self.source.dec_deg_cont,
                    self.kwargs.get('corner_span', 20 / 3600),
                    self.kwargs.get('corner_offset', 10 / 3600))
            else:
                self.sourcepos = Ellipse(
                    (self.source.ra_deg_cont, self.source.dec_deg_cont),
                    self.source.min_axis / 3600,
                    self.source.maj_axis / 3600,
                    -self.source.pos_ang,
                    facecolor='none',
                    edgecolor='r',
                    ls=':',
                    lw=2,
                    transform=self.ax.get_transform('world'))
                self.ax.add_patch(self.sourcepos)

        else:
            if self.kwargs.get('corner'):
                self._add_cornermarker(
                    self.ra, self.dec, self.kwargs.get('corner_span',
                                                       20 / 3600),
                    self.kwargs.get('corner_offset', 10 / 3600))
            else:
                self.bmin = 15
                self.bmaj = 15
                self.bpa = 0
                overlay = SphericalCircle(
                    (self.ra * u.deg, self.dec * u.deg),
                    self.bmaj * u.arcsec,
                    edgecolor='r',
                    linewidth=2,
                    facecolor='none',
                    transform=self.ax.get_transform('world'))
                self.ax.add_artist(overlay)

        if self.plot_neighbours:
            for idx, neighbour in self.neighbours.iterrows():
                n = Ellipse((neighbour.ra_deg_cont, neighbour.dec_deg_cont),
                            neighbour.min_axis / 3600,
                            neighbour.maj_axis / 3600,
                            -neighbour.pos_ang,
                            facecolor='none',
                            edgecolor='c',
                            ls=':',
                            lw=2,
                            transform=self.ax.get_transform('world'))
                self.ax.add_patch(n)

    def save(self, path, fmt='png'):
        """Save figure with tight bounding box."""
        self.fig.savefig(path, format=fmt, bbox_inches='tight')

    def savefits(self, path):
        """Export FITS cutout to path"""
        header = self.wcs.to_header()
        hdu = fits.PrimaryHDU(data=self.data, header=header)
        hdu.writeto(path)
示例#24
0
class EventManager:
    def __init__(self):
        self.handlers = {}
        self.logger = Logger("event_manager")
        self.event_types = []
        self.last_timer_event = 0

    def inject(self, registry):
        self.db = registry.get_instance("db")
        self.util = registry.get_instance("util")

    def pre_start(self):
        self.register_event_type("timer")

    def start(self):
        # process decorators
        for _, inst in Registry.get_all_instances().items():
            for name, method in get_attrs(inst).items():
                if hasattr(method, "event"):
                    event_type, description = getattr(method, "event")
                    handler = getattr(inst, name)
                    module = self.util.get_module_name(handler)
                    self.register(handler, event_type, description, module)

    def register_event_type(self, event_type):
        event_type = event_type.lower()

        if event_type in self.event_types:
            self.logger.error(
                "Could not register event type '%s': event type already registered"
                % event_type)
            return

        self.logger.debug("Registering event type '%s'" % event_type)
        self.event_types.append(event_type)

    def is_event_type(self, event_base_type):
        return event_base_type in self.event_types

    def register(self, handler, event_type, description, module):
        event_base_type, event_sub_type = self.get_event_type_parts(event_type)
        module = module.lower()
        handler_name = self.util.get_handler_name(handler).lower()

        if event_base_type not in self.event_types:
            self.logger.error(
                "Could not register handler '%s' for event type '%s': event type does not exist"
                % (handler_name, event_type))
            return

        if not description:
            self.logger.warning(
                "No description for event_type '%s' and handler '%s'" %
                (event_type, handler_name))

        row = self.db.find('event_config', {
            'event_type': event_base_type,
            'handler': handler_name
        })

        if row is None:
            # add new event commands
            self.db.insert(
                'event_config', {
                    'event_type': event_base_type,
                    'event_sub_type': event_sub_type,
                    'handler': handler_name,
                    'description': description,
                    'module': module,
                    'verified': 1,
                    'enabled': 1,
                    'next_run': int(time.time())
                })

        else:
            # mark command as verified
            self.db.update('event_config', {
                'event_type': event_base_type,
                'handler': handler_name
            }, {
                'verified': 1,
                'module': module,
                'description': description,
                'event_sub_type': event_sub_type,
            })

        # load command handler
        self.handlers[handler_name] = handler

    def fire_event(self, event_type, event_data=None):
        event_base_type, event_sub_type = self.get_event_type_parts(event_type)

        if event_base_type not in self.event_types:
            self.logger.error(
                "Could not fire event type '%s': event type does not exist" %
                event_type)
            return

        data = self.db.find_all(
            'event_config', {
                'event_type': event_base_type,
                'event_sub_type': event_sub_type,
                'enabled': 1
            })
        for row in data:
            handler = self.handlers.get(row['handler'], None)
            if not handler:
                self.logger.error(
                    "Could not find handler callback for event type '%s' and handler '%s'"
                    % (event_type, row.handler))
                return

            try:
                handler(event_type, event_data)
            except Exception as e:
                self.logger.error("error processing event '%s'" % event_type,
                                  e)

    def get_event_type_parts(self, event_type):
        parts = event_type.lower().split(":", 1)
        if len(parts) == 2:
            return parts[0], parts[1]
        else:
            return parts[0], ""

    def get_event_type_key(self, event_base_type, event_sub_type):
        return event_base_type + ":" + event_sub_type

    def check_for_timer_events(self, timestamp):
        data = self.db.find('event_config', {
            'enabled': 1,
            'event_type': 'timer',
            'next_run': {
                '$gte': timestamp
            }
        })

        if data is not None:
            for row in data:
                event_type_key = self.get_event_type_key(
                    row['event_type'], row['event_sub_type'])

                # timer event run times should be consistent, so we base the next run time off the last run time,
                # instead of the current timestamp
                next_run = row['next_run'] + int(row['event_sub_type'])

                # prevents timer events from getting too far behind, or having a large "catch-up" after
                # the bot has been offline for a time
                if next_run < timestamp:
                    next_run = timestamp + int(row['event_sub_type'])

                self.db.update('event_config', {
                    'event_type': 'timer',
                    'handler': row['handler']
                }, {'next_run': next_run})

                self.fire_event(event_type_key)
示例#25
0
        bot.connect("chat.dt.funcom.com", 7109)
    elif int(config["dimension"]) == 3:
        bot.connect("localhost", 9993)
    else:
        print('Invalid server!')
        bot.disconnect()
        time.sleep(5)
        exit(1)

    if not bot.login(config["username"], config["password"],
                     config["character"]):
        bot.disconnect()
        time.sleep(5)
        exit(3)
    else:
        status = bot.run()
        bot.disconnect()
        exit(status.value)

except ConnectionFailure:
    print("Connection to database failed.")
    exit(1)

except KeyboardInterrupt:
    exit(0)

except Exception as e:
    logger = Logger("bootstrap")
    logger.error("", e)
    exit(4)
示例#26
0
 def stop_ssh(self):
     try:
         subprocess.run("sudo /etc/init.d/ssh stop", shell=True, check=True)
     except subprocess.CalledProcessError:
         Logger.error("停止失败")
示例#27
0
    def updateItem(self, item, lx, ly, vx, vy):
        self.newLX = lx
        self.newLY = ly
        localNewLX = lx
        localNewLY = ly
        while True:
            time.sleep(1 / self.tickrate)
            self.newLX = float(self.newLX) + float(vx)
            self.newLY = float(self.newLY) + float(vy)
            localNewLX = float(localNewLX) + float(vx)
            localNewLY = float(localNewLY) + float(vy)

            item.place(relx=localNewLX, rely=localNewLY)
            print(self.newLX, self.newLY)

            try:

                cached = self.locations

                MYdiffX = cached[self.locIndex][0] - 1.00
                MYdiffY = cached[self.locIndex][1] - 1.00

                diffX = cached[0][0] - 1.00
                diffY = cached[0][1] - 1.00

                diffX2 = cached[1][0] - 1.00
                diffY2 = cached[1][1] - 1.00

                diffX3 = cached[2][0] - 1.00
                diffY3 = cached[2][1] - 1.00

                diffX4 = cached[3][0] - 1.00
                diffY4 = cached[3][1] - 1.00

                if diffX < 0:
                    diffX = diffX * -1

                if diffY < 0:
                    diffY = diffY * -1

                if diffX2 < 0:
                    diffX2 = diffX2 * -1

                if diffY2 < 0:
                    diffY2 = diffY2 * -1

                if diffX3 < 0:
                    diffX3 = diffX3 * -1

                if diffY3 < 0:
                    diffY3 = diffY3 * -1

                if diffX4 < 0:
                    diffX4 = diffX4 * -1

                if diffY4 < 0:
                    diffY4 = diffY4 * -1

                if MYdiffX < 0:
                    MYdiffX = MYdiffX * -1

                if MYdiffY < 0:
                    MYdiffY = MYdiffY * -1

                differences = [[diffX, diffY], [diffX2, diffY2],
                               [diffX3, diffY3], [diffX4, diffY4]]
                # print(differences)
                # print(MYdiffX, MYdiffY)
                myIndex = differences.index([MYdiffX, MYdiffY])
                # print(myIndex)

                diffXItem = float(self.newLX) - 1
                diffYItem = float(self.newLY) - 1

                if 1 < float(self.newLX) or float(self.newLX) < 0:
                    item.place_forget()
                    item = None
                    print('bullet out of bounds')
                    break
                if 1 < float(self.newLY) or float(self.newLY) < 0:
                    item.place_forget()
                    item = None
                    print('bullet out of bounds')
                    break

                if diffXItem < 0:
                    diffXItem = diffXItem * -1

                if diffYItem < 0:
                    diffYItem = diffYItem * -1

                GOTHIT = None

                # print(diffX, diffY, diffXItem, diffYItem)

                if self.bullet.cget("foreground") != self.playerColours[
                        self.locIndex]:

                    if diffXItem - 0.04 < diffX < diffXItem + 0.04:
                        if diffYItem - 0.04 < diffY < diffYItem + 0.04:
                            item.place_forget()
                            item = None
                            GOTHIT = 0
                    elif diffXItem - 0.04 < diffX2 < diffXItem + 0.04:
                        if diffYItem - 0.04 < diffY2 < diffYItem + 0.04:
                            item.place_forget()
                            item = None
                            GOTHIT = 1
                    elif diffXItem - 0.04 < diffX3 < diffXItem + 0.04:
                        if diffYItem - 0.04 < diffY3 < diffYItem + 0.04:
                            item.place_forget()
                            item = None
                            GOTHIT = 2
                    elif diffXItem - 0.04 < diffX4 < diffXItem + 0.04:
                        if diffYItem - 0.04 < diffY4 < diffYItem + 0.04:
                            item.place_forget()
                            item = None
                            GOTHIT = 3
                    if GOTHIT != None:
                        print('SOMEONE GOT HIT')
                        print(GOTHIT, myIndex)
                        if GOTHIT == myIndex:
                            self.notificationText.set(
                                'You were hit by a bullet!')
                            self.Window.after(
                                3000, lambda: self.notificationText.set(''))
                        break

            except Exception as e:
                Logger.error(e)
示例#28
0
class Profile(object):
    def __init__(self, profile_dir=None):
        self.profile_dir = profile_dir
        self.config = configparser.ConfigParser()
        self.logger = Logger()
        self.name = ''
        self.device = {'Device': 'SERIAL|IP:PORT', 'TCP': True}
        self.advanced = {'Debugging': False}
        if self.profile_dir is None:
            self.init_new()
            self.modify_profile()
        else:
            self.read_profile()
        self.adb = Device(self.__dict__)

    def __eq__(self, other):
        return (self.__class__ == other.__class__ and self.name == other.name
                and self.profile_dir == other.profile_dir)

    def read_profile(self):
        self.config.read(self.profile_dir)
        if not self.malformed():
            self.update_local()
        else:
            self.logger.error(
                'Profile is malformed. Please check the file or create a new profile.'
            )

    def update_local(self):
        self.__read_device()
        self.__read_advanced()
        self.profile_dir = './profiles/{}.prof'.format(self.name)

    def __read_device(self):
        self.name = self.config.get('Profile', 'Name')
        self.device['Device'] = self.config.get('Device', 'Device')
        self.device['TCP'] = self.config.getboolean('Device', 'TCP')

    def __read_advanced(self):
        self.advanced['Debugging'] = self.config.getboolean(
            'Advanced', 'Debugging')
        if self.advanced['Debugging']:
            self.logger.enable_debugging()
        else:
            self.logger.disable_debugging()

    def malformed(self):
        return not (self.config.has_option('Profile', 'Name')
                    and self.config.has_option('Device', 'Device')
                    and self.config.has_option('Device', 'TCP')
                    and self.config.has_option('Advanced', 'Debugging'))

    def init_new(self):
        default_profile = {
            'Profile': {
                'Name': self.name
            },
            'Device': self.device,
            'Advanced': self.advanced
        }
        self.config.read_dict(default_profile)

    def save_profile(self):
        os.makedirs(os.path.dirname(self.profile_dir), exist_ok=True)
        with open(self.profile_dir, 'w') as config_file:
            self.config.write(config_file)

    def modify_profile(self):
        self.config.set('Profile', 'Name', input('Enter profile name: '))
        self.config.set('Device', 'Device', input('Enter device: '))
        self.config.set('Device', 'TCP', input('Enter TCP: '))
        self.config.set('Advanced', 'Debugging', input('Enter debugging: '))
        self.update_local()

    def kill_consoles(self):
        self.logger.receiver.kill()
示例#29
0
def main(radius, contours, clabels, pm, epoch, sign, psf, corner, neighbours,
         annotation, basesurvey, cmap, maxnorm, band, obfuscate, verbose, save,
         savefits, ra, dec, survey):
    """Generate image cutout from multi-wavelength survey data.

    Available surveys:

    \b
    Radio
    ---------------------------------
    gw1I        s190814bv Epoch 1 (I)
    gw2I        s190814bv Epoch 2 (I)
    gw3I        s190814bv Epoch 3 (I)
    gw4I        s190814bv Epoch 4 (I)
    racsI                    RACS (I)
    racsV                    RACS (V)
    vastp1I               VAST P1 (I)
    vastp1V               VAST P1 (V)
    vastp2I               VAST P2 (I)
    vastp2V               VAST P2 (V)
    vastp3xI             VAST P3x (I)
    vastp3xV             VAST P3x (V)
    vastp4xI             VAST P4x (I)
    vastp4xV             VAST P4x (V)
    vastp5xI             VAST P5x (I)
    vastp5xV             VAST P5x (V)
    vastp6xI             VAST P6x (I)
    vastp6xV             VAST P6x (V)
    vastp7xI             VAST P7x (I)
    vastp7xV             VAST P7x (V)
    vastp8I               VAST P8 (I)
    vastp8V               VAST P8 (V)
    vastp9I               VAST P9 (I)
    vastp9V               VAST P9 (V)
    vastp10xI           VAST P10x (I)
    vastp10xV           VAST P10x (V)
    vastp11xI           VAST P11x (I)
    vastp11xV           VAST P11x (V)
    vlass                       VLASS
    sumss                       SUMSS
    nvss                         NVSS
    tgss                         TGSS
    gleam                       GLEAM
    ---------------------------------
    Infra-red
    ---------------------------------
    2massh                    2MASS H
    2massj                    2MASS J
    2massk                    2MASS K
    wise3_4                  WISE 3.4
    wise4_6                  WISE 4.6
    wise12                    WISE 12
    wise22                    WISE 22
    ---------------------------------
    Optical
    ---------------------------------
    decam                    DECam LS
    panstarrs               PanSTARRS
    skymapper               Skymapper
    dss                           DSS
    ---------------------------------
    UV / X-ray / Gamma-ray
    ---------------------------------
    galex_nuv           GALEX Near UV
    fermi             Fermi 3-300 GeV
    rass_soft       RASS Soft (ROSAT)
    swift_xrtcnt         SWIFT Counts
    """

    level = 'DEBUG' if verbose else 'INFO'
    logger = Logger(__name__, streamlevel=level).logger

    unit = u.hourangle if ':' in ra or 'h' in ra else u.deg

    position = SkyCoord(ra=ra, dec=dec, unit=(unit, u.deg))
    psign = -1 if sign else 1

    s = SURVEYS.loc[survey]
    if not radius:
        radius = s.radius

    try:
        if s.radio and not contours:
            cutout = Cutout(survey,
                            position,
                            radius=radius,
                            psf=psf,
                            corner=corner,
                            neighbours=neighbours,
                            annotation=annotation,
                            basesurvey=basesurvey,
                            band=band,
                            maxnorm=maxnorm,
                            cmap=cmap,
                            obfuscate=obfuscate,
                            verbose=verbose,
                            sign=psign,
                            pm=pm,
                            epoch=epoch)
        elif contours:
            cutout = ContourCutout(survey,
                                   position,
                                   radius=radius,
                                   contours=contours,
                                   clabels=clabels,
                                   psf=psf,
                                   corner=corner,
                                   neighbours=neighbours,
                                   annotation=annotation,
                                   basesurvey=basesurvey,
                                   band=band,
                                   cmap=cmap,
                                   maxnorm=maxnorm,
                                   obfuscate=obfuscate,
                                   verbose=verbose,
                                   sign=psign,
                                   pm=pm,
                                   epoch=epoch)
        else:
            cutout = ContourCutout(survey,
                                   position,
                                   radius=radius,
                                   contours='racsI',
                                   psf=psf,
                                   corner=corner,
                                   neighbours=neighbours,
                                   annotation=annotation,
                                   basesurvey=basesurvey,
                                   band=band,
                                   cmap=cmap,
                                   maxnorm=maxnorm,
                                   obfuscate=obfuscate,
                                   verbose=verbose,
                                   sign=psign,
                                   pm=pm,
                                   epoch=epoch)

        cutout.plot()
    except FITSException as e:
        if verbose:
            logger.exception(e)
        else:
            logger.error(e)

    if save:
        cutout.save(save)

    if savefits:
        cutout.savefits(savefits)

    plt.show()
示例#30
0
def find_materials():
    """Find material models

    """
    logger = Logger("console")

    errors = []
    mat_libs = {}
    rx = re.compile(r"(?:^|[\\b_\\.-])[Mm]at")
    a = ["MaterialModel", "AbaqusMaterial"]
    # gather and verify all files
    search_dirs = [d for d in MAT_LIB_DIRS]
    if not SUPPRESS_USER_ENV:
        for user_mat in cfgparse("materials"):
            user_mat = os.path.realpath(user_mat)
            if user_mat not in search_dirs:
                search_dirs.append(user_mat)

    # go through each item in search_dirs and generate a list of material
    # interface files. if item is a directory gather all files that match rx;
    # if it's a file, add it to the list of material files
    for item in search_dirs:
        if os.path.isfile(item):
            d, files = os.path.split(os.path.realpath(item))
            files = [files]
        elif os.path.isdir(item):
            d = item
            files = [f for f in os.listdir(item) if rx.search(f)]
        else:
            logger.warn("{0} no such directory or file, skipping".format(d),
                               report_who=1)
            continue
        files = [f for f in files if f.endswith(".py")]

        if not files:
            logger.warn("{0}: no mat files found".format(d), report_who=1)

        # go through files and determine if it's an interface file. if it is,
        # load it and add it to mat_libs
        for f in files:
            module = f[:-3]
            try:
                libs = xpyclbr.readmodule(module, [d], ancestors=a)
            except AttributeError as e:
                errors.append(e.args[0])
                logger.error(e.args[0])
                continue
            for lib in libs:
                if lib in mat_libs:
                    logger.error("{0}: duplicate material".format(lib))
                    errors.append(lib)
                    continue
                module = load_file(libs[lib].file)
                mat_class = getattr(module, libs[lib].class_name)
                if not mat_class.name:
                    raise AFEPYError("{0}: material name attribute "
                                     "not defined".format(lib))
                libs[lib].mat_class = mat_class
                mat_libs.update({mat_class.name.lower(): libs[lib]})

    if errors:
        raise AFEPYError(", ".join(errors))

    return mat_libs