コード例 #1
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
 async def guild_bindings(self, member):
     """Return all bound messages for guild_id."""
     async with connection().transaction():
         await self.wiki_db.check_permissions(member, Permissions.view)
         async for row in connection().cursor(self.queries.guild_bindings(),
                                              member.guild.id):
             yield AttrDict(row)
コード例 #2
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def delete_page(self, member, title) -> bool:
        """delete a page or alias

		return whether an alias was deleted
		"""
        async with connection().transaction():
            # we use resolve_page here for separate permissions check depending on type
            is_alias = (await self.resolve_page(member, title)).alias

            if is_alias:
                # why Permissions.edit and not Permissions.delete?
                # deleting an alias is a prerequisite to recreating it with a different title
                # and deleting an alias is nowhere near as destructive as deleting a page
                await self.check_permissions(member, Permissions.edit)
                command_tag = await connection().execute(
                    self.queries.delete_alias(), member.guild.id, title)
                if command_tag.split()[-1] == '0':
                    raise RuntimeError(
                        'page is supposed to be an alias but delete_alias did not delete it',
                        title)
                return True

            await self.check_permissions(member, Permissions.delete, title)
            command_tag = await connection().execute(
                self.queries.delete_page(), member.guild.id, title)
            if command_tag.split()[-1] == '0':
                raise RuntimeError(
                    'page is not supposed to be an alias but delete_page did not delete it',
                    title)

            return False

        raise errors.PageNotFoundError(title)
コード例 #3
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def revise_page(self, member, title,
                          new_content) -> typing.Optional[str]:
        self.check_title(title)
        self.check_content(new_content)

        async with connection().transaction(isolation='serializable'):
            await self.check_permissions(member, Permissions.edit, title)

            page = await connection().fetchrow(self.queries.get_page_basic(),
                                               member.guild.id, title)
            if page is None:
                raise errors.PageNotFoundError(title)

            content_id = await connection().fetchval(
                self.queries.create_content(), new_content)
            await connection().execute(
                self.queries.create_revision(),
                page['page_id'],
                member.id,
                page['original_title'],
                content_id,
            )

            if page['alias']:
                return page['original_title']
コード例 #4
0
	async def unmark(self, user_id, points):
		indices = list(map(bingo.index, points))
		mask = functools.reduce(operator.or_, (1 << i for i in indices))
		async with connection().transaction(isolation='serializable'):
			params = list(zip(itertools.repeat(user_id), indices))
			await connection().executemany(self.queries.delete_board_mark(), params)
			await connection().execute(self.queries.delete_board_marks_by_mask(), user_id, mask)
コード例 #5
0
 async def unwatch(self, ctx, *, title: clean_content):
     """Removes a page from your watch list."""
     async with connection().transaction():
         await self.wiki_db.get_page(ctx.author,
                                     title,
                                     partial=True,
                                     check_permissions=False)
         await self.db.unwatch_page(ctx.author, title)
     await ctx.message.add_reaction(self.bot.config['success_emojis'][True])
コード例 #6
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
 async def unbind(self, member, message: discord.Message):
     """Unbind a message. Return whether the message was successfully unbound."""
     async with connection().transaction():
         page = await self.get_bound_page(message)
         await self.wiki_db.check_permissions(member,
                                              Permissions.manage_bindings,
                                              page.title)
         tag = await connection().execute(self.queries.unbind(), message.id)
     return tag == 'DELETE 1'
コード例 #7
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def watch_page(self, member, title) -> bool:
        """subscribe the given user to the given page.
		return success, ie True if they were not a subscriber before.
		"""
        async with connection().transaction():
            title = (await self.wiki_db.resolve_page(member, title)).target
            tag = await connection().execute(self.queries.watch_page(),
                                             member.guild.id, member.id, title)
            if tag.rsplit(None, 1)[-1] == '0':
                raise errors.PageNotFoundError(title)
コード例 #8
0
	async def mark(self, user_id, marks):
		async with connection().transaction(isolation='repeatable_read'):
			marks = list(marks)
			params = (
				(user_id, bingo.index(point), emote.nsfw, emote.name, emote.id, emote.animated)
				for point, emote
				in marks)
			await connection().executemany(self.queries.set_board_mark(), params)
			indices = map(compose(bingo.index, operator.itemgetter(0)), marks)
			mask = functools.reduce(operator.or_, (1 << i for i in indices))
			await connection().execute(self.queries.add_board_marks_by_mask(), user_id, mask)
コード例 #9
0
    async def mark(self, context, *,
                   args: MultiConverter[str.upper, DatabaseOrLoggedEmote]):
        """Adds one or more marks to your board."""
        if not args:
            raise commands.BadArgument(
                _('You must specify at least one position and emote name.'))

        async with connection().transaction(isolation='repeatable_read'):
            await self.db.mark(context.author.id, args)
            board = await self.db.get_board(context.author.id)

        message = _('You win! Your new bingo board:') if board.has_won(
        ) else _('Your new bingo board:')
        await self.send_board(context, message, board)
コード例 #10
0
	async def new_board(self, user_id):
		async with connection().transaction(isolation='repeatable_read'):
			await connection().execute(self.queries.delete_board(), user_id)
			await connection().execute(self.queries.set_board_value(), user_id, DEFAULT_BOARD_VALUE)
			rows = await connection().fetch(self.queries.get_categories(), bingo.BingoBoard.SQUARES)
			to_insert = [
				(user_id, pos + 1 if pos >= bingo.BingoBoard.FREE_SPACE_I else pos, category_id)  # skip free space
				for pos, (category_id, category_text)
				in enumerate(rows)]
			await connection().copy_records_to_table(
				'bingo_board_categories',
				records=to_insert,
				columns=('user_id', 'pos', 'category_id'))
			return bingo.EmoteCollectorBingoBoard(categories=[category_text for __, category_text in rows])
コード例 #11
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def get_page_overwrites_for(
            self, guild_id, entity_id: int,
            title) -> typing.Tuple[Permissions, Permissions]:
        async with connection().transaction():
            page_id = await connection().fetchval(self.queries.get_page_id(),
                                                  guild_id, title)
            if page_id is None:
                raise errors.PageNotFoundError(title)

            row = await connection().fetchrow(
                self.queries.get_page_overwrites_for(), page_id, entity_id)

            if row is None:
                return (Permissions.none, Permissions.none)
            return tuple(map(Permissions, row))
コード例 #12
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def get_page_overwrites(
            self, guild_id, title
    ) -> typing.Mapping[int, typing.Tuple[Permissions, Permissions]]:
        """get the allowed and denied permissions for a particular page"""
        async with connection().transaction():
            page_id = await connection().fetchval(self.queries.get_page_id(),
                                                  guild_id, title)
            if page_id is None:
                raise errors.PageNotFoundError(title)

            return {
                entity: (Permissions(allow), Permissions(deny))
                for entity, allow, deny in await connection().fetch(
                    self.queries.get_page_overwrites(), page_id)
            }
コード例 #13
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def alias_page(self, member, alias_title, target_title):
        self.check_title(alias_title)

        async with connection().transaction():
            await self.check_permissions(member, Permissions.create)
            await self.check_permissions(member, Permissions.view,
                                         target_title)
            await self.ensure_title_available(member, alias_title)

            try:
                await connection().execute(self.queries.alias_page(),
                                           member.guild.id, alias_title,
                                           target_title)
            except asyncpg.NotNullViolationError:
                # the CTE returned no rows
                raise errors.PageNotFoundError(target_title)
            except asyncpg.UniqueViolationError:
                raise errors.PageExistsError
コード例 #14
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
 async def bind(self,
                member,
                message: discord.Message,
                title,
                *,
                check_permissions=True):
     async with connection().transaction():
         page = await self.wiki_db.get_page(member,
                                            title,
                                            check_permissions=False)
         if check_permissions:
             await self.wiki_db.check_permissions(
                 member, Permissions.manage_bindings, title)
         await connection().execute(self.queries.bind(), message.channel.id,
                                    message.id, page.page_id)
     binding = page
     binding.channel_id = message.channel.id
     binding.message_id = message.id
     return binding
コード例 #15
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def resolve_page(self, member, title):
        # XXX if a user is denied permissions for a page, that applies to its aliases too.
        # So if a user is denied view permissions for a single page, and they request info on an alias to that page,
        # the fact that they were denied permission to view that alias would leak information about what
        # page it is an alias to. Consider allowing anyone to resolve an alias, or only denying those who
        # were globally denied view permissions.
        async with connection().transaction():
            await self.check_permissions(member, Permissions.view, title)
            row = await connection().fetchrow(self.queries.get_alias(),
                                              member.guild.id, title)
            if row is not None:
                return AttrDict(row)

            row = await connection().fetchrow(self.queries.get_page_no_alias(),
                                              member.guild.id, title)
            if row is not None:
                return AttrDict(row)

            raise errors.PageNotFoundError(title)
コード例 #16
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def rename_page(self, member, title, new_title):
        self.check_title(new_title)

        async with connection().transaction(isolation='serializable'):
            await self.ensure_title_available(member, new_title)

            try:
                page_id = await connection().fetchval(
                    self.queries.rename_page(), member.guild.id, title,
                    new_title)
            except asyncpg.UniqueViolationError:
                raise errors.PageExistsError

            if page_id is None:
                raise errors.PageNotFoundError(title)

            content_id = await connection().fetchval(
                self.queries.get_content_id(), page_id)
            await connection().execute(self.queries.log_page_rename(), page_id,
                                       member.id, content_id, new_title)
コード例 #17
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def create_page(self, member, title, content):
        self.check_title(title)
        self.check_content(content)

        async with connection().transaction(isolation='serializable'):
            await self.check_permissions(member, Permissions.create)
            if await connection().fetchrow(self.queries.get_alias(),
                                           member.guild.id, title):
                raise errors.PageExistsError

            try:
                page_id = await connection().fetchval(
                    self.queries.create_page(), member.guild.id, title)
            except asyncpg.UniqueViolationError:
                raise errors.PageExistsError

            content_id = await connection().fetchval(
                self.queries.create_content(), content)
            await connection().execute(self.queries.create_first_revision(),
                                       page_id, member.id, content_id, title)
コード例 #18
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
    async def on_cm_page_edit(self, revision_id):
        async with connection().transaction():
            old, new = await self.get_revision_and_previous(revision_id)
            guild = self.bot.get_guild(new.guild_id)
            if guild is None:
                logger.warning(
                    f'on_cm_page_edit: guild_id {new.guild_id} not found!')
                return

            async def send(user_id):
                # editing a page you subscribe to should not notify yourself
                if user_id == new.author_id:
                    return

                try:
                    recipient = await utils.fetch_member(guild, user_id)
                except discord.NotFound:
                    return

                try:
                    await self.wiki_db.check_permissions(
                        recipient, Permissions.view, new.current_title)
                except errors.MissingPagePermissionsError:
                    return

                with contextlib.suppress(discord.NotFound):
                    new.author = await utils.fetch_member(guild, new.author_id)

                with contextlib.suppress(discord.NotFound):
                    old.author = await utils.fetch_member(guild, old.author_id)

                await recipient.send(
                    embed=self.page_edit_notification(recipient, old, new))

            await asyncio.gather(
                *map(send, await self.page_subscribers(new.page_id)))
コード例 #19
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
 async def _bound_messages(self, page_id):
     async with connection().transaction():
         async for row in connection().cursor(self.queries.bound_messages(),
                                              page_id):
             yield AttrDict(row)
コード例 #20
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
 async def bound_messages(self, member, title):
     async with connection().transaction():
         page = await self.wiki_db.get_page(member, title, partial=True)
         async for row in self._bound_messages(page.page_id):
             yield row
コード例 #21
0
ファイル: db.py プロジェクト: ioistired/chrona
 async def latest_message_per_channel(self, cutoff: int):
     async with connection().transaction():
         async for row in connection().cursor(
                 self.queries.latest_message_per_channel(), cutoff):
             yield row
コード例 #22
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
 async def watch_list(self, member):
     async with connection().transaction():
         async for page_id, title in connection().cursor(
                 self.queries.watch_list(), member.guild.id, member.id):
             yield page_id, title
コード例 #23
0
ファイル: db.py プロジェクト: ioistired/cautious-memory
 async def cursor(self, query, *args):
     """return an async iterator over all rows matched by query and args. Lazy equivalent to fetch()"""
     async with connection().transaction():
         async for row in connection().cursor(query, *args):
             yield AttrDict(row)