コード例 #1
0
 async def info(self, ctx):
     """Shows you information about the bot owner, bot uptime, latency, memory and cpu usage."""
     embed = Embed(color=0x000000)
     embed.set_thumbnail(url=ctx.bot.user.avatar_url)
     app = await ctx.bot.application_info()
     owner = app.owner
     embed.set_author(name=str(owner), icon_url=owner.avatar_url)
     proc = Process()
     with proc.oneshot():
         uptime = datetime.utcnow() - ctx.bot.launched_at
         mem_total = virtual_memory().total / (1024**2)
         mem_of_total = proc.memory_percent()
         mem_usage = mem_total * (mem_of_total / 100)
         cpu_usage = proc.cpu_percent() / cpu_count()
     embed.add_field(name='Uptime', value=str(uptime), inline=False)
     embed.add_field(name='Latency',
                     value=f'{round(ctx.bot.latency * 1000, 2)} ms',
                     inline=False)
     embed.add_field(
         name='Memory usage',
         value=
         f'{int(mem_usage)} / {int(mem_total)} MiB ({round(mem_of_total)}%)',
         inline=False)
     embed.add_field(name='CPU usage',
                     value=f'{round(cpu_usage)}%',
                     inline=False)
     await ctx.send(embed=embed)
コード例 #2
0
    def get_resource_usage(self) -> ResourceUsage:
        """
        Return various resource usage statistics about the running process.
        """
        assert not self.returncode, "Can't collect data on stopped process"

        proc = Process(self.ps.pid)

        if 'bitcoind' in self.cmd:

            def find_process(proc_):
                """
                Process graph looks like this:

                    sh(327)───time(334)───bitcoind(335)
                """
                name = proc_.name()

                # Recurse into child processes if need be.
                if name in ['sh', 'time']:
                    assert len(proc_.children()) == 1
                    return find_process(proc_.children()[0])

                assert (name.startswith('bitcoin') or name.startswith('b-'))
                return proc_

            proc = find_process(proc)

        with proc.oneshot():
            return ResourceUsage(
                cpu_percent=proc.cpu_percent(),
                memory_info=proc.memory_info(),
                num_fds=proc.num_fds(),
            )
コード例 #3
0
ファイル: hardware_track.py プロジェクト: xiaming9880/labml
def track_process(p: psutil.Process):
    pid = p.pid

    with p.oneshot():
        try:
            res = p.memory_info()
            tracker.add({
                f'process.{p.pid}.{p.name()}.rss': res.rss,
                f'process.{p.pid}.{p.name()}.vms': res.vms
            })
        except psutil.AccessDenied:
            pass
        try:
            res = p.memory_percent()
            tracker.add({
                f'process.{p.pid}.{p.name()}.mem': res,
            })
        except psutil.AccessDenied:
            pass

        try:
            res = p.cpu_percent()
            tracker.add({
                f'process.{p.pid}.{p.name()}.cpu': res,
            })
        except psutil.AccessDenied:
            pass

        try:
            res = p.num_threads()
            tracker.add({
                f'process.{p.pid}.{p.name()}.threads': res,
            })
        except psutil.AccessDenied:
            pass
コード例 #4
0
ファイル: admin.py プロジェクト: silverfix/django-accio
 def worker(self, obj):
     if self.active_workers:
         for node, active_workers in self.active_workers.iteritems():
             for worker in active_workers:
                 if worker['id'] == obj.task_id:
                     p = Process(worker['worker_pid'])
                     return 'CPU:%.1f%% RAM:%.2f%%' % (p.cpu_percent(0.05), p.memory_percent())
     return 'N/a'
コード例 #5
0
ファイル: main.py プロジェクト: Cthulhu2/barbarian
    def main(self, opts):
        if not opts.sound:
            mixer.quit()
        cpu_timer = 0
        mem_timer = 0
        pid = getpid()
        pu = Process(pid)

        # import after init, to load images
        #   pygame.error: cannot convert without pygame.display initialized
        from sprite.common import Txt
        if opts.viewer:
            from scene.viewer import AnimationViewerScene
            scene = AnimationViewerScene(self.screen)
            display.set_caption('Barbarian - Animation viewer')
        else:
            from scene.battle import BattleScene
            scene = BattleScene(self.screen)
            display.set_caption('Barbarian')
        clock = time.Clock()

        cpu = Txt(FONT, 8, 'CPU: ', RED, 0, 566)
        # 'Resident Set Size', this is the non-swapped
        #   physical memory a process has used.
        mem_rss = Txt(FONT, 8, 'Mem RSS: ', RED, 0, cpu.rect.bottom)
        # 'Virtual Memory Size', this is the total amount of
        #   virtual memory used by the process.
        mem_vms = Txt(FONT, 8, 'Mem VMS: ', RED, 0, mem_rss.rect.bottom)
        fps = Txt(FONT, 8, 'FPS: ', RED, 0, mem_vms.rect.bottom)
        if opts.debug:
            scene.add(cpu, mem_rss, mem_vms, fps)

        while True:
            for evt in event.get():
                scene.process_event(evt)

            # Update all the sprites
            current_time = time.get_ticks()
            if opts.debug:
                fps.msg = 'FPS: {0:.0f}'.format(clock.get_fps())

                if current_time - cpu_timer > opts.cpu_time:
                    cpu_timer = current_time
                    cpu.msg = 'CPU: {0:.1f}%'.format(pu.cpu_percent())

                if current_time - mem_timer > opts.mem_time:
                    mem_timer = current_time
                    mem = pu.memory_info()
                    resident = 'Mem RSS: {0:>7,.0f} Kb'.format(mem.rss / 1024)
                    mem_rss.msg = resident.replace(',', ' ')
                    virtual = 'Mem VMS: {0:>7,.0f} Kb'.format(mem.vms / 1024)
                    mem_vms.msg = virtual.replace(',', ' ')
            scene.update(current_time)

            # Draw the scene
            dirty = scene.draw(self.screen)
            display.update(dirty)
            clock.tick(60)
コード例 #6
0
    def add_new_information_from_process_object(self, process: psutil.Process,
                                                data_retrieval_timestamp: datetime.datetime) -> None:
        """
        Adds the new information about the process to the application profile.
        This should be mainly used for applications with only one process.
        :raises TypeError if process is not of type psutil.Process or data_retrieval_timestamp is not of type
            datetime.datetime.
        :raises ValueError if data_retrieval_timestamp is newer than current time.
        :param process: Information about the specific process.
        :type process: psutil.Process
        :param data_retrieval_timestamp: The time the data was retrieved.
        :type data_retrieval_timestamp: datetime.datetime
        """
        if not (isinstance(process, psutil.Process)):
            raise TypeError(expected_type_but_received_message.format("process", "psutil.Process", process))
        if not (isinstance(data_retrieval_timestamp, datetime.datetime)):
            raise TypeError(expected_type_but_received_message.format("data_retrieval_timestamp", "datetime.datetime",
                                                                      data_retrieval_timestamp))
        if data_retrieval_timestamp.replace(tzinfo=None) > datetime.datetime.now():
            raise ValueError("Argument data_retrieval_timestamp cannot be newer than current time. Value receive: {}"
                             .format(data_retrieval_timestamp))

        # Get info from the process object. One of the following calls may raise an Error (OS, AccessDenied, etc).
        open_files = process.open_files()
        memory_info = process.memory_info()
        child_process_count = len(process.children())
        username = process.username()
        threads_number = process.num_threads()
        process.cpu_percent()
        try:
            connections_num = len(process.connections())
        except psutil.AccessDenied:
            connections_num = 0

        time.sleep(0.1)  # wait for cpu_percent to return a meaningful value.
        cpu_percentage = process.cpu_percent()

        self.add_open_files(open_files=open_files, data_retrieval_timestamp=data_retrieval_timestamp)
        self.__memory_usages.append(memory_info.rss)
        self.__data_retrieval_timestamp.append(data_retrieval_timestamp)
        self.__child_processes_count.append(child_process_count)
        self.__users.extend(username)
        self.__cpu_percent_usages.append(cpu_percentage)
        self.__threads_numbers.append(threads_number)
        self.__connections_numbers.append(connections_num)
コード例 #7
0
def collect_status(pid, appname, site):
    ip_out = get_host_info()[0]
    ip_inner = get_host_info()[1]
    server_id = get_host_info()[2]
    physical_mem = psutil.virtual_memory().total / 1024 / 1024  #Unit of M
    cpu_count = psutil.cpu_count()
    its = int(time.time())
    p_ins = Process(pid)
    pstatus = p_ins.status()
    create_time = time.strftime("%Y%m%d %H:%M:%S",
                                time.localtime(p_ins.create_time()))
    memory_percent = p_ins.memory_percent()
    memory_used = memory_percent * physical_mem
    cpu_calc_list = []
    for i in range(6):
        cpu_calc = p_ins.cpu_percent(interval=0.1)
        cpu_calc_list.append(cpu_calc)
    cpu_percent = float(sum(cpu_calc_list) / len(cpu_calc_list))
    num_fds = p_ins.num_fds()
    connections = p_ins.connections()
    connections_num = len(connections)

    #appname=p_ins.cwd()
    if p_ins.name() == 'jsvc':
        app_path = p_ins.exe().split('/')[:-2]
    else:
        app_path = p_ins.cwd()

    #appname = app_path.split('/')[-1]
    appname = appname
    if p_ins.children(recursive=True):
        children_list = str(p_ins.children(recursive=True))
    else:
        children_list = None
    message = {
        'site': site,
        'ip': ip_out,
        'ip_inner': ip_inner,
        'server_id': server_id,
        'pstatus': pstatus,
        'metric_name': 'app_monitor',
        'its': its,
        'pid': pid,
        'physical_mem': physical_mem,
        'memory_used': memory_used,
        'memory_percent': memory_percent,
        'cpu_count': cpu_count,
        'cpu_percent': cpu_percent,
        'num_fds': num_fds,
        'connections_num': connections_num,
        'create_time': create_time,
        'appname': appname,
        'app_path': app_path,
        'children': children_list
    }
    return message
コード例 #8
0
 def _collect(self, index: int, process: psutil.Process, data: ValueSet):
     if self.load:
         data.add(
             Value(process.cpu_percent(),
                   label_values=[str(index)],
                   name='load_percent'))
     if self.memory:
         data.add(
             Value(process.memory_info().vms,
                   label_values=[str(index)],
                   name='virtual_memory'))
     return data
コード例 #9
0
def track_memory_usage(out_path: str, write_frequency: float):
    """Track how busy the head node is

    Args:
        out_path: Path to the output file
        write_frequency: How often to write (s)
    """

    while True:
        # Get a timestamp
        ts = datetime.now().timestamp()

        # Measure the thinker process
        proc = Process()
        my_usage = proc.cpu_percent()
        my_memory = proc.memory_full_info().pss

        # Measure all processes from my user
        my_name = getuser()
        all_cpu = all_memory = 0
        for proc in process_iter():
            if proc.username() != my_name:
                continue
            try:
                all_cpu += proc.cpu_percent()
                all_memory += proc.memory_full_info().pss
            except:
                continue

        with open(out_path, 'a') as fp:
            print(json.dumps({
                'time': ts,
                'thinker_cpu': my_usage,
                'thinker_mem': my_memory,
                'all_cpu': all_cpu,
                'all_mem': all_memory
            }),
                  file=fp)
        time.sleep(write_frequency)
コード例 #10
0
ファイル: executor.py プロジェクト: zeta1999/agents-aea
    def _get_stats_record(proc_info: psutil.Process) -> ResourceStats:
        """
        Read resources usage and create record.

        :param proc_info: process information to get cpu usage and memory usage from.

        :return: one time resource stats record
        """
        return ResourceStats(
            time.time(),
            proc_info.cpu_percent(),
            memory_profiler.memory_usage(proc_info.pid, max_usage=True),
        )
コード例 #11
0
 def fetch_process(process: psutil.Process):
     cpu_percent = None
     name = None
     try:
         cpu_percent = process.cpu_percent()
         name = process.name()
     except Exception:
         pass
     return PsUtilProcess(
         process=process,
         name=name,
         cpu_percent=cpu_percent,
     )
コード例 #12
0
ファイル: utils.py プロジェクト: pmav99/pmon
def get_proc_data(proc: psutil.Process) -> Dict[str, Union[int, float]]:
    data: Dict[str, Union[int, float]] = {}
    try:
        with proc.oneshot():
            data.update(proc.memory_full_info()._asdict())
            data["cpu_percent"] = proc.cpu_percent()
            data["rss_percent"] = data["rss"] / TOTAL_MEMORY * 100
            data["pss_percent"] = data["pss"] / TOTAL_MEMORY * 100
            data["uss_percent"] = data["uss"] / TOTAL_MEMORY * 100
            data["vms_percent"] = data["vms"] / TOTAL_MEMORY * 100
    except psutil.NoSuchProcess:
        raise ValueError(f"The process no longer exists: {proc.pid}")
    else:
        return data
コード例 #13
0
ファイル: text_ui.py プロジェクト: lunareve/mpf
class TextUi(MpfController):
    """Handles the text-based UI."""
    def __init__(self, machine: "MachineController") -> None:
        """Initialize TextUi."""
        super().__init__(machine)

        self.screen = None

        if not machine.options['text_ui']:
            return

        self.start_time = datetime.now()
        self.machine = machine
        self._tick_task = self.machine.clock.schedule_interval(self._tick, 1)
        self.screen = Screen.open()
        self.mpf_process = Process()
        self.ball_devices = list()  # type: List[BallDevice]

        self.switches = OrderedDict(
        )  # type: Dict[Switch, Tuple[str, int, int]]
        self.player_start_row = 0
        self.column_positions = [0, .25, .5, .75]
        self.columns = [0] * len(self.column_positions)

        self.machine.events.add_handler('init_phase_2', self._init)
        self.machine.events.add_handler('init_phase_3', self._update_switches)
        # self.machine.events.add_handler('init_phase_3', self._init2)
        self.machine.events.add_handler('loading_assets',
                                        self._asset_load_change)
        self.machine.events.add_handler('bcp_connection_attempt',
                                        self._bcp_connection_attempt)
        self.machine.events.add_handler('asset_loading_complete',
                                        self._asset_load_complete)
        self.machine.events.add_handler('bcp_clients_connected',
                                        self._bcp_connected)
        self.machine.events.add_handler('shutdown', self.stop)
        self.machine.events.add_handler('player_number', self._update_player)
        self.machine.events.add_handler('player_ball', self._update_player)
        self.machine.events.add_handler('player_score', self._update_player)
        self.machine.events.add_handler('ball_ended',
                                        self._update_player_no_game)

        self._pending_bcp_connection = False
        self._asset_percent = 0
        self._bcp_status = (0, 0, 0)  # type: Tuple[float, int, int]

        self._draw_screen()
        self.screen.refresh()

    def _init(self, **kwargs):
        del kwargs
        self.machine.mode_controller.register_start_method(self._mode_change)
        self.machine.mode_controller.register_stop_method(self._mode_change)
        self.machine.switch_controller.add_monitor(self._update_switches)
        self.machine.bcp.interface.register_command_callback(
            "status_report", self._bcp_status_report)

        for bd in [
                x for x in self.machine.ball_devices if not x.is_playfield()
        ]:
            self.ball_devices.append(bd)

        self.ball_devices.sort()
        self._draw_player_header()

        self._update_switch_layout()

    def _bcp_status_report(self, client, cpu, rss, vms):
        del client
        self._bcp_status = cpu, rss, vms

    def _draw_screen(self):

        for i, percent in enumerate(self.column_positions):
            if not i:
                self.columns[i] = 1
            self.columns[i] = int(self.screen.width * percent)

        height, width = self.screen.dimensions
        title = 'Mission Pinball Framework v{}'.format(
            mpf._version.__version__)  # noqa
        padding = int((self.screen.width - len(title)) / 2)

        self.screen.print_at((' ' * padding) + title + (' ' * (padding + 1)),
                             0,
                             0,
                             colour=7,
                             bg=1)

        self.screen.print_at('<CTRL+C> TO EXIT', width - 16, 0, colour=0, bg=1)

        self.screen.print_at('ACTIVE MODES', self.columns[0], 2)
        self.screen.print_at('SWITCHES', int((width * .5) - 8), 2)
        self.screen.print_at('BALL COUNTS', self.columns[3], 2)
        self.screen.print_at('-' * width, 0, 3)

        self.screen.print_at(self.machine.machine_path,
                             0,
                             height - 2,
                             colour=3)

        if 0 < self._asset_percent < 100:
            self.screen.print_at(' ' * width, 0, int(height / 2) + 1, bg=3)
            self.screen.print_at('LOADING ASSETS: {}%'.format(
                self._asset_percent),
                                 int(width / 2) - 10,
                                 int(height / 2) + 1,
                                 colour=0,
                                 bg=3)

        if self._pending_bcp_connection:
            bcp_string = 'WAITING FOR MEDIA CONTROLLER {}...'.format(
                self._pending_bcp_connection)

            self.screen.print_at(' ' * width, 0, int(height / 2) - 1, bg=3)
            self.screen.print_at(bcp_string,
                                 int((width - len(bcp_string)) / 2),
                                 int(height / 2) - 1,
                                 colour=0,
                                 bg=3)

        self._update_stats()

    def _draw_player_header(self):
        self.player_start_row = (len(self.ball_devices) +
                                 len(self.machine.playfields)) + 7

        self.screen.print_at('CURRENT PLAYER', self.columns[3],
                             self.player_start_row - 2)
        self.screen.print_at('-' * (int(self.screen.width * .75) + 1),
                             self.columns[3], self.player_start_row - 1)
        self._update_player()

    def _update_stats(self):
        height, width = self.screen.dimensions

        # Runtime
        rt = (datetime.now() - self.start_time)
        mins, sec = divmod(rt.seconds + rt.days * 86400, 60)
        hours, mins = divmod(mins, 60)
        time_string = 'RUNNING {:d}:{:02d}:{:02d}'.format(hours, mins, sec)
        self.screen.print_at(time_string,
                             width - len(time_string),
                             height - 2,
                             colour=2)

        # System Stats
        system_str = 'Free Memory (MB): {} CPU:{:3d}%'.format(
            round(virtual_memory().available / 1048576),
            round(cpu_percent(interval=None, percpu=False)))
        self.screen.print_at(system_str,
                             width - len(system_str),
                             height - 1,
                             colour=2)

        # MPF process stats
        stats_str = 'MPF (CPU RSS/VMS): {}% {}/{} MB    '.format(
            round(self.mpf_process.cpu_percent()),
            round(self.mpf_process.memory_info().rss / 1048576),
            round(self.mpf_process.memory_info().vms / 1048576))

        self.screen.print_at(stats_str, 0, height - 1, colour=6)

        # MC process stats
        if self._bcp_status != (0, 0, 0):
            bcp_string = 'MC (CPU RSS/VMS) {}% {}/{} MB '.format(
                round(self._bcp_status[0]),
                round(self._bcp_status[1] / 1048576),
                round(self._bcp_status[2] / 1048576))

            self.screen.print_at(bcp_string,
                                 len(stats_str) - 2,
                                 height - 1,
                                 colour=5)

    def _update_switch_layout(self):
        start_row = 4
        cutoff = int(len(self.machine.switches) / 2) + start_row - 1
        row = start_row
        col = 1

        for sw in sorted(self.machine.switches):
            if sw.invert:
                name = sw.name + '*'
            else:
                name = sw.name

            self.switches[sw] = (name, self.columns[col], row)

            if row == cutoff:
                row = start_row
                col += 1
            else:
                row += 1

        self._update_switches()

    def _update_switches(self, *args, **kwargs):
        del args, kwargs
        for sw, info in self.switches.items():
            if sw.state:
                self.screen.print_at(*info, colour=0, bg=2)
            else:
                self.screen.print_at(*info)

        self.screen.refresh()

    def _mode_change(self, *args, **kwargs):
        # Have to call this on the next frame since the mode controller's
        # active list isn't updated yet
        del args
        del kwargs
        self.machine.clock.schedule_once(self._update_modes)

    def _update_modes(self, *args, **kwargs):
        del args
        del kwargs
        modes = self.machine.mode_controller.active_modes

        for i, mode in enumerate(modes):
            self.screen.print_at(' ' * (self.columns[0] - 1), self.columns[0],
                                 i + 4)
            self.screen.print_at('{} ({})'.format(mode.name, mode.priority),
                                 self.columns[0], i + 4)

        self.screen.print_at(' ' * (int(self.screen.width * .25) - 1),
                             self.columns[0],
                             len(modes) + 4)

    def _update_ball_devices(self, **kwargs):
        del kwargs

        row = 4

        try:
            for pf in self.machine.playfields:
                self.screen.print_at('{}: {} '.format(pf.name, pf.balls),
                                     self.columns[3],
                                     row,
                                     colour=2 if pf.balls else 7)
                row += 1
        except AttributeError:
            pass

        for bd in self.ball_devices:
            # extra spaces to overwrite previous chars if the str shrinks
            self.screen.print_at('{}: {} ({})                   '.format(
                bd.name, bd.balls, bd.state),
                                 self.columns[3],
                                 row,
                                 colour=2 if bd.balls else 7)
            row += 1

    def _update_player(self, **kwargs):
        del kwargs
        for i in range(3):
            self.screen.print_at(
                ' ' * (int(self.screen.width * (1 / len(self.columns))) + 1),
                self.columns[3], self.player_start_row + i)
        try:
            self.screen.print_at(
                'PLAYER: {}'.format(self.machine.game.player.number),
                self.columns[3], self.player_start_row)
            self.screen.print_at(
                'BALL: {}'.format(self.machine.game.player.ball),
                self.columns[3], self.player_start_row + 1)
            self.screen.print_at(
                'SCORE: {:,}'.format(self.machine.game.player.score),
                self.columns[3], self.player_start_row + 2)
        except AttributeError:
            self._update_player_no_game()

    def _update_player_no_game(self, **kwargs):
        del kwargs
        for i in range(3):
            self.screen.print_at(
                ' ' * (int(self.screen.width * (1 / len(self.columns))) + 1),
                self.columns[3], self.player_start_row + i)

        self.screen.print_at('NO GAME IN PROGRESS', self.columns[3],
                             self.player_start_row)

    def _tick(self):
        if self.screen.has_resized():
            self.screen = Screen.open()
            self._update_switch_layout()
            self._update_modes()
            self._draw_screen()
            self._draw_player_header()

        self.machine.bcp.transport.send_to_all_clients("status_request")
        self._update_stats()
        self._update_ball_devices()
        self.screen.refresh()

    def _bcp_connection_attempt(self, name, host, port, **kwargs):
        del name
        del kwargs
        self._pending_bcp_connection = '{}:{}'.format(host, port)
        self._draw_screen()

    def _bcp_connected(self, **kwargs):
        del kwargs
        self._pending_bcp_connection = None
        self.screen.print_at(' ' * self.screen.width, 0,
                             int(self.screen.height / 2) - 1)

        self._update_modes()
        self._update_switches()
        self._update_ball_devices()

    def _asset_load_change(self, percent, **kwargs):
        del kwargs
        self._asset_percent = percent
        self._draw_screen()

    def _asset_load_complete(self, **kwargs):
        del kwargs
        self._asset_percent = 100
        self.screen.print_at(' ' * self.screen.width, 0,
                             int(self.screen.height / 2) + 1)

        self._update_modes()
        self._update_switches()
        self._update_ball_devices()

    def stop(self, **kwargs):
        """Stop the Text UI and restore the original console screen."""
        del kwargs

        if self.screen:
            self.machine.clock.unschedule(self._tick_task)
            logger = logging.getLogger()
            logger.addHandler(logging.StreamHandler())
            self.screen.close(True)
コード例 #14
0
    def track_process(self, p: psutil.Process):
        with p.oneshot():
            key = None
            if p.pid in self.pids:
                key = self.pids[p.pid]
                if self.processes[key].name != p.name():
                    key = None
            if key is None:
                key = len(self.processes)
                self.processes.append(ProcessInfo(key,
                                               p.pid,
                                               p.name()))
                self.pids[p.pid] = key
                self.data.update({
                    f'process.{key}.name': p.name(),
                    f'process.{key}.pid': p.pid,
                    f'process.{key}.ppid': p.ppid(),
                    f'process.{key}.create_time': p.create_time(),
                })

                try:
                    self.data.update({
                        f'process.{key}.exe': p.exe(),
                    })
                except (psutil.AccessDenied, psutil.ZombieProcess):
                    pass

                try:
                    self.data.update({
                        f'process.{key}.cmdline': '\n'.join(p.cmdline()),
                    })
                except (psutil.AccessDenied, psutil.ZombieProcess):
                    pass

            self.processes[key].active = True

            try:
                res = p.memory_info()
                self.data.update({
                    f'process.{key}.rss': res.rss,
                    f'process.{key}.vms': res.vms,
                })
            except (psutil.AccessDenied, psutil.ZombieProcess):
                pass

            try:
                res = p.cpu_times()
                self.data.update({
                    f'process.{key}.user': res.user,
                    f'process.{key}.system': res.system,
                })
                if hasattr(res, 'iowait'):
                    self.data.update({
                        f'process.{key}.iowait': res.iowait,
                    })
            except (psutil.AccessDenied, psutil.ZombieProcess):
                pass

            try:
                res = p.cpu_percent()
                self.data.update({
                    f'process.{key}.cpu': res,
                })
            except (psutil.AccessDenied, psutil.ZombieProcess):
                pass

            try:
                res = p.num_threads()
                self.data.update({
                    f'process.{key}.threads': res,
                })
            except (psutil.AccessDenied, psutil.ZombieProcess):
                pass
コード例 #15
0
    if not exists(log_path):
        makedirs(log_path)

    basicConfig(
        filename='%s/log_%s.log' %
        ('Log', strftime("%Y-%m-%d-%H-%M-%S", gmtime())),
        level=TRACE,
        format=
        "%(levelname)s:%(filename)s,%(lineno)d:%(name)s.%(funcName)s:%(message)s"
    )
    #, stream=sys.stderr
    srv = Server()
    server_thread = Thread(target=srv.run)
    server_thread.start()

    print("VERSION: ", __version__)

    self_usage = Process(getpid())
    while True:
        sleep(1)
        u_cpu = int(self_usage.cpu_percent())
        u_memory = int(self_usage.memory_info()[0] / 2.**20)
        t_memory = int(virtual_memory()[0] / 2.**20)
        u_disk = int(self_usage.io_counters()[0] / self_usage.io_counters()[1])
        o_slots = len(srv.connections.keys())
        t_slots = srv.setting.maximum_users
        sys.stdout.write(
            "\rSERVER MONITOR [CPU: %s%% | RAM: %s/%s Mb | DISK: %s%% | SLOTS: %s/%s]"
            % (u_cpu, u_memory, t_memory, u_disk, o_slots, t_slots))
        sys.stdout.flush()
コード例 #16
0
class ProcessWrapper:
    def check_alive(self):
        if self._alive and self.process.returncode is not None:
            self._alive = False

    def check_pipe(self,
                   read_pipe,
                   write_pipe,
                   write_stdout=False,
                   write_stderr=False):
        with self.lock:
            self._pipes_watching += 1

        OutputHandler.print(
            f'Start watching {"stdout" if write_stdout else "stderr"} '
            f'Pipes watching = {self._pipes_watching}')

        while not self.is_finished():
            try:
                new_output = read_pipe.read(1)
            except ValueError:
                self.check_alive()
                continue

            if len(new_output) == 0:
                with self.lock:
                    self._pipes_watching -= 1

                OutputHandler.print(
                    f'Out of {"stdout" if write_stdout else "stderr"}... '
                    f'Maybe program terminated. Pipes watching = {self._pipes_watching}'
                )

                if self._pipes_watching == 0:
                    self._alive = False
                    self.terminate()

                break

            try:
                if self.register_output:
                    write_pipe.write(new_output)
            except ExitException:
                self._alive = False
                self.terminate()
                break

            if write_stdout:
                self.stdout += new_output

            if write_stderr:
                self.stderr += new_output

            self.check_alive()

    def check_stdout(self):
        self.check_pipe(self.process.stdout, sys.stdout, write_stdout=True)

    def check_stderr(self):
        self.check_pipe(self.process.stderr, sys.stderr, write_stderr=True)

    def check_cpuload(self):
        while self._alive:
            try:
                cpu_load = self.ps.cpu_percent()
                OutputHandler.print(f'Check cpuload - {cpu_load}')
                self.cpu_load_history.append(cpu_load)
                if len(self.cpu_load_history) > self.cpu_load_length:
                    self.cpu_load_history.pop(0)
            except NoSuchProcess:
                OutputHandler.print('Check cpuload finished, waiting output')
                self.wait_output()
                OutputHandler.print(
                    'Check cpuload finished, set alive = false')
                self._alive = False
                break
            sleep(0.01)
            self.check_alive()

    def is_waiting_input(self) -> bool:
        return len(self.cpu_load_history) == self.cpu_load_length and sum(
            self.cpu_load_history) < 1

    def register_input_request(self):
        if not self.is_waiting_input():
            raise RuntimeError('Program is not waiting for the input')
        self.cpu_load_history = []

    def is_finished(self):
        if not self.check_early_finish:
            return not self._alive

        else:
            if not self._alive:
                return True

            try:
                is_running = self.ps.status() == 'running'
                if not is_running:
                    self._alive = False
                return not is_running
            except NoSuchProcess:
                self._alive = False
                return True

    def __init__(self, *args, check_early_finish=False, register_output=True):
        self.lock = Lock()

        try:
            self.process = subprocess.Popen(
                [str(a) for a in args],
                bufsize=0,
                universal_newlines=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                stdin=subprocess.PIPE,
                encoding='utf-8',
            )
        except Exception:
            raise

        self.ps = Process(self.process.pid)

        self.cpu_load = self.ps.cpu_percent()
        self.cpu_load_history = []
        self.cpu_load_length = 10

        self.stdout = ''
        self.stderr = ''
        self._alive = True
        self._pipes_watching = 0
        self.terminated = False

        self.check_early_finish = check_early_finish
        self.register_output = register_output

        Thread(target=lambda: self.check_cpuload(), daemon=True).start()
        Thread(target=lambda: self.check_stdout(), daemon=True).start()
        Thread(target=lambda: self.check_stderr(), daemon=True).start()

    def terminate(self):
        OutputHandler.print('Terminate called')

        with self.lock:
            OutputHandler.print('Terminate - LOCK ACQUIRED')

            if not self.terminated:
                OutputHandler.print('Terminate - BEFORE WAIT STDERR')

                self.wait_output()

                OutputHandler.print('Terminate - AFTER WAIT STDERR')

                self._alive = False

                OutputHandler.print('Terminate - SELF ALIVE == FALSE')

                is_exit_replaced = ExitHandler.is_replaced()
                if is_exit_replaced:
                    ExitHandler.revert_exit()
                    OutputHandler.print('Terminate - EXIT REVERTED')

                try:
                    parent = Process(self.process.pid)
                    OutputHandler.print(f'Terminate - parent == {parent}')
                    for child in parent.children(recursive=True):
                        OutputHandler.print(f'Terminate - child kill {child}')
                        child.kill()
                    OutputHandler.print(f'Terminate - parent kill {parent}')
                    parent.kill()
                except NoSuchProcess:
                    OutputHandler.print(f'Terminate - NO SUCH PROCESS')
                    pass
                finally:
                    OutputHandler.print(f'Terminate - finally before kill')
                    self.process.kill()
                    OutputHandler.print(f'Terminate - finally before wait')
                    self.process.wait()

                    self.process.stdout.close()
                    self.process.stderr.close()
                    self.process.stdin.close()

                    if is_exit_replaced:
                        ExitHandler.replace_exit()
                        OutputHandler.print(f'Terminate - EXIT REPLACED AGAIN')

                self.terminated = True
                OutputHandler.print(f'Terminate - TERMINATED')
        OutputHandler.print(f'Terminate - finished')

    def wait_output(self):
        iterations = 50
        sleep_time = 50 / 1000

        curr_stdout = self.stdout
        curr_stderr = self.stderr
        while iterations != 0:
            sleep(sleep_time)
            if self.stderr == curr_stderr and self.stdout == curr_stdout:
                break
            curr_stderr = self.stderr
            curr_stdout = self.stdout
            iterations -= 1

    def wait(self):
        while not self.is_finished():
            sleep(0.01)
        self.wait_output()

    def is_error_happened(self) -> bool:
        return (not self._alive and len(self.stderr) > 0
                and self.process.returncode != 0 or 'Traceback' in self.stderr)
コード例 #17
0
class Misc(Cog):
    def __init__(self, bot: CustomBot):
        super().__init__(self.__class__.__name__)
        self.bot = bot
        pid = getpid()
        self.process = Process(pid)
        self.process.cpu_percent()

    async def cog_command_error(self, ctx: Context, error):
        '''Local error handler for the cog'''

        # Throw errors properly for me
        if ctx.author.id in self.bot.config['owners'] and not isinstance(
                error, CommandOnCooldown):
            text = f'```py\n{error}```'
            await ctx.send(text)
            raise error

        # Cooldown
        if isinstance(error, CommandOnCooldown):
            if ctx.author.id in self.bot.config['owners']:
                await ctx.reinvoke()
            else:
                await ctx.send(
                    f"You can only use this command once every `{error.cooldown.per:.0f} seconds` per server. You may use this again in `{error.retry_after:.2f} seconds`."
                )
            return

        # Disabled command
        elif isinstance(error, DisabledCommand):
            if ctx.author.id in self.bot.config['owners']:
                await ctx.reinvoke()
            else:
                await ctx.send("This command has been disabled.")
            return

    @command(enabled=False, aliases=['upvote'])
    @cooldown(1, 5, BucketType.user)
    async def vote(self, ctx: Context):
        '''Gives you a link to upvote the bot'''

        if self.bot.config['dbl_vainity']:
            await ctx.send(
                f"<https://discordbots.org/bot/{self.bot.config['dbl_vainity']}/vote>\nSee {ctx.prefix}perks for more information."
            )
        else:
            await ctx.send(
                f"<https://discordbots.org/bot/{self.bot.user.id}/vote>\nSee {ctx.prefix}perks for more information."
            )

    @command(aliases=['git', 'code'])
    @cooldown(1, 5, BucketType.user)
    async def github(self, ctx: Context):
        '''Gives you a link to the bot's code repository'''

        await ctx.send(f"<{self.bot.config['github']}>")

    @command(aliases=['patreon', 'paypal'])
    @cooldown(1, 5, BucketType.user)
    async def donate(self, ctx: Context):
        '''Gives you the creator's donation links'''

        links = []
        if self.bot.config['patreon']:
            links.append(
                f"Patreon: <{self.bot.config['patreon']}> (see {ctx.prefix}perks to see what you get)"
            )
        if self.bot.config['paypal']:
            links.append(
                f"PayPal: <{self.bot.config['paypal']}> (doesn't get you the perks, but is very appreciated)"
            )
        if not links:
            ctx.command.enabled = False
            ctx.command.hidden = True
        await ctx.send('\n'.join(links))

    @command()
    @cooldown(1, 5, BucketType.user)
    async def invite(self, ctx: Context):
        '''Gives you an invite link for the bot'''

        await ctx.send(
            f"<https://discordapp.com/oauth2/authorize?client_id={self.bot.user.id}&scope=bot&permissions=314432>"
        )

    @command(aliases=['guild', 'support'])
    @cooldown(1, 5, BucketType.user)
    async def server(self, ctx: Context):
        '''Gives you a server invite link'''

        await ctx.send(self.bot.config['guild_invite'])

    @command(hidden=True)
    @cooldown(1, 5, BucketType.user)
    async def echo(self, ctx: Context, *, content: str):
        '''Echos a saying'''

        await ctx.send(content)

    @command(enabled=False)
    @cooldown(1, 5, BucketType.user)
    async def perks(self, ctx: Context):
        '''Shows you the perks associated with different support tiers'''

        # DISABLED UNTIL I KNOW WHAT TO DO WITH IT

        # Normies
        normal_users = [
            "60s tree cooldown",
            "5 children",
        ]

        # Perks for voting
        voting_perks = [
            "30s tree cooldown",
        ]

        # Perks for $1 Patrons
        t1_donate_perks = [
            "15s tree cooldown",
            "Up to 10 children",
            "`disownall` command (disowns all of your children at once)",
        ]

        # $3 Patrons
        t2_donate_perks = [
            "Up to 15 children",
            "`stupidtree` command (shows all relations, not just blood relatives)",
        ]

        # Perks for $5 Patrons
        t3_donate_perks = [
            "5s tree cooldown",
            "Up to 20 children",
        ]
        e = Embed()
        e.add_field(name=f'Normal Users',
                    value=f"Gives you access to:\n* " +
                    '\n* '.join(normal_users))
        e.add_field(name=f'Voting ({ctx.clean_prefix}vote)',
                    value=f"Gives you access to:\n* " +
                    '\n* '.join(voting_perks))
        e.add_field(name=f'T1 Patreon Donation ({ctx.clean_prefix}donate)',
                    value=f"Gives you access to:\n* " +
                    '\n* '.join(t1_donate_perks))
        e.add_field(name=f'T2 Patreon Donation ({ctx.clean_prefix}donate)',
                    value=f"Gives you access to:\n* " +
                    '\n* '.join(t2_donate_perks))
        e.add_field(name=f'T3 Patreon Donation ({ctx.clean_prefix}donate)',
                    value=f"Gives you access to:\n* " +
                    '\n* '.join(t3_donate_perks))
        await ctx.send(embed=e)

    @command(aliases=['status'])
    @cooldown(1, 5, BucketType.user)
    async def stats(self, ctx: Context):
        '''Gives you the stats for the bot'''

        # await ctx.channel.trigger_typing()
        embed = Embed(colour=0x1e90ff)
        embed.set_footer(text=str(self.bot.user),
                         icon_url=self.bot.user.avatar_url)
        embed.add_field(
            name="ProfileBot",
            value="A bot to make the process of filling out forms fun.")
        creator_id = self.bot.config["owners"][0]
        creator = await self.bot.fetch_user(creator_id)
        embed.add_field(name="Creator", value=f"{creator!s}\n{creator_id}")
        embed.add_field(name="Library", value=f"Discord.py {dpy_version}")
        try:
            embed.add_field(
                name="Average Guild Count",
                value=int((len(self.bot.guilds) / len(self.bot.shard_ids)) *
                          self.bot.shard_count))
        except TypeError:
            embed.add_field(name="Guild Count", value=len(self.bot.guilds))
        embed.add_field(name="Shard Count", value=self.bot.shard_count)
        embed.add_field(name="Average WS Latency",
                        value=f"{(self.bot.latency * 1000):.2f}ms")
        embed.add_field(
            name="Coroutines",
            value=
            f"{len([i for i in Task.all_tasks() if not i.done()])} running, {len(Task.all_tasks())} total."
        )
        embed.add_field(name="Process ID", value=self.process.pid)
        embed.add_field(name="CPU Usage",
                        value=f"{self.process.cpu_percent():.2f}")
        embed.add_field(
            name="Memory Usage",
            value=
            f"{self.process.memory_info()[0]/2**20:.2f}MB/{virtual_memory()[0]/2**20:.2f}MB"
        )
        # ut = self.bot.get_uptime()  # Uptime
        # uptime = [
        #     int(ut // (60*60*24)),
        #     int((ut % (60*60*24)) // (60*60)),
        #     int(((ut % (60*60*24)) % (60*60)) // 60),
        #     ((ut % (60*60*24)) % (60*60)) % 60,
        # ]
        # embed.add_field(name="Uptime", value=f"{uptime[0]} days, {uptime[1]} hours, {uptime[2]} minutes, and {uptime[3]:.2f} seconds.")
        try:
            await ctx.send(embed=embed)
        except Exception:
            await ctx.send("I tried to send an embed, but I couldn't.")

    @command(aliases=['clean'])
    async def clear(self, ctx: Context):
        '''Clears the bot's commands from chat'''

        if ctx.channel.permissions_for(ctx.guild.me).manage_messages:
            _ = await ctx.channel.purge(
                limit=100, check=lambda m: m.author.id == self.bot.user.id)
        else:
            _ = await ctx.channel.purge(
                limit=100,
                check=lambda m: m.author.id == self.bot.user.id,
                bulk=False)
        await ctx.send(f"Cleared `{len(_)}` messages from chat.",
                       delete_after=3.0)

    @command()
    async def shard(self, ctx: Context):
        '''Gives you the shard that your server is running on'''

        await ctx.send(
            f"The shard that your server is on is shard `{ctx.guild.shard_id}`."
        )
コード例 #18
0
 def get_cpu(self, process: Process) -> Percentage:
     """Get the process CPU usage."""
     try:
         return int(process.cpu_percent())
     except NoSuchProcess:
         return 0
コード例 #19
0
class Misc(Cog):

    def __init__(self, bot:CustomBot):
        super().__init__(self.__class__.__name__)
        self.bot = bot 
        pid = getpid()
        self.process = Process(pid)
        self.process.cpu_percent()


    async def cog_command_error(self, ctx:Context, error):
        '''Local error handler for the cog'''

        # Throw errors properly for me
        if ctx.original_author_id in self.bot.config['owners'] and not isinstance(error, CommandOnCooldown):
            text = f'```py\n{error}```'
            await ctx.send(text)
            raise error

        # Cooldown
        if isinstance(error, CommandOnCooldown):
            if ctx.original_author_id in self.bot.config['owners']:
                await ctx.reinvoke()
            else:
                await ctx.send(f"You can only use this command once every `{error.cooldown.per:.0f} seconds` per server. You may use this again in `{error.retry_after:.2f} seconds`.")
            return

        # Disabled command 
        elif isinstance(error, DisabledCommand):
            if ctx.original_author_id in self.bot.config['owners']:
                await ctx.reinvoke()
            else:
                await ctx.send("This command has been disabled.")
            return


    @command(aliases=['upvote'])
    @cooldown(1, 5, BucketType.user)
    async def vote(self, ctx:Context):
        '''Gives you a link to upvote the bot'''

        if self.bot.config['dbl_vainity']:
            await ctx.send(f"[Add a DBL vote](https://discordbots.org/bot/{self.bot.config['dbl_vainity']}/vote)!\nSee {ctx.prefix}perks for more information.")
        else:
            await ctx.send(f"[Add a DBL vote](https://discordbots.org/bot/{self.bot.user.id}/vote)!\nSee {ctx.prefix}perks for more information.")


    @command(aliases=['git', 'code'])
    @cooldown(1, 5, BucketType.user)
    async def github(self, ctx:Context):
        '''Gives you a link to the bot's code repository'''

        await ctx.send(f"<{self.bot.config['github']}>", embeddify=False)


    @command(aliases=['patreon', 'paypal'])
    @cooldown(1, 5, BucketType.user)
    async def donate(self, ctx:Context):
        '''Gives you the creator's donation links'''

        links = []
        if self.bot.config['patreon']:
            links.append(f"Patreon: <{self.bot.config['patreon']}> (see {ctx.prefix}perks to see what you get)")
        if self.bot.config['paypal']:
            links.append(f"PayPal: <{self.bot.config['paypal']}> (doesn't get you the perks, but is very appreciated)")
        if not links:
            ctx.command.enabled = False 
            ctx.command.hidden = True
        await ctx.send('\n'.join(links), embeddify=False)        


    @command()
    @cooldown(1, 5, BucketType.user)
    async def invite(self, ctx:Context):
        '''Gives you an invite link for the bot'''

        await ctx.send(f"<{self.bot.invite_link}>", embeddify=False)


    @command(aliases=['guild', 'support'])
    @cooldown(1, 5, BucketType.user)
    async def server(self, ctx:Context):
        '''Gives you a server invite link'''

        await ctx.send(self.bot.config['guild_invite'], embeddify=False)


    @command(hidden=True)
    @cooldown(1, 5, BucketType.user)
    async def echo(self, ctx:Context, *, content:str):
        '''Echos a saying'''

        await ctx.send(content, embeddify=False)


    @command()
    @cooldown(1, 5, BucketType.user)
    async def perks(self, ctx:Context):
        '''Shows you the perks associated with different support tiers'''

        # Normies
        normal_users = [
            "60s tree cooldown",
            "5 children",
        ]

        # Perks for voting
        voting_perks = [
            "30s tree cooldown",
        ]

        # Perks for $1 Patrons
        t1_donate_perks = [
            "15s tree cooldown",
            "Up to 10 children",
            "`disownall` command (disowns all of your children at once)",
        ]

        # $3 Patrons
        t2_donate_perks = [
            "Up to 15 children",
            "`stupidtree` command (shows all relations, not just blood relatives)",
        ]

        # Perks for $5 Patrons
        t3_donate_perks = [
            "5s tree cooldown",
            "Up to 20 children",
        ]

        # Perks for MarriageBot Gold
        gold_perks = [
            "Togglable incest",
            "Faster bot responses",
            "Server specific families",
            "Access to the `forcemarry`, `forcedivorce`, and `forceemancipate` commands"
        ]
        e = Embed()
        e.add_field(name=f'Normal Users', value=f"Gives you access to:\n* " + '\n* '.join(normal_users), inline=False)
        e.add_field(name=f'Voting ({ctx.clean_prefix}vote)', value=f"Gives you access to:\n* " + '\n* '.join(voting_perks), inline=False)
        e.add_field(name=f'T1 Patreon Donation ({ctx.clean_prefix}donate)', value=f"Gives you access to:\n* " + '\n* '.join(t1_donate_perks), inline=False)
        e.add_field(name=f'T2 Patreon Donation ({ctx.clean_prefix}donate)', value=f"Gives you access to:\n* " + '\n* '.join(t2_donate_perks), inline=False)
        e.add_field(name=f'T3 Patreon Donation ({ctx.clean_prefix}donate)', value=f"Gives you access to:\n* " + '\n* '.join(t3_donate_perks), inline=False)
        e.add_field(name=f'MarriageBot Gold ({ctx.clean_prefix}ssf)', value=f"Gvies you access to:\n* " + '\n* '.join(gold_perks), inline=False)
        await ctx.send(embed=e)


    @command(aliases=['status'])
    @cooldown(1, 5, BucketType.user)
    async def stats(self, ctx:Context):
        '''Gives you the stats for the bot'''       

        # await ctx.channel.trigger_typing()
        embed = Embed(
            colour=0x1e90ff
        )
        embed.set_footer(text=str(self.bot.user), icon_url=self.bot.user.avatar_url)
        embed.add_field(name="MarriageBot", value="A robot for marrying your friends and adopting your enemies.")
        creator_id = self.bot.config["owners"][0]
        creator = await self.bot.get_name(creator_id)
        embed.add_field(name="Creator", value=f"{creator}\n{creator_id}")
        embed.add_field(name="Library", value=f"Discord.py {dpy_version}")
        embed.add_field(name="Average Guild Count", value=int((len(self.bot.guilds) / len(self.bot.shard_ids)) * self.bot.shard_count))
        embed.add_field(name="Shard Count", value=self.bot.shard_count)
        embed.add_field(name="Average WS Latency", value=f"{(self.bot.latency * 1000):.2f}ms")
        embed.add_field(name="Coroutines", value=f"{len([i for i in Task.all_tasks() if not i.done()])} running, {len(Task.all_tasks())} total.")
        embed.add_field(name="Process ID", value=self.process.pid)
        embed.add_field(name="CPU Usage", value=f"{self.process.cpu_percent():.2f}")
        embed.add_field(name="Memory Usage", value=f"{self.process.memory_info()[0]/2**20:.2f}MB/{virtual_memory()[0]/2**20:.2f}MB")
        ut = self.bot.get_uptime()  # Uptime
        uptime = [
            int(ut // (60*60*24)),
            int((ut % (60*60*24)) // (60*60)),
            int(((ut % (60*60*24)) % (60*60)) // 60),
            ((ut % (60*60*24)) % (60*60)) % 60,
        ]
        embed.add_field(name="Uptime", value=f"{uptime[0]} days, {uptime[1]} hours, {uptime[2]} minutes, and {uptime[3]:.2f} seconds.")
        # embed.add_field(name="Family Members", value=len(FamilyTreeMember.all_users) - 1)
        try:
            await ctx.send(embed=embed)
        except Exception:
            await ctx.send("I tried to send an embed, but I couldn't.")


    @command(aliases=['clean'])
    async def clear(self, ctx:Context):
        '''Clears the bot's commands from chat'''

        if ctx.channel.permissions_for(ctx.guild.me).manage_messages:
            _ = await ctx.channel.purge(limit=100, check=lambda m: m.author.id == self.bot.user.id)
        else:
            _ = await ctx.channel.purge(limit=100, check=lambda m: m.author.id == self.bot.user.id, bulk=False)
        await ctx.send(f"Cleared `{len(_)}` messages from chat.", delete_after=3.0)


    @command()
    async def block(self, ctx:Context, user:Member):
        '''Blocks a user from being able to adopt/makeparent/whatever you'''

        current_blocks = self.bot.blocked_users.get(ctx.author.id, list())
        if user.id in current_blocks:
            await ctx.send("That user is already blocked.")
            return 
        current_blocks.append(user.id)
        self.bot.blocked_users[ctx.author.id] = current_blocks
        async with self.bot.database() as db:
            await db(
                'INSERT INTO blocked_user (user_id, blocked_user_id) VALUES ($1, $2)',
                ctx.author.id, user.id
            )
        await ctx.send("That user is now blocked.")


    @command()
    async def unblock(self, ctx:Context, user:UserID):
        '''Unblocks a user and allows them to adopt/makeparent/whatever you'''

        # Get the current blocks for a user
        current_blocks = self.bot.blocked_users[ctx.author.id]
        if user not in current_blocks:
            await ctx.send("You don't have that user blocked.")
            return 
        current_blocks.remove(user)
        self.bot.blocked_users[ctx.author.id] = current_blocks
        async with self.bot.database() as db:
            await db(
                'DELETE FROM blocked_user WHERE user_id=$1 AND blocked_user_id=$2',
                ctx.author.id, user
            )
        await ctx.send("That user is now unblocked.")


    @command()
    async def shard(self, ctx:Context):
        '''Gives you the shard that your server is running on'''

        await ctx.send(f"The shard that your server is on is shard `{ctx.guild.shard_id}`.")


    @command(enabled=False)
    @cooldown(1, 5, BucketType.guild)
    async def toptree(self, ctx:Context):
        '''Gives you the amount of users in the top tree'''

        async with ctx.channel.typing():
            top_users = max([len(i.span(add_parent=True, expand_upwards=True)) for i in FamilyTreeMember.all_users.copy().values() if i])
        await ctx.send(f"The top tree I handle has `{top_users}` users in it.")
コード例 #20
0
class Misc(Cog):
    def __init__(self, bot: CustomBot):
        super().__init__(self.__class__.__name__)
        self.bot = bot
        pid = getpid()
        self.process = Process(pid)
        self.process.cpu_percent()

    async def cog_command_error(self, ctx: Context, error):
        '''
        Local error handler for the cog
        '''

        # Throw errors properly for me
        if ctx.author.id in self.bot.config['owners'] and not isinstance(
                error, CommandOnCooldown):
            text = f'```py\n{error}```'
            await ctx.send(text)
            raise error

        # Cooldown
        if isinstance(error, CommandOnCooldown):
            if ctx.author.id in self.bot.config['owners']:
                await ctx.reinvoke()
            else:
                await ctx.send(
                    f"You can only use this command once every `{error.cooldown.per:.0f} seconds` per server. You may use this again in `{error.retry_after:.2f} seconds`."
                )
            return

    @command(aliases=['upvote'])
    @cooldown(1, 5, BucketType.user)
    async def vote(self, ctx: Context):
        '''
        Gives you a link to upvote the bot
        '''

        if self.bot.config['dbl_vainity']:
            await ctx.send(
                f"<https://discordbots.org/bot/{self.bot.config['dbl_vainity']}/vote>",
                embeddify=False)
        else:
            await ctx.send(
                f"<https://discordbots.org/bot/{self.bot.user.id}/vote>",
                embeddify=False)

    @command(aliases=['git', 'code'])
    @cooldown(1, 5, BucketType.user)
    async def github(self, ctx: Context):
        '''
        Gives you a link to the bot's code repository
        '''

        await ctx.send(f"<{self.bot.config['github']}>", embeddify=False)

    @command(aliases=['patreon', 'paypal'])
    @cooldown(1, 5, BucketType.user)
    async def donate(self, ctx: Context):
        '''
        Gives you the creator's donation links
        '''

        links = []
        if self.bot.config['patreon']:
            links.append(f"Patreon: <{self.bot.config['patreon']}>")
        if self.bot.config['paypal']:
            links.append(
                f"PayPal: <{self.bot.config['paypal']}> (doesn't get you the perks, but is very appreciated)"
            )
        if not links:
            return
        await ctx.send('\n'.join(links), embeddify=False)

    @command()
    @cooldown(1, 5, BucketType.user)
    async def invite(self, ctx: Context):
        '''
        Gives you an invite link for the bot
        '''

        await ctx.send(
            f"<https://discordapp.com/oauth2/authorize?client_id={self.bot.user.id}&scope=bot&permissions=35840>",
            embeddify=False)

    @command(aliases=['guild', 'support'])
    @cooldown(1, 5, BucketType.user)
    async def server(self, ctx: Context):
        '''
        Gives you a server invite link
        '''

        await ctx.send(self.bot.config['guild'], embeddify=False)

    @command(hidden=True)
    @cooldown(1, 5, BucketType.user)
    async def echo(self, ctx: Context, *, content: str):
        '''
        Echos a saying
        '''

        await ctx.send(content, embeddify=False)

    @command(aliases=['status'])
    @cooldown(1, 5, BucketType.user)
    async def stats(self, ctx: Context):
        '''
        Gives you the stats for the bot
        '''

        # await ctx.channel.trigger_typing()
        embed = Embed(colour=0x1e90ff)
        embed.set_footer(text=str(self.bot.user),
                         icon_url=self.bot.user.avatar_url)
        embed.add_field(
            name="MarriageBot",
            value="A robot for marrying your friends and adopting your enemies."
        )
        creator = self.bot.get_user(self.bot.config["owners"][0])
        embed.add_field(name="Creator", value=f"{creator!s}\n{creator.id}")
        embed.add_field(name="Library", value=f"Discord.py {dpy_version}")
        embed.add_field(name="Guild Count", value=len(self.bot.guilds))
        embed.add_field(name="Shard Count", value=self.bot.shard_count)
        embed.add_field(name="Average Latency",
                        value=f"{(self.bot.latency * 1000):.2f}ms")
        embed.add_field(name="Member Count",
                        value=sum((len(i.members) for i in self.bot.guilds)))
        embed.add_field(
            name="Coroutines",
            value=
            f"{len([i for i in Task.all_tasks() if not i.done()])} running, {len(Task.all_tasks())} total."
        )
        embed.add_field(name="Process ID", value=self.process.pid)
        embed.add_field(name="CPU Usage",
                        value=f"{self.process.cpu_percent():.2f}")
        embed.add_field(
            name="Memory Usage",
            value=
            f"{self.process.memory_info()[0]/2**20:.2f}MB/{virtual_memory()[0]/2**20:.2f}MB"
        )
        ut = self.bot.get_uptime()  # Uptime
        uptime = [
            int(ut // (60 * 60 * 24)),
            int((ut % (60 * 60 * 24)) // (60 * 60)),
            int(((ut % (60 * 60 * 24)) % (60 * 60)) // 60),
            ((ut % (60 * 60 * 24)) % (60 * 60)) % 60,
        ]
        embed.add_field(
            name="Uptime",
            value=
            f"{uptime[0]} days, {uptime[1]} hours, {uptime[2]} minutes, and {uptime[3]:.2f} seconds."
        )
        # embed.add_field(name="Family Members", value=len(FamilyTreeMember.all_users) - 1)
        try:
            await ctx.send(embed=embed)
        except Exception:
            await ctx.send("I tried to send an embed, but I couldn't.")

    @command(aliases=['clean'])
    async def clear(self, ctx: Context):
        '''
        Clears the bot's commands from chat
        '''

        if ctx.channel.permissions_for(ctx.guild.me).manage_messages:
            _ = await ctx.channel.purge(
                limit=100, check=lambda m: m.author.id == self.bot.user.id)
        else:
            _ = await ctx.channel.purge(
                limit=100,
                check=lambda m: m.author.id == self.bot.user.id,
                bulk=False)
        await ctx.send(f"Cleared `{len(_)}` messages from chat.",
                       delete_after=3.0)

    @command()
    async def block(self, ctx: Context, user: Member):
        '''
        Blocks a user from being able to adopt/makeparent/whatever you
        '''

        current_blocks = self.bot.blocked_users.get(ctx.author.id, list())
        if user.id in current_blocks:
            await ctx.send("That user is already blocked.")
            return
        current_blocks.append(user.id)
        self.bot.blocked_users[ctx.author.id] = current_blocks
        async with self.bot.database() as db:
            await db(
                'INSERT INTO blocked_user (user_id, blocked_user_id) VALUES ($1, $2)',
                ctx.author.id, user.id)
        await ctx.send("That user is now blocked.")

    @command()
    async def unblock(self, ctx: Context, user: Member):
        '''
        Unblocks a user and allows them to adopt/makeparent/whatever you
        '''

        current_blocks = self.bot.blocked_users.get(ctx.author.id, list())
        if user.id not in current_blocks:
            await ctx.send("You don't have that user blocked.")
            return
        current_blocks.remove(user.id)
        self.bot.blocked_users[ctx.author.id] = current_blocks
        async with self.bot.database() as db:
            await db(
                'DELETE FROM blocked_user WHERE user_id=$1 AND blocked_user_id=$2',
                ctx.author.id, user.id)
        await ctx.send("That user is now unblocked.")
コード例 #21
0
    async def botinfo(self, ctx):
        """Viser info om meg"""

        dev = await self.bot.fetch_user(170506717140877312)

        now = time()
        diff = int(now - self.bot.uptime)
        days, remainder = divmod(diff, 24 * 60 * 60)
        hours, remainder = divmod(remainder, 60 * 60)
        minutes, seconds = divmod(remainder, 60)

        process = Process(getpid())
        memory_usage = round(process.memory_info().rss / 1000000, 1)
        cpu_percent = process.cpu_percent()

        total_members = []
        online_members = []
        idle_members = []
        dnd_members = []
        offline_members = []
        for guild in self.bot.guilds:
            for member in guild.members:
                if member.id in total_members:
                    continue
                total_members.append(member.id)
                if str(member.status) == 'online':
                    online_members.append(member.id)
                elif str(member.status) == 'idle':
                    idle_members.append(member.id)
                elif str(member.status) == 'dnd':
                    dnd_members.append(member.id)
                elif str(member.status) == 'offline':
                    offline_members.append(member.id)

        embed = discord.Embed(color=ctx.me.color, url=website)
        embed.set_author(name=dev.name, icon_url=dev.avatar_url)
        embed.set_thumbnail(url=self.bot.user.avatar_url)
        embed.add_field(name='Dev',
                        value=f'{dev.mention}\n{dev.name}#{dev.discriminator}')
        embed.add_field(name='Oppetid',
                        value=f'{days}d {hours}t {minutes}m {seconds}s')
        embed.add_field(name='Ping',
                        value=f'{int(self.bot.latency * 1000)} ms')
        embed.add_field(name='Servere', value=len(self.bot.guilds))
        embed.add_field(name='Discord.py Versjon', value=discord.__version__)
        embed.add_field(name='Python Versjon', value=platform.python_version())
        embed.add_field(name='Ressursbruk',
                        value=f'RAM: {memory_usage} MB\nCPU: {cpu_percent}%')
        embed.add_field(name='Maskin',
                        value=f'{platform.system()} {platform.release()}')
        embed.add_field(
            name=f'Brukere ({len(total_members)})',
            value=f'<:online:516328785910431754>{len(online_members)} ' +
            f'<:idle:516328783347843082>{len(idle_members)} ' +
            f'<:dnd:516328782844395579>{len(dnd_members)} ' +
            f'<:offline:516328785407246356>{len(offline_members)}')
        embed.add_field(
            name='Lenker',
            value='[Inviter](https://discordapp.com/oauth2/authorize?client_' +
            f'id={self.bot.user.id}&permissions=388174&scope=bot) ' +
            f'| [Nettside]({website}) | [Kildekode]({github})')
        await Defaults.set_footer(ctx, embed)
        await ctx.send(embed=embed)
コード例 #22
0
class _ProcessMonitor:
    WARNING_THRESHOLD = 100 * 1024 * 1024

    busy = False

    def __init__(self):
        self.process = Process()
        self.peak_mem_res = 0
        self.low_mem_warning = False

    def monitor_task(self):
        if sys.stdout.isatty():

            while self.busy:
                try:
                    # only print the data out every 10 seconds
                    if datetime.now().second / 10 == 0:
                        info = self._get_info()

                        output.debug(info)
                    else:
                        # call get_mem so that we record peak more accurately
                        self._get_mem()

                    time.sleep(1)
                except Exception:
                    output.debug_exception()

                    self.busy = False

                    pass
        else:
            # if this isn't a TTY, no point in doing any of this
            self.busy = False

    def _get_info(self) -> str:
        from yawast.external.memory_size import Size

        # prime the call to cpu_percent, as the first call doesn't return useful data
        self.process.cpu_percent(interval=1)

        # use oneshot() to cache the data, so we minimize hits
        with self.process.oneshot():
            pct = self.process.cpu_percent()

            times = self.process.cpu_times()
            mem = self._get_mem()
            mem_res = "{0:cM}".format(Size(mem.rss))
            mem_virt = "{0:cM}".format(Size(mem.vms))

            thr = self.process.num_threads()

            vm = psutil.virtual_memory()
            mem_total = "{0:cM}".format(Size(vm.total))
            mem_avail_bytes = vm.available
            mem_avail = "{0:cM}".format(Size(vm.available))

            if mem_avail_bytes < self.WARNING_THRESHOLD and not self.low_mem_warning:
                self.low_mem_warning = True

                output.error(f"Low RAM Available: {mem_avail}")

            cons = -1
            try:
                cons = len(self.process.connections(kind="inet"))
            except Exception:
                # we don't care if this fails
                output.debug_exception()

            cpu_freq = psutil.cpu_freq()

        info = (f"Process Stats: CPU: {pct}% - Sys: {times.system} - "
                f"User: {times.user} - Res: {mem_res} - Virt: {mem_virt} - "
                f"Available: {mem_avail}/{mem_total} - Threads: {thr} - "
                f"Connections: {cons} - CPU Freq: "
                f"{int(cpu_freq.current)}MHz/{int(cpu_freq.max)}MHz")

        return info

    def _get_mem(self):
        mem = self.process.memory_info()

        if mem.rss > self.peak_mem_res:
            self.peak_mem_res = mem.rss
            output.debug(f"New high-memory threshold: {self.peak_mem_res}")

        return mem

    def __enter__(self):
        self.busy = True
        threading.Thread(target=self.monitor_task).start()

        return self

    def __exit__(self, exception, value, tb):
        self.busy = False

        if exception is not None:
            return False
コード例 #23
0
class CPUUsage(Metric[float]):
    """
    The standalone CPU usage metric.

    Instances of this metric compute the average CPU usage as a float value.
    The metric starts tracking the CPU usage when the `update` method is called
    for the first time. That is, the tracking does not start at the time the
    constructor is invoked.

    Calling the `update` method more than twice will update the metric to the
    average usage between the first and the last call to `update`.

    The result, obtained using the `result` method, is the usage computed
    as stated above.

    The reset method will bring the metric to its initial state. By default
    this metric in its initial state will return an usage value of 0.
    """
    def __init__(self):
        """
        Creates an instance of the standalone CPU usage metric.

        By default this metric in its initial state will return a CPU usage
        value of 0. The metric can be updated by using the `update` method
        while the average CPU usage can be retrieved using the `result` method.
        """

        self._mean_usage = Mean()
        """
        The mean utility that will be used to store the average usage.
        """

        self._process_handle: Optional[Process] = None
        """
        The process handle, lazily initialized.
        """

        self._first_update = True
        """
        An internal flag to keep track of the first call to the `update` method.
        """

    def update(self) -> None:
        """
        Update the running CPU usage.

        For more info on how to set the starting moment see the class
        description.

        :return: None.
        """
        if self._first_update:
            self._process_handle = Process(os.getpid())

        last_time = getattr(self._process_handle, '_last_sys_cpu_times', None)
        utilization = self._process_handle.cpu_percent()
        current_time = getattr(self._process_handle, '_last_sys_cpu_times',
                               None)

        if self._first_update:
            self._first_update = False
        else:
            if current_time is None or last_time is None:
                warnings.warn('CPUUsage can\'t detect the elapsed time. It is '
                              'recommended to update avalanche to the latest '
                              'version.')
                # Fallback, shouldn't happen
                current_time = 1.0
                last_time = 0.0
            self._mean_usage.update(utilization, current_time - last_time)

    def result(self) -> float:
        """
        Retrieves the average CPU usage.

        Calling this method will not change the internal state of the metric.

        :return: The average CPU usage, as a float value.
        """
        return self._mean_usage.result()

    def reset(self) -> None:
        """
        Resets the metric.

        :return: None.
        """
        self._mean_usage.reset()
        self._process_handle = None
        self._first_update = True
コード例 #24
0
 def _get_cpu_percent(process: psutil.Process):
     return process.cpu_percent()
コード例 #25
0
ファイル: BotInfo.py プロジェクト: Roxedus/MornBot
    async def botinfo(self, ctx):
        """Viser info om meg"""

        dev = await self.bot.fetch_user(170506717140877312)

        start = perf_counter()
        status_msg = await ctx.send('Beregner ping...')
        end = perf_counter()
        ping = int((end - start) * 1000)

        now = time()
        diff = int(now - self.bot.uptime)
        days, remainder = divmod(diff, 24 * 60 * 60)
        hours, remainder = divmod(remainder, 60 * 60)
        minutes, seconds = divmod(remainder, 60)

        process = Process(getpid())
        memory_usage = round(process.memory_info().rss / 1000000, 1)
        cpu_percent = process.cpu_percent()

        total_members = []
        online_members = []
        idle_members = []
        dnd_members = []
        offline_members = []
        for guild in self.bot.guilds:
            for member in guild.members:
                if member.id in total_members:
                    continue
                total_members.append(member.id)
                if str(member.status) == 'online':
                    online_members.append(member.id)
                elif str(member.status) == 'idle':
                    idle_members.append(member.id)
                elif str(member.status) == 'dnd':
                    dnd_members.append(member.id)
                elif str(member.status) == 'offline':
                    offline_members.append(member.id)

        embed = discord.Embed(color=ctx.me.color, url=self.bot.misc['website'])
        embed.set_author(name=dev.name, icon_url=dev.avatar_url)
        embed.set_thumbnail(url=self.bot.user.avatar_url)
        embed.add_field(name='Dev',
                        value=f'{dev.mention}\n{dev.name}#{dev.discriminator}')
        embed.add_field(name='Oppetid',
                        value=f'{days}d {hours}t {minutes}m {seconds}s')
        embed.add_field(
            name='Ping',
            value=
            f'Ekte ping: {ping} ms\nWebsocket ping: {int(self.bot.latency * 1000)} ms'
        )
        embed.add_field(name='Servere', value=len(self.bot.guilds))
        embed.add_field(name='Discord.py Versjon', value=discord.__version__)
        embed.add_field(name='Python Versjon', value=platform.python_version())
        embed.add_field(name='Ressursbruk',
                        value=f'RAM: {memory_usage} MB\nCPU: {cpu_percent}%')
        embed.add_field(name='Maskin',
                        value=f'{platform.system()} {platform.release()}')
        embed.add_field(
            name=f'Brukere ({len(total_members)})',
            value=f'{self.bot.emoji["online"]}{len(online_members)} ' +
            f'{self.bot.emoji["idle"]}{len(idle_members)} ' +
            f'{self.bot.emoji["dnd"]}{len(dnd_members)} ' +
            f'{self.bot.emoji["offline"]}{len(offline_members)}')
        embed.add_field(
            name='Lenker',
            value='[Inviter](https://discordapp.com/oauth2/authorize?client_' +
            f'id={self.bot.user.id}&permissions=388174&scope=bot) ' +
            f'| [Nettside]({self.bot.misc["website"]}) ' +
            f'| [Kildekode]({self.bot.misc["source_code"]})')
        await Defaults.set_footer(ctx, embed)
        await status_msg.edit(embed=embed, content=None)
コード例 #26
0
ファイル: text_ui.py プロジェクト: Clohman11/mpf
class TextUi(MpfController):
    """Handles the text-based UI."""

    config_name = "text_ui"

    __slots__ = [
        "start_time", "machine", "_tick_task", "screen", "mpf_process",
        "ball_devices", "switches", "config", "_pending_bcp_connection",
        "_asset_percent", "_player_widgets", "_machine_widgets", "_bcp_status",
        "frame", "layout", "scene", "footer_memory", "switch_widgets",
        "mode_widgets", "ball_device_widgets", "footer_cpu", "footer_mc_cpu",
        "footer_uptime", "delay", "_layout_change"
    ]

    def __init__(self, machine: "MachineController") -> None:
        """Initialize TextUi."""
        super().__init__(machine)
        self.delay = DelayManager(machine)
        self.config = machine.config.get('text_ui', {})

        self.screen = None

        if not machine.options['text_ui'] or not Scene:
            return

        # hack to add themes until https://github.com/peterbrittain/asciimatics/issues/207 is implemented
        THEMES["mpf_theme"] = defaultdict(
            lambda:
            (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_BLACK), {
                "active_switch":
                (Screen.COLOUR_BLACK, Screen.A_NORMAL, Screen.COLOUR_GREEN),
                "pf_active":
                (Screen.COLOUR_GREEN, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "pf_inactive":
                (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "label":
                (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "title":
                (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_RED),
                "title_exit":
                (Screen.COLOUR_BLACK, Screen.A_NORMAL, Screen.COLOUR_RED),
                "footer_cpu":
                (Screen.COLOUR_CYAN, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "footer_path":
                (Screen.COLOUR_YELLOW, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "footer_memory":
                (Screen.COLOUR_GREEN, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "footer_mc_cpu":
                (Screen.COLOUR_MAGENTA, Screen.A_NORMAL, Screen.COLOUR_BLACK),
            })

        self.start_time = datetime.now()
        self.machine = machine

        self.mpf_process = Process()
        self.ball_devices = list()  # type: List[BallDevice]

        self.switches = {}  # type: Dict[str, Switch]

        self.machine.events.add_handler('init_phase_2', self._init)
        # self.machine.events.add_handler('init_phase_3', self._init2)
        self.machine.events.add_handler('loading_assets',
                                        self._asset_load_change)
        self.machine.events.add_handler('bcp_connection_attempt',
                                        self._bcp_connection_attempt)
        self.machine.events.add_handler('asset_loading_complete',
                                        self._asset_load_complete)
        self.machine.events.add_handler('bcp_clients_connected',
                                        self._bcp_connected)
        self.machine.events.add_handler('shutdown', self.stop)
        self.machine.add_crash_handler(self.stop)
        self.machine.events.add_handler('player_number', self._update_player)
        self.machine.events.add_handler('player_ball', self._update_player)
        self.machine.events.add_handler('player_score', self._update_player)
        self.machine.events.add_handler('ball_ended', self._update_player)

        self._pending_bcp_connection = False
        self._asset_percent = 0
        self._bcp_status = (0, 0, 0)  # type: Tuple[float, int, int]
        self.switch_widgets = []  # type: List[Widget]
        self.mode_widgets = []  # type: List[Widget]
        self.ball_device_widgets = []  # type: List[Widget]
        self._machine_widgets = []  # type: List[Widget]
        self._player_widgets = []  # type: List[Widget]
        self.footer_memory = None
        self.footer_cpu = None
        self.footer_mc_cpu = None
        self.footer_uptime = None
        self._layout_change = True

        self._tick_task = self.machine.clock.schedule_interval(self._tick, 1)
        self._create_window()
        self._draw_screen()

    def _init(self, **kwargs):
        del kwargs
        for mode in self.machine.modes.values():
            self.machine.events.add_handler(
                "mode_{}_started".format(mode.name), self._mode_change)
            self.machine.events.add_handler(
                "mode_{}_stopped".format(mode.name), self._mode_change)

        self.machine.switch_controller.add_monitor(self._update_switches)
        self.machine.register_monitor("machine_vars",
                                      self._update_machine_vars)
        self.machine.variables.machine_var_monitor = True
        self.machine.bcp.interface.register_command_callback(
            "status_report", self._bcp_status_report)

        for bd in [
                x for x in self.machine.ball_devices.values()
                if not x.is_playfield()
        ]:
            self.ball_devices.append(bd)

        self.ball_devices.sort()

        self._update_switch_layout()
        self._schedule_draw_screen()

    async def _bcp_status_report(self, client, cpu, rss, vms):
        del client
        self._bcp_status = cpu, rss, vms

    def _update_stats(self):
        # Runtime
        rt = (datetime.now() - self.start_time)
        mins, sec = divmod(rt.seconds + rt.days * 86400, 60)
        hours, mins = divmod(mins, 60)
        self.footer_uptime.text = 'RUNNING {:d}:{:02d}:{:02d}'.format(
            hours, mins, sec)

        # System Stats
        self.footer_memory.text = 'Free Memory (MB): {} CPU:{:3d}%'.format(
            round(virtual_memory().available / 1048576),
            round(cpu_percent(interval=None, percpu=False)))

        # MPF process stats
        self.footer_cpu.text = 'MPF (CPU RSS/VMS): {}% {}/{} MB    '.format(
            round(self.mpf_process.cpu_percent()),
            round(self.mpf_process.memory_info().rss / 1048576),
            round(self.mpf_process.memory_info().vms / 1048576))

        # MC process stats
        if self._bcp_status != (0, 0, 0):
            self.footer_mc_cpu.text = 'MC (CPU RSS/VMS) {}% {}/{} MB '.format(
                round(self._bcp_status[0]),
                round(self._bcp_status[1] / 1048576),
                round(self._bcp_status[2] / 1048576))
        else:
            self.footer_mc_cpu.text = ""

    def _update_switch_layout(self):
        num = 0
        self.switch_widgets = []
        self.switches = {}
        self.switch_widgets.append((Label("SWITCHES"), 1))
        self.switch_widgets.append((Divider(), 1))
        self.switch_widgets.append((Label(""), 2))
        self.switch_widgets.append((Divider(), 2))

        for sw in sorted(self.machine.switches.values()):
            if sw.invert:
                name = sw.name + '*'
            else:
                name = sw.name

            col = 1 if num <= int(len(self.machine.switches) / 2) else 2

            switch_widget = Label(name)
            if sw.state:
                switch_widget.custom_colour = "active_switch"

            self.switch_widgets.append((switch_widget, col))
            self.switches[sw.name] = (sw, switch_widget)

            num += 1

        self._schedule_draw_screen()

    def _update_switches(self, change, *args, **kwargs):
        del args
        del kwargs
        try:
            sw, switch_widget = self.switches[change.name]
        except KeyError:
            return
        if sw.state:
            switch_widget.custom_colour = "active_switch"
        else:
            switch_widget.custom_colour = "label"

        self._schedule_draw_screen()

    def _draw_switches(self):
        """Draw all switches."""
        for widget, column in self.switch_widgets:
            self.layout.add_widget(widget, column)

    def _mode_change(self, *args, **kwargs):
        # Have to call this on the next frame since the mode controller's
        # active list isn't updated yet
        del args
        del kwargs
        self.mode_widgets = []
        self.mode_widgets.append(Label("ACTIVE MODES"))
        self.mode_widgets.append(Divider())
        try:
            modes = self.machine.mode_controller.active_modes
        except AttributeError:
            modes = None

        if modes:
            for mode in modes:
                self.mode_widgets.append(
                    Label('{} ({})'.format(mode.name, mode.priority)))
        else:
            self.mode_widgets.append(Label("No active modes"))

        # empty line at the end
        self.mode_widgets.append(Label(""))

        self._layout_change = True
        self._schedule_draw_screen()

    def _draw_modes(self):
        for widget in self.mode_widgets:
            self.layout.add_widget(widget, 0)

    def _draw_ball_devices(self):
        for widget in self.ball_device_widgets:
            self.layout.add_widget(widget, 3)

    def _update_ball_devices(self, **kwargs):
        del kwargs
        # TODO: do not create widgets. just update contents
        self.ball_device_widgets = []
        self.ball_device_widgets.append(Label("BALL COUNTS"))
        self.ball_device_widgets.append(Divider())

        try:
            for pf in self.machine.playfields.values():
                widget = Label('{}: {} '.format(pf.name, pf.balls))
                if pf.balls:
                    widget.custom_colour = "pf_active"
                else:
                    widget.custom_colour = "pf_inactive"
                self.ball_device_widgets.append(widget)

        except AttributeError:
            pass

        for bd in self.ball_devices:
            widget = Label('{}: {} ({})'.format(bd.name, bd.balls, bd.state))
            if bd.balls:
                widget.custom_colour = "pf_active"
            else:
                widget.custom_colour = "pf_inactive"

            self.ball_device_widgets.append(widget)

        self.ball_device_widgets.append(Label(""))

        self._layout_change = True
        self._schedule_draw_screen()

    def _update_player(self, **kwargs):
        del kwargs
        self._player_widgets = []
        self._player_widgets.append(Label("CURRENT PLAYER"))
        self._player_widgets.append(Divider())

        try:
            player = self.machine.game.player
            self._player_widgets.append(
                Label('PLAYER: {}'.format(player.number)))
            self._player_widgets.append(Label('BALL: {}'.format(player.ball)))
            self._player_widgets.append(
                Label('SCORE: {:,}'.format(player.score)))
        except AttributeError:
            self._player_widgets.append(Label("NO GAME IN PROGRESS"))
            return

        player_vars = player.vars.copy()
        player_vars.pop('score', None)
        player_vars.pop('number', None)
        player_vars.pop('ball', None)

        names = self.config.get('player_vars', player_vars.keys())
        for name in names:
            self._player_widgets.append(
                Label("{}: {}".format(name, player_vars[name])))

        self._layout_change = True
        self._schedule_draw_screen()

    def _draw_player(self, **kwargs):
        del kwargs
        for widget in self._player_widgets:
            self.layout.add_widget(widget, 3)

    def _update_machine_vars(self, **kwargs):
        """Update machine vars."""
        del kwargs
        self._machine_widgets = []
        self._machine_widgets.append(Label("MACHINE VARIABLES"))
        self._machine_widgets.append(Divider())
        machine_vars = self.machine.variables.machine_vars
        # If config defines explict vars to show, only show those. Otherwise, all
        names = self.config.get('machine_vars', machine_vars.keys())
        for name in names:
            self._machine_widgets.append(
                Label("{}: {}".format(name, machine_vars[name]['value'])))
        self._layout_change = True
        self._schedule_draw_screen()

    def _draw_machine_variables(self):
        """Draw machine vars."""
        for widget in self._machine_widgets:
            self.layout.add_widget(widget, 0)

    def _create_window(self):
        self.screen = Screen.open()
        self.frame = Frame(self.screen,
                           self.screen.height,
                           self.screen.width,
                           has_border=False,
                           title="Test")
        self.frame.set_theme("mpf_theme")

        title_layout = Layout([1, 5, 1])
        self.frame.add_layout(title_layout)

        title_left = Label("")
        title_left.custom_colour = "title"
        title_layout.add_widget(title_left, 0)

        title = 'Mission Pinball Framework v{}'.format(
            mpf._version.__version__)  # noqa
        title_text = Label(title, align="^")
        title_text.custom_colour = "title"
        title_layout.add_widget(title_text, 1)

        exit_label = Label("< CTRL + C > TO EXIT", align=">")
        exit_label.custom_colour = "title_exit"

        title_layout.add_widget(exit_label, 2)

        self.layout = MpfLayout([1, 1, 1, 1], fill_frame=True)
        self.frame.add_layout(self.layout)

        footer_layout = Layout([1, 1, 1])
        self.frame.add_layout(footer_layout)
        self.footer_memory = Label("", align=">")
        self.footer_memory.custom_colour = "footer_memory"
        self.footer_uptime = Label("", align=">")
        self.footer_uptime.custom_colour = "footer_memory"
        self.footer_mc_cpu = Label("")
        self.footer_mc_cpu.custom_colour = "footer_mc_cpu"
        self.footer_cpu = Label("")
        self.footer_cpu.custom_colour = "footer_cpu"
        footer_path = Label(self.machine.machine_path)
        footer_path.custom_colour = "footer_path"
        footer_empty = Label("")
        footer_empty.custom_colour = "footer_memory"

        footer_layout.add_widget(footer_path, 0)
        footer_layout.add_widget(self.footer_cpu, 0)
        footer_layout.add_widget(footer_empty, 1)
        footer_layout.add_widget(self.footer_mc_cpu, 1)
        footer_layout.add_widget(self.footer_uptime, 2)
        footer_layout.add_widget(self.footer_memory, 2)

        self.scene = Scene([self.frame], -1)
        self.screen.set_scenes([self.scene], start_scene=self.scene)

        # prevent main from scrolling out the footer
        self.layout.set_max_height(self.screen.height - 2)

    def _schedule_draw_screen(self):
        # schedule the draw in 10ms if it is not scheduled
        self.delay.add_if_doesnt_exist(10, self._draw_screen, "draw_screen")

    def _draw_screen(self):
        if not self.screen:
            # probably drawing during game end
            return

        if self._layout_change:
            self.layout.clear_columns()
            self._draw_modes()
            self._draw_machine_variables()
            self._draw_switches()
            self._draw_ball_devices()
            self._draw_player()
            self.frame.fix()
            self._layout_change = False

        self.screen.force_update()
        self.screen.draw_next_frame()

    def _tick(self):
        if self.screen.has_resized():
            self._create_window()

        self._update_ball_devices()
        self._update_stats()

        self._schedule_draw_screen()

        self.machine.bcp.transport.send_to_clients_with_handler(
            handler="_status_request", bcp_command="status_request")

    def _bcp_connection_attempt(self, name, host, port, **kwargs):
        del name
        del kwargs
        self._pending_bcp_connection = PopUpDialog(
            self.screen,
            'WAITING FOR MEDIA CONTROLLER {}:{}'.format(host, port), [])
        self.scene.add_effect(self._pending_bcp_connection)
        self._schedule_draw_screen()

    def _bcp_connected(self, **kwargs):
        del kwargs
        self.scene.remove_effect(self._pending_bcp_connection)
        self._schedule_draw_screen()

    def _asset_load_change(self, percent, **kwargs):
        del kwargs
        if self._asset_percent:
            self.scene.remove_effect(self._asset_percent)
        self._asset_percent = PopUpDialog(
            self.screen, 'LOADING ASSETS: {}%'.format(percent), [])
        self.scene.add_effect(self._asset_percent)
        self._schedule_draw_screen()

    def _asset_load_complete(self, **kwargs):
        del kwargs
        self.scene.remove_effect(self._asset_percent)
        self._schedule_draw_screen()

    def stop(self, **kwargs):
        """Stop the Text UI and restore the original console screen."""
        del kwargs
        if self.screen:
            self.machine.clock.unschedule(self._tick_task)
            self.screen.close(True)
            self.screen = None
コード例 #27
0
class FactorioManager(object):
    def __init__(self, name: str, port: int, root_path, is_steam=False):
        self.name = name
        self.port = port
        self.process = None
        self.root_path = Path(root_path)
        self.log = make_log(f'{name}_factorio')
        self.update_available = False
        self._ps_proc = None
        self._virtual_mem = VIRTUAL_MEMORY
        self._is_steam = is_steam
        self._player_data = None
        self._config = None
        self._server_config = None
        self._version_info = None
        self._available_versions = None
        self._temp_update = None
        self._log_queue = deque(maxlen=20)
        self._status_history = deque(maxlen=50)

    @property
    def version(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['version']

    @property
    def build(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['build']

    @property
    def build_num(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['build']['number']

    @property
    def build_platform(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['build']['platform']

    @property
    def build_mode(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['build']['mode']

    @property
    def bin_version(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['binary version']

    @property
    def map_in_version(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['map input version']

    @property
    def map_out_version(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info['map output version']

    @property
    def is_experimental(self):
        if not self._available_versions:
            t = self.fetch_factorio_versions()
            t.join()
        if self.version_list.index(self.stable) < self.version_list.index(
                self.version):
            return True
        return False

    @property
    def stable(self):
        if not self._available_versions:
            t = self.fetch_factorio_versions()
            t.join()
        return self._available_versions['stable']

    @property
    def version_list(self):
        if not self._available_versions:
            t = self.fetch_factorio_versions()
            t.join()
        return self._available_versions['version_list']

    @property
    def experimental_version_list(self):
        if not self._available_versions:
            t = self.fetch_factorio_versions()
            t.join()
        return self.version_list[self.version_list.index(self.stable) + 1:]

    @property
    def stable_version_list(self):
        if not self._available_versions:
            t = self.fetch_factorio_versions()
            t.join()
        return self.version_list[:self.version_list.index(self.stable) + 1]

    @property
    def executable(self):
        if OS_WIN:
            return (self.root_path / 'bin' / 'x64' / 'factorio.exe').resolve()
        else:
            return (self.root_path / 'bin' / 'x64' / 'factorio').resolve()

    @property
    def save_file(self):
        return (self.root_path / 'saves' / self.name /
                f'{self.name}.zip').resolve()

    @property
    def player_data(self):
        if not self._player_data:
            self._player_data = json.load(
                (self.root_path / 'player-data.json').resolve().open())
        return self._player_data

    @property
    def service_username(self):
        if not self._player_data:
            self._player_data = json.load(
                (self.root_path / 'player-data.json').resolve().open())
        return self._player_data['service-username']

    @property
    def service_token(self):
        if not self._player_data:
            self._player_data = json.load(
                (self.root_path / 'player-data.json').resolve().open())
        return self._player_data['service-token']

    @property
    def config(self):
        if not self._config:
            conf_parser = ConfigParser()
            self._config = conf_parser.read(
                (self.root_path / 'config' /
                 'config.ini').resolve().as_posix())
        return self._config

    @property
    def server_config(self):
        if not self._server_config:
            self._server_config = json.load(
                (self.root_path / 'config' /
                 'server-settings.json').resolve().open())
        return self._server_config

    @server_config.setter
    def server_config(self, config):
        self._server_config = merge_two_dicts(config, self._server_config)
        save_settings(self._server_config, (self.root_path / 'config' /
                                            'server-settings.json').resolve())

    @property
    def bits(self):
        if self.build_platform[-2:] == '64':
            return '64'
        else:
            return '32'  # I don't have any 32 bit systems so I wasn't sure what factorio would respond with

    @property
    def core_str(self):
        core = f'core-{self.build_platform[:-2]}'
        if self.build_mode == 'headless':
            core = core + '_headless'
        core = core + self.bits
        return core

    def set_version_info(self):
        log.info(f'Getting the version info for {self.name}')
        commands = [self.executable.as_posix(), '--version']
        p = Popen(commands, stdout=PIPE, stderr=PIPE)
        std_out, std_err = p.communicate()
        self._version_info = std_out.decode().splitlines()
        self._version_info = {
            l.split(':')[0].lower(): l.split(':')[1]
            for l in self._version_info
        }
        self._version_info['build'] = self._version_info['version'].split(
            '(')[1]
        self._version_info['build'] = self._version_info['build'].replace(
            ')', '').split(', ')
        self._version_info['build'] = {
            'number': self._version_info['build'][0].replace('build', ''),
            'platform': self._version_info['build'][1],
            'mode': self._version_info['build'][2]
        }
        self._version_info['version'] = self._version_info['version'].split(
            '(')[0].strip()

    def status(self):
        if self.process:
            if not self._ps_proc:
                self._ps_proc = Process(self.process.pid)
            try:
                data = {
                    'status': self._ps_proc.status(),
                    'cpu': self._ps_proc.cpu_percent(interval=2),
                    'mem': naturalsize(self._ps_proc.memory_info().rss),
                    'mem_raw': self._ps_proc.memory_info().rss,
                    'available_mem': naturalsize(self._virtual_mem.available),
                    'available_mem_raw': self._virtual_mem.available,
                    'total_mem': naturalsize(TOTAL_MEMORY),
                    'total_mem_raw': TOTAL_MEMORY,
                }
            except (NoSuchProcess, AttributeError):
                log.warn(
                    f'Factorio Process {self.name} does not exist anymore')
                return
            self._status_history.appendleft(data)
            return list(self._status_history)

    @run_in_thread
    def start(self):
        log.info(f'Starting Factorio instance {self.name}')
        if self.name in app_settings.factorio_instances:
            if isinstance(self.process, Popen):
                # TODO: need to do more here to actually check if it is running
                log.warn(f'{self.name} factorio instance is already running')
                return
        if self.name not in app_settings.factorio_instances:
            log.warn(f'{self.name} factorio instance does not exist')
            return
        commands = [
            self.executable.as_posix(), '--start-server', self.save_file,
            '--port',
            str(self.port)
        ]
        log.debug(f'Starting {self.name}')
        self.process = Popen(commands, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        self.output_log()

    @run_in_thread
    def output_log(self):
        while True:
            std_out = self.process.stdout.readline()
            if std_out:
                std_out = std_out.decode()
                self._log_queue.append('{} {}: {}'.format(
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3],
                    self.name.upper(), std_out.replace('\n', '')))
                self.log.info(std_out)
            else:
                sleep(.05)
            if self.process is None:
                break
            if self.process.poll() is not None:
                break

    def get_log_line(self):
        if len(self._log_queue):
            return self._log_queue.pop()
        else:
            return

    @run_in_thread
    def stop(self):
        log.debug(f'Stopping {self.name}')
        if self.process:
            self.process.terminate()
            self.process = None
            self._ps_proc = None

    @run_in_thread
    def kill(self):
        log.debug(f'Killing {self.name}')
        if self.process:
            self.process.kill()
            self.process = None
            self._ps_proc = None

    @run_in_thread
    def send_command(self, command):
        # TODO: This does not work. No idea how it should work
        if self.process:
            self.process.communicate(f'{command}\n'.encode())

    def create_save_file(self,
                         map_gen_file_path=None,
                         map_settings_path=None,
                         preset=None,
                         map_preview_path=None):
        if not self.save_file.is_file():
            if not (self.save_file / '..').resolve().is_dir():
                (self.save_file / '..').resolve().mkdir()
            commands = [
                self.executable.as_posix(), '--create',
                self.save_file.as_posix()
            ]
            # TODO: Add the optional arguments to commands
            p = Popen(commands, stdout=PIPE, stderr=PIPE)
            log.info(p.communicate())

    def get_version_info(self):
        if self._version_info is None:
            self.set_version_info()
        return self._version_info

    def check_for_update(self):
        self.get_version_info()
        t = self.fetch_factorio_versions()
        t.join()
        if self.is_experimental:
            version_list = self.experimental_version_list
        else:
            version_list = self.stable_version_list
        if self.version != version_list[-1]:
            self.update_available = version_list[-1]
            return version_list[-1]
        else:
            self.update_available = False

    def get_download_link(self, version):
        get_link_url = 'https://www.factorio.com/get-download-link'
        update_version_info = list(
            filter(lambda x: x['to'] == version,
                   self._available_versions['available_versions']))[0]
        data = {
            'username': self.service_username,
            'token': self.service_token,
            'package': self.core_str,
            'from': update_version_info['from'],
            'to': update_version_info['to'],
            'apiVersion': 2
        }
        req = request.Request(get_link_url + '?' + parse.urlencode(data))
        resp = request.urlopen(req)
        download_link = json.loads(resp.read())
        return download_link[0]

    def download_update(self, version):
        link = self.get_download_link(version)
        log.info(link)
        with TqdmUpTo(unit='B',
                      unit_scale=True,
                      miniters=1,
                      desc=link.split('/')[-1]) as t:
            self._temp_update = request.urlretrieve(
                link, reporthook=t.download_progress)[0]

    @run_in_thread
    def apply_update(self):
        if self._temp_update:
            commands = [
                self.executable.as_posix(), '--apply-update', self._temp_update
            ]
            p = Popen(commands, stdout=PIPE, stderr=PIPE)
            log.info(p.communicate())
            p.terminate()
        self.set_version_info()
        self.update_available = False

    @run_in_thread
    def fetch_factorio_versions(self):
        available_versions_url = 'https://www.factorio.com/get-available-versions'
        data = parse.urlencode({
            'username': self.service_username,
            'token': self.service_token,
            'apiVersion': 2
        })
        req = request.Request(available_versions_url + '?' + data)
        resp = request.urlopen(req)
        json_resp = json.loads(resp.read())
        available_versions = json_resp[self.core_str]
        stable_version = list(
            filter(lambda x: True if 'stable' in x else False,
                   available_versions))[0]['stable']
        available_versions = list(
            filter(lambda x: False
                   if 'stable' in x else True, available_versions))
        version_list = sorted(
            available_versions,
            key=lambda s: [int(u) for u in s['to'].split('.')])
        version_list = [u['to'] for u in version_list]
        self._available_versions = {
            'stable': stable_version,
            'version_list': version_list,
            'available_versions': available_versions
        }
        return json_resp