Esempio n. 1
0
async def test_choose_menu_repr(client, message):
    '''
    Creates a ChooseMenu and returns it's repr.
    '''
    choices = ['nice', 'cat']
    choose_menu = await ChooseMenu(client, message.channel, choices,
                                   lambda *args: Future(KOKORO))
    await client.message_create(message.channel, repr(choose_menu))
Esempio n. 2
0
    def __new__(cls, client, event, map_name, length, possibilities):
        self = object.__new__(cls)
        self.client = client
        self.channel = event.channel
        self.users = [event.user]

        self.map_name = map_name
        self.length = length
        self.possibilities = possibilities

        self.cancelled = False
        self.waiter = waiter = Future(KOKORO)
        future_or_timeout(waiter, 300.0)

        Task(self.start_waiting(), KOKORO)
        ACTIVE_GAMES[event.channel.id] = self

        return self
Esempio n. 3
0
 async def __new__(cls):
     waiter = cls.waiter
     if waiter is None:
         average_cpu_frequence = psutil.cpu_freq().current
         PROCESS.cpu_percent()
         cls.waiter = waiter = Future(KOKORO)
         await sleep(1.0, KOKORO)
         cpu_percent = PROCESS.cpu_percent()
         cpu_frequence = psutil.cpu_freq()
         average_cpu_frequence = (average_cpu_frequence + cpu_frequence.current) / 2.0
         
         result = object.__new__(cls)
         result.cpu_percent = cpu_percent
         result.average_cpu_frequence = average_cpu_frequence
         waiter.set_result(result)
         cls.waiter = None
     else:
         result = await waiter
     
     return result
Esempio n. 4
0
    async def start(self):
        client = self.client
        player1 = self.player1
        player2 = self.player2

        player1.other = player2
        player2.other = player1
        
        try:
            #creating missing channel
            player1.channel = await client.channel_private_create(player1.user)

            #adding channels to the event to notify us
            client.events.message_create.append(player1.channel, self)
            client.events.message_create.append(player2.channel, self)
            
            #game starts            
            self.future = FutureWM(KOKORO, 2)
            future_or_timeout(self.future, 300.)

            #startup
            self.process = self.process_state_0
            Task(player1.set_state_0(), KOKORO)
            Task(player2.set_state_0(), KOKORO)
            
            try:
                await self.future
            except TimeoutError:
                if not self.future._result:
                    text1 = text2 ='The time is over, both players timed out'
                elif player1 in self.future._result:
                    text1 = 'The other player timed out'
                    text2 = 'You timed out'
                else:
                    text1 = 'You timed out'
                    text2 = 'The other player timed out'
                Task(client.message_create(player1.channel, text1), KOKORO)
                Task(client.message_create(player2.channel, text2), KOKORO)
                return

            self.process = self.process_state_1
            player1.ships_left[:] = user_profile.ships
            player2.ships_left[:] = user_profile.ships

            if randint(0, 1):
                self.actual = player1
            else:
                self.actual = player2
            
            await self.actual.set_state_1(True)
            await self.actual.other.set_state_1(False)
            
            
            while self.process is not None:
                self.future = Future(KOKORO)
                future_or_timeout(self.future, 300.)
                try:
                    result = await self.future
                except TimeoutError:

                    await self.actual.other.set_state_2(True, 'Your opponent timed out!')
                    await self.actual.set_state_2(False, 'You timed out!')
                    return
                
                if result:
                    self.actual = self.actual.other
        
        
        except BaseException as err:
            if isinstance(err, ConnectionError):
                return
            
            if isinstance(err, DiscordException) and err.code == ERROR_CODES.invalid_message_send_user:
                return
            
            await client.events.error(client, f'{self!r}.start', err)
        finally:
            self.cancel()
Esempio n. 5
0
class battleships_game:
    __slots__=('actual', 'client', 'future', 'player1', 'player2', 'process',)
    def __init__(self, client, user1, user2, channel2):
        
        BS_GAMES[user1] = self
        BS_GAMES[user2] = self
        
        self.client = client
        
        self.player1 = user_profile(user1, client)
        self.player2 = user_profile(user2, client)
        self.player2.channel = channel2
        
        Task(self.start(), KOKORO)
    
    #compability
    async def start(self):
        client = self.client
        player1 = self.player1
        player2 = self.player2

        player1.other = player2
        player2.other = player1
        
        try:
            #creating missing channel
            player1.channel = await client.channel_private_create(player1.user)

            #adding channels to the event to notify us
            client.events.message_create.append(player1.channel, self)
            client.events.message_create.append(player2.channel, self)
            
            #game starts            
            self.future = FutureWM(KOKORO, 2)
            future_or_timeout(self.future, 300.)

            #startup
            self.process = self.process_state_0
            Task(player1.set_state_0(), KOKORO)
            Task(player2.set_state_0(), KOKORO)
            
            try:
                await self.future
            except TimeoutError:
                if not self.future._result:
                    text1 = text2 ='The time is over, both players timed out'
                elif player1 in self.future._result:
                    text1 = 'The other player timed out'
                    text2 = 'You timed out'
                else:
                    text1 = 'You timed out'
                    text2 = 'The other player timed out'
                Task(client.message_create(player1.channel, text1), KOKORO)
                Task(client.message_create(player2.channel, text2), KOKORO)
                return

            self.process = self.process_state_1
            player1.ships_left[:] = user_profile.ships
            player2.ships_left[:] = user_profile.ships

            if randint(0, 1):
                self.actual = player1
            else:
                self.actual = player2
            
            await self.actual.set_state_1(True)
            await self.actual.other.set_state_1(False)
            
            
            while self.process is not None:
                self.future = Future(KOKORO)
                future_or_timeout(self.future, 300.)
                try:
                    result = await self.future
                except TimeoutError:

                    await self.actual.other.set_state_2(True, 'Your opponent timed out!')
                    await self.actual.set_state_2(False, 'You timed out!')
                    return
                
                if result:
                    self.actual = self.actual.other
        
        
        except BaseException as err:
            if isinstance(err, ConnectionError):
                return
            
            if isinstance(err, DiscordException) and err.code == ERROR_CODES.invalid_message_send_user:
                return
            
            await client.events.error(client, f'{self!r}.start', err)
        finally:
            self.cancel()
    
    async def process_state_0(self, message):
        if message.author is self.player1.user:
            player = self.player1
        else:
            player = self.player2
        other = player.other
        
        while True:
            if sum(player.ships_left) == 0:
                text='Waiting on the other player.'
                break
            
            result = NEW_RP.fullmatch(message.content)
            if result is not None:
                text='new'
                break
            result = POS_PATTERN_0.match(message.content)
            if result is None:
                text='Bad input format'
                break
            result=result.groups()
            
            value=result[0]
            if value.isdigit():
                x = int(value)
                if x > 10:
                    text='Bad input format.'
                    break
                x -= 1
                y = 100
            else:
                x = 100
                y = ('abcdefghij').index(value.lower())
            
            value = result[1]
            if value.isdigit():
                if x != 100:
                    text = 'Dupe coordinate'
                    break
                x = int(value)
                if x > 10:
                    text = 'Bad input format.'
                    break
                x -= 1
            else:
                if y != 100:
                    text = 'Dupe coordinate'
                    break
                y = ('abcdefghij').index(value)
            
            size1 = int(result[2])
            size2 = int(result[4])
            if (size1 == 1 and size2 == 3) or (size1 == 3 and size2 == 1):
                type_=1
            elif (size1 == 1 and size2 == 4) or (size1 == 4 and size2 == 1):
                type_ = 2
            elif (size1 == 2 and size2 == 2):
                type_ = 3
            else:
                text = 'Invalid ship size'
                break
            
            if player.ships_left[type_] == 0:
                text = 'You do not have anymore ships from that size'
                break
            
            
            text = ''
            
            x_start = x
            if x_start > 0:
                x_start -= 1
            
            x_end = x+size1
            if x_end > 10:
                text = 'There is not enough space to place that ship!'
                break
            elif x_end < 10:
                x_end += 1
            
            y_start = y*10
            if y_start > 0:
                y_start -= 10

            y_end = (y+size2)*10
            if y_end > 100:
                text = 'There is not enough space to place that ship!'
                break
            elif y_end < 100:
                y_end += 10

                
            data = player.data
            for n_x in range(x_start, x_end):
                for n_y in range(y_start, y_end, 10):
                    if data[n_x+n_y]:
                        text = (
                            f'Can not set ship to {1+x}/{chr(65+y)}, because coordinate {1+n_x}/{chr(65+n_y//10)} is '
                            'already used.'
                                )
                        break
            if text:
                break
            
            ship = ship_type(x, y, size1, size2, type_)
            cords = []
            
            x_start = x
            x_end = x+size1
            y_start = y*10
            y_end = (y+size2)*10
            for n_x in range(x_start, x_end):
                for n_y in range(y_start, y_end, 10):
                    cord = n_x+n_y
                    data[cord] = type_
                    player.ship_positions[cord] = ship
                    cords.append(f'{chr(65+n_y//10)}/{1+n_x}')
            
            player.ships_left[type_] -= 1
            
            if sum(player.ships_left) == 0:
                self.future.set_result(player)
                text = (
                    f'You placed all of your ships. Last ship placed at: {", ".join(cords)}; waiting on the other '
                    'player.'
                            )
            else:
                text = f'You placed the ship succesfully at: {", ".join(cords)}.'
            
            break
        
        client = self.client
        
        if text == 'new':
            await player.process(True, None)
            return
        
        if sum(player.ships_left) == sum(other.ships_left) == 0:
            return
        
        await player.process(False, text)

    async def process_state_1(self, message):
        if self.actual is self.player1:
            player = self.player1
            other = self.player2
        else:
            player = self.player2
            other = self.player1

        client = self.client
        
        if message.author is not self.actual.user:
            result = NEW_RP.fullmatch(message.content)
            if result is not None:
                await player.process(True, None)
            return

        data=other.data
        
        while True:
            result = NEW_RP.fullmatch(message.content)
            if result is not None:
                text = 'new'
                break
            
            result = POS_PATTERN_1.match(message.content)
            if result is None:
                text = 'Bad input format'
                break
            
            result = result.groups()
        
            value = result[0]
            if value.isdigit():
                x = int(value)
                if x > 10:
                    text = 'Bad input format.'
                    break
                x = x-1
                y = 100
            else:
                x = 100
                y = ('abcdefghij').index(value.lower())

            value = result[1]
            if value.isdigit():
                if x != 100:
                    text = 'Dupe coordinate'
                    break
                x = int(value)
                if x > 10:
                    text = 'Bad input format.'
                    break
                x = x-1
            else:
                if y!=100:
                    text='Dupe coordinate'
                    break
                y = ('abcdefghij').index(value)
            
            value = data[x+y*10]
            if value > 4:
                text='That position is already shot'
                break

            text = ''
            break
        
        if text:
            if text == 'new':
                await player.process(True, None)                    
            else:
                await player.process(False, text)
            return

        if value == 0:
            data[x+y*10] = 5

            player.state = False
            other.state = True
                
            await player.process(False, 'You missed!')
            await other.process(True, f'Your opponent shot {chr(65+y)}/{1+x}, it missed!\n')
            self.future.set_result(True)
            return

        del text
        
        data[x+y*10] = 6
        ship=other.ship_positions.pop(x+y*10)
        ship.parts_left -= 1
        if ship.parts_left == 0:
            other.ships_left[ship.type] -= 1
            for cord in ship:
                data[cord] = 7
            if sum(other.ships_left):
                text1 = f'You shot {chr(65+y)}/{1+x} and you sinked 1 of your opponents ships!\n'
                text2 = f'Your opponent shot {chr(65+y)}/{1+x} and your ship sinked :c\n'
            else:
                self.process = None
                await player.set_state_2(True,
                    f'You shot {chr(65+y)}/{1+x} and you sinked your opponents last ship!')
                await other.set_state_2(False,
                    f'Your opponent shot {chr(65+y)}/{1+x} and your last ship sinked :c')
                self.future.set_result(False)
                return
        else:

            text1 = f'You shot {chr(65+y)}/{1+x} and you hit a ship!'
            text2 = f'Your opponent shot {chr(65+y)}/{1+x} and hit 1 of your ships!'

        player.state = True
        other.state = False
            
        await player.process(False, text1)
        await other.process(True, text2)
        self.future.set_result(False)
    
    async def __call__(self, client, message):
        if message.author is client:
            return
        
        await self.process(message)
        
    def cancel(self):
        event = self.client.events.message_create
        event.remove(self, self.player1.channel)
        event.remove(self, self.player2.channel)
        
        del BS_GAMES[self.player1.user]
        del BS_GAMES[self.player2.user]

        self.player1.cancel()
        self.player2.cancel()
Esempio n. 6
0
async def battle_manager(client, message, target:Converter('user', flags=ConverterFlag.user_default.update_by_keys(everywhere=True), default=None)):
    text = ''
    while True:
        if target is None:
            break
        
        guild = message.guild
        source = message.author
        
        if source in BS_GAMES:
            text = 'You cant start a game, if you are in 1 already'
            break
        
        if source in BS_REQUESTERS:
            text = 'You can have only one active request'
            break

        if target is source:
            text = 'Say 2 and easier.'
            break

        if target is client:
            text = 'NO AI opponent yet!'
            break
        
        if target in BS_GAMES:
            text = 'The user is already in game'
            break

        
        request = active_request(source, target)
        
        is_reversed = BS_REQUESTS.get(request)

        if is_reversed is not None:
            is_reversed.future.set_result(message)
            return

        BS_REQUESTS[request] = request
        
        BS_REQUESTERS.add(source)
        
        channel = message.channel
        private = await client.channel_private_create(target)
        
        await client.message_create(channel,
            f'Waiting on {target.full_name}\'s reply here and at dm.\nType:"accept name/mention" to accept')
        
        
        future = request.future=Future(KOKORO)
        check = wait_on_reply(guild, source, target)
        event = client.events.message_create
        
        waiter1 = WaitAndContinue(future, check, channel, event, 300.)
        waiter2 = WaitAndContinue(future, check, private, event, 300.)
        
        try:
            result = await future
        except TimeoutError:
            try:
                BS_REQUESTERS.remove(source)
                text = f'The request from {source.full_name} timed out'
            except KeyError:
                pass
            break
        finally:
            try:
                del BS_REQUESTS[request]
            except KeyError:
                pass

            for waiter in (waiter1,waiter2):
                waiter.cancel()

        try:
            BS_REQUESTERS.remove(source)
        except KeyError:
            text = 'The requester is already in a game'
            break
        
        if target in BS_GAMES:
            text='You already accepted a game'
            break

        try:
            BS_REQUESTERS.remove(target)
            await client.message_create(channel, f'Request from {target.full_name} got cancelled')
        except KeyError:
            pass
            
        game = battleships_game(client, source, target, private)
        break
    
    if text:
        await client.message_create(message.channel, text)
    else:
        embed = await bs_description(client, message)
        await Closer(client, message.channel, embed)
Esempio n. 7
0
    async def runner(self):
        client = self.client
        channel = self.channel
        answers = self.answers
        buffer = ReuBytesIO()
        embed = Embed(color=KANAKO_COLOR).add_image(
            'attachment://guess_me.png').add_footer('')

        time_till_notify = CIRCLE_TIME - 10

        for index, (question, answer) in enumerate(self.map, 1):
            embed.footer.text = f'{index} / {len(self.map)}'
            if self.possibilities:
                self.options = self.generate_options(answer)
                embed.description = '\n'.join([
                    f'**{index}.: {value}**'
                    for index, value in enumerate(self.options, 1)
                ])

            try:
                await client.message_create(channel,
                                            embed=embed,
                                            file=('guess_me.png',
                                                  draw(buffer, question)))
            except BaseException as err:
                self.cancel()
                if isinstance(err, ConnectionError):
                    return

                if isinstance(err, DiscordException):
                    if err.code in (
                            ERROR_CODES.unknown_channel,  # channel deleted
                            ERROR_CODES.missing_access,  # client removed
                            ERROR_CODES.
                            missing_permissions,  # permissions changed meanwhile
                    ):
                        return

                await client.events.error(client,
                                          f'{self.__class__.__name__}.runner',
                                          err)
                return

            circle_start = LOOP_TIME()
            self.waiter = waiter = Future(KOKORO)
            future_or_timeout(waiter, time_till_notify)

            try:
                await waiter
            except TimeoutError:
                Task(self.notify_late_users(), KOKORO)

                self.waiter = waiter = Future(KOKORO)
                future_or_timeout(waiter, 10)

                try:
                    await waiter
                except TimeoutError:
                    leavers = []

                    users = self.users

                    for index in reversed(range(len(users))):
                        user = users[index]
                        if user in answers:
                            continue

                        leavers.append(user)
                        del users[index]

                        for element in self.history:
                            del element.answers[index]

                    if len(self.users) == 0:
                        self.cancel()
                        embed = Embed(
                            None,
                            'No-one gave answer in time, cancelling the game.',
                            color=KANAKO_COLOR)
                    else:
                        embed = Embed(None,
                                      '\n'.join([
                                          'Users timed out:',
                                          *(user.full_name for user in leavers)
                                      ]),
                                      color=KANAKO_COLOR)

                    try:
                        await client.message_create(channel, embed=embed)
                    except BaseException as err:
                        self.cancel()
                        if isinstance(err, ConnectionError):
                            return

                        if isinstance(err, DiscordException):
                            if err.code in (
                                    ERROR_CODES.
                                    unknown_channel,  # channel deleted
                                    ERROR_CODES.
                                    missing_access,  # client removed
                                    ERROR_CODES.
                                    missing_permissions,  # permissions changed meanwhile
                            ):
                                return

                        await client.events.error(
                            client, f'{self.__class__.__name__}.runner', err)
                        return

            if self.cancelled:
                return

            self.waiter = None

            element = HistoryElement()
            element.question = question
            element.answer = answer
            element.options = self.options
            element.answers = [(value[0], value[1] - circle_start)
                               for value in (answers[user.id]
                                             for user in self.users)]
            self.history.append(element)

            answers.clear()

            embed.title = f'Last answer: {answer}'

        self.cancel()

        embed = Embed(embed.title, color=KANAKO_COLOR)
        try:
            await client.message_create(channel, embed=embed)
        except BaseException as err:
            self.cancel()
            if isinstance(err, ConnectionError):
                return

            if isinstance(err, DiscordException):
                if err.code in (
                        ERROR_CODES.unknown_channel,  # channel deleted
                        ERROR_CODES.missing_access,  # client removed
                        ERROR_CODES.
                        missing_permissions,  # permissions changed meanwhile
                ):
                    return

            await client.events.error(client,
                                      f'{self.__class__.__name__}.runner', err)
            return

        await GameStatistics(self)
Esempio n. 8
0
    async def command(client, message, target_channel: ChannelText, time: int):
        guild = message.guild
        if guild is None:
            return

        if time < 1:
            await client.message_create(
                message.channel, f'Time cannot be less than 1, got {time!r}')
            return

        canceller = Future(KOKORO)
        KOKORO.call_later(time * 3600.0, Future.set_result_if_pending,
                          canceller, None)

        await client.message_create(
            message.channel,
            f'Starting loop over {target_channel.mention} for {time} hours.')

        invites = []
        total = 0

        while True:
            try:
                invite = await client.invite_create(target_channel)
                parsed = INVITE_GEN_RP.search(invite.code)
                if parsed is None:
                    await client.invite_delete(invite)
                else:
                    invites.append(invite)

                total += 1
            except BaseException as err:
                if isinstance(err, ConnectionError):
                    canceller.cancel()
                    sys.stderr.write(
                        'invite_gen failed, connection error occured meanwhile!\n'
                    )
                    return

                if isinstance(err, DiscordException):
                    err_code = err.code
                    if err_code in (
                            ERROR_CODES.
                            invalid_permissions,  # permissions changed meanwhile
                            ERROR_CODES.invalid_access,  # client removed
                    ):

                        canceller.set_result_if_pending(None)
                        break

                    if err_code == ERROR_CODES.unknown_channel:  # message's channel deleted
                        canceller.cancel()
                        return

                    if err_code == ERROR_CODES.max_invites:
                        canceller.set_result_if_pending(None)
                        break

                canceller.cancel()
                await client.events.error(client, 'invite_gen', err)
                return

            if canceller.done():
                break

        title = f'{total} invites generated, from this {len(invites)} passed.'
        pages = [
            Embed(title, chunk)
            for chunk in cchunkify([invite.url for invite in invites])
        ]

        await Pagination(client, message.channel, pages, timeout=7200.0)
Esempio n. 9
0
    async def __call__(self, key):
        cache = self.cache
        try:
            result = cache[key]
        except KeyError:
            pass
        else:
            cache.move_to_end(key)
            return result, False

        if self.limit.is_active():
            return None, True

        quoted_key = quote(key)

        active = self.active
        try:
            waiters = active[key]
        except KeyError:
            pass
        else:
            waiter = Future(KOKORO)
            waiters.append(waiter)
            return await waiter

        waiters = []
        active[key] = waiters

        try:
            async with self.limit.lock:
                # Check time again, because we may become limited when we get here.
                if self.limit.is_active():
                    result = None
                    limited = True
                else:

                    url = self.query_builder(quoted_key)
                    async with self.http.get(
                            url, headers=GITHUB_HEADERS) as response:
                        self.limit.set(response.headers)
                        if response.status in (200, 404):
                            result_data = await response.json()
                        else:
                            result_data = None

                    result = self.object_type(result_data)
                    if len(cache) == 1000:
                        del cache[next(iter(cache))]

                    cache[key] = result
                    limited = False

        except BaseException as err:
            try:
                del active[key]
            except KeyError:
                pass
            else:
                for waiter in waiters:
                    waiter.set_exception_if_pending(err)

            raise err

        else:
            try:
                del active[key]
            except KeyError:
                pass
            else:
                for waiter in waiters:
                    waiter.set_result_if_pending((result, limited))

            return result, limited