Example #1
0
class Manager(manager_grpc.ManagerServicer):
    """
    Implements a server for the Manager gRPC protocol.
    """
    def __init__(self, total_shards):
        """
        Instantiates a new manager server that handles some
        number of shards.
        """
        logger.info(f"Number of shards: {total_shards}")
        self.hoarfrost_gen = HoarFrostGenerator()
        self.total_shards = total_shards
        self.registered = [False for _ in range(total_shards)]
        self.last_checkin = dict()
        self.store = dict()

    def health_check(self):
        while True:
            time.sleep(5)
            for shard, last_checkin in self.last_checkin.items():
                if last_checkin is not None and last_checkin < datetime.now(
                ) - timedelta(seconds=5):
                    logger.error(
                        f"--- SHARD {shard} MISSED ITS HEARTBEAT, DEREGISTERING... ---"
                    )
                    self.registered[shard] = False
                    self.last_checkin[shard] = None

    def register(self, request, context):
        """Returns the next shard id that needs to be filled as well as the total shards"""
        if all(self.registered):
            raise Exception("Shard trying to register even though we're full")
        i = next(i for i in range(self.total_shards) if not self.registered[i])
        logger.info(
            f"Shard requested id, assigning {i + 1}/{self.total_shards}...")
        self.registered[i] = True
        return message.ShardInfo(shard_id=i, shard_count=self.total_shards)

    def guild_count(self, request, context):
        """Return guild and user count information"""
        gc = 0
        uc = 0
        for guilds in self.store.values():
            gc += len(guilds)
            for guild in guilds:
                uc += guild.member_count

        return message.GuildInfo(guild_count=gc, user_count=uc)

    def checkin(self, request, context):
        self.last_checkin[request.shard_id] = datetime.now()
        self.registered[request.shard_id] = True
        return message.CheckInResponse()

    def publish_file(self, request_iterator, context):
        """Missing associated documentation comment in .proto file"""
        first = next(request_iterator)
        filetype = "png" if first.filetype == "" else first.filetype
        name = first.name
        if name == "":
            name = str(self.hoarfrost_gen.generate())
        location = first.location
        if location == "":
            location = "assets"
        directory = f"/var/www/{location}"

        if not os.path.exists(directory):
            os.makedirs(directory)
        with open(f"{directory}/{name}.{filetype}", "wb") as f:
            logger.info(f"Writing {directory}/{name}.{filetype}")
            f.write(first.file)
            for datum in request_iterator:
                f.write(datum.file)

        return message.Url(
            url=f"https://cdn.{domain_name}/{location}/{name}.{filetype}")

    def all_guilds(self, request, context):
        """Return information about all guilds that the bot is in, including their admins"""
        for guilds in self.store.values():
            for guild in guilds:
                yield guild

    def guild_update(self, request_iterator, context):
        """Update the manager with the latest information about a shard's guilds"""
        guilds = []
        for guild in request_iterator:
            guilds.append(guild)
        if len(guilds) == 0:
            return message.UpdateResponse()
        logger.debug(
            f"Received guild list from shard {guilds[0].shard_id + 1} of {len(guilds)} guilds"
        )
        self.store[guilds[0].shard_id] = guilds
        return message.UpdateResponse()
Example #2
0
class Manager:
    """Manages shards.  assigns shard nodes their ids and checks if they are alive"""
    def __init__(self, total_shards):
        logger.info(f"Number of shards: {total_shards}")
        self.hoarfrost_gen = HoarFrostGenerator()
        self.total_shards = total_shards
        self.registered = [False for _ in range(total_shards)]
        self.last_checkin = {}
        self.store = {}

    async def handle_task(self, method, *args, **kwargs):
        try:
            return (await (getattr(self, method)(*args, **kwargs)), 200)
        except Exception as e:
            logger.exception(f"caught: '{e}' while executing '{method}'")
            return {'message': f"caught: '{e}' while executing '{method}'"}

    async def health_check(self):
        while True:
            await asyncio.sleep(1)
            for shard, last_checkin in self.last_checkin.items():
                if last_checkin is not None and last_checkin < datetime.now() - timedelta(seconds=5):
                    logger.error(f"--- SHARD {shard} MISSED ITS HEARTBEAT, DEREGISTERING... ---")
                    self.registered[shard] = False
                    self.last_checkin[shard] = None

    async def register(self):
        """Returns the next shard id that needs to be filled as well as the total shards"""
        if all(self.registered):
            raise Exception("Shard trying to register even though we're full")
        i = next(i for i in range(self.total_shards) if not self.registered[i])
        logger.info(f'Shard requested id, assigning {i + 1}/{self.total_shards}...')
        self.store[i] = {'shard_id': i}
        self.registered[i] = True
        return {'shard_id': i, 'shard_count': self.total_shards}

    async def all_guilds(self):
        """Return information about all guilds that the bot is in, including their admins"""
        guilds = []
        for shard, shard_store in self.store.items():
            guilds += shard_store.get('guilds', ())
        return guilds

    async def guild_count(self):
        """Return guild and user count information"""
        guild_count = 0
        user_count = 0
        for shard, shard_store in self.store.items():
            guilds = shard_store.get('guilds', ())
            guild_count += len(guilds)
            for guild in guilds:
                user_count += guild['member_count']
        return {'guild_count': guild_count, 'user_count': user_count}

    async def guild_update(self, shard_id, guilds):
        """Update the manager with the latest information about a shard's guilds"""
        logger.debug(f"someone sent guild list containing {len(guilds)} guilds")
        self.store[int(shard_id)]['guilds'] = guilds
        return {"message": "thanks"}

    async def checkin(self, shard_id):
        self.last_checkin[shard_id] = datetime.now()
        self.registered[shard_id] = True
        return "nice"

    async def publish_file(self, location: str = 'assets', name: str = '', filetype: str = 'png', data: str = ''):
        assert data != ''
        if name == '':
            name = str(self.hoarfrost_gen.generate())
        directory = f'/var/www/{location}'

        if not os.path.exists(directory):
            os.makedirs(directory)
        with open(f'{directory}/{name}.{filetype}', 'wb') as f:
            logger.info(f'writing {directory}/{name}.{filetype}')
            f.write(base64.b64decode(data))
        return {'url': f'https://cdn.{domain_name}/{location}/{name}.{filetype}'}
def generate_response_ast(response):
    response = generate_response(response)
    try:
        return json.dumps(parse(response).stringify())
    except Exception as e:
        print(e.__class__.__name__)
        print(f"caught while parsing: '{response}'")
        return ""


responses = defaultdict(list)
for cmd in command_list:
    trigger = generate_trigger(cmd.trigger, cmd.server_id)
    responses[cmd.server_id].append(AutoResponse(
        hoarfrost_gen.generate(),
        trigger,
        generate_response(cmd.response),
        cmd.author_id,
        cmd.server_id,
        generate_trigger_regex(trigger, get_mode(trigger)),
        get_puncutation(trigger),
        generate_response_ast(cmd.response),
        get_mode(trigger),
        cmd.count
    ))

for guild_id in responses.keys():
    reggys = []
    uses_regex = False
    for resp in responses[guild_id]: