# Path: bansync/converters.py
# class MentionOrID(NamedTuple):
#     id: int
# 
#     @classmethod
#     async def convert(cls, ctx: Context, argument: str):
# 
#         match = _id_regex.match(argument) or _mention_regex.match(argument)
#         if match:
#             return cls(int(match.group(1)))
# 
#         raise BadArgument()
# 
# class ParserError(Exception):
#     pass
# 
# class SyndicatedConverter:
#     """
#     Parser based converter.
# 
#     Takes sources, and either
#         destinations, a flag to automatically determine destinations, or both
#     """
# 
#     sources: Set[discord.Guild]
#     dests: Set[discord.Guild]
#     usr: Union[discord.Member, discord.User]
#     shred_ratelimits: bool = False
#     auto: bool = False
# 
#     def to_dict(self) -> dict:
#         return {
#             "sources": self.sources,
#             "dests": self.dests,
#             "usr": self.usr,
#             "shred_ratelimits": self.shred_ratelimits,
#             "auto": self.auto,
#         }
# 
#     @classmethod
#     async def convert(cls, ctx: Context, argument: str):
# 
#         parser = NoExitParser(description="Syndicated Ban Syntax", add_help=False)
#         parser.add_argument("--sources", nargs="*", dest="sources", default=[])
#         parser.add_argument("--destinations", nargs="*", dest="dests", default=[])
#         parser.add_argument(
#             "--auto-destinations", action="store_true", default=False, dest="auto"
#         )
#         parser.add_argument(
#             "--shred-ratelimits",
#             action="store_true",
#             default=False,
#             dest="shred_ratelimits",
#         )
# 
#         vals = parser.parse_args(shlex.split(argument))
# 
#         guilds = set(ctx.bot.guilds)
# 
#         sources = set(filter(lambda g: str(g.id) in vals.sources, guilds))
#         if not sources:
#             raise ParserError("I need at least 1 source.")
# 
#         if vals.auto:
#             destinations = guilds - sources
#         elif vals.dests:
#             destinations = set()
#             for guild in guilds:
#                 to_comp = str(guild.id)
#                 if to_comp in vals.dests and to_comp not in sources:
#                     destinations.add(guild)
#         else:
#             raise ParserError(
#                 "I need either at least one destination, "
#                 " to be told to automatically determine destinations, "
#                 "or a combination of both to add extra destinations beyond the automatic."
#             )
# 
#         return cls(
#             sources=sources,
#             dests=destinations,
#             shred_ratelimits=vals.shred_ratelimits,
#             auto=vals.auto,
#             usr=ctx.author,
#         )


import asyncio
import io
import json
import logging
import discord
from datetime import datetime
from typing import (
    AsyncIterator,
    Collection,
    Dict,
    Generator,
    List,
    Optional,
    Set,
    Tuple,
    Union,
    cast,
)
from discord.ext.commands import Greedy
from redbot.core import checks, commands
from redbot.core.bot import Red
from redbot.core.config import Config
from redbot.core.data_manager import cog_data_path
from redbot.core.modlog import create_case as _red_create_case
from redbot.core.utils.chat_formatting import box, pagify
from .converters import MentionOrID, ParserError, SyndicatedConverter
        syncs bans across servers
        """
        guilds: GuildSet = set()
        if not auto:
            while True:
                s = await self.interactive(ctx, guilds)
                if s == -1:
                    break
                if s == -2:
                    return await ctx.send("You took too long, try again later")
                if s is not None:
                    guilds.add(s)

        elif auto is True:
            opt_ins = await self.config.opted_into_automatic()
            guilds = {
                g
                for g in self.bot.guilds
                if g.id in opt_ins and await self.can_sync(g, ctx.author)
            }

        if len(guilds) < 2:
            return await ctx.send("I need at least two servers to sync")

        async with ctx.typing():
            await self.process_sync(usr=ctx.author, sources=guilds, dests=guilds)
        await ctx.tick()

    @checks.is_owner()
    @commands.command(name="syndicatebans")

# Path: bansync/converters.py
# class MentionOrID(NamedTuple):
#     id: int
# 
#     @classmethod
#     async def convert(cls, ctx: Context, argument: str):
# 
#         match = _id_regex.match(argument) or _mention_regex.match(argument)
#         if match:
#             return cls(int(match.group(1)))
# 
#         raise BadArgument()
# 
# class ParserError(Exception):
#     pass
# 
# class SyndicatedConverter:
#     """
#     Parser based converter.
# 
#     Takes sources, and either
#         destinations, a flag to automatically determine destinations, or both
#     """
# 
#     sources: Set[discord.Guild]
#     dests: Set[discord.Guild]
#     usr: Union[discord.Member, discord.User]
#     shred_ratelimits: bool = False
#     auto: bool = False
# 
#     def to_dict(self) -> dict:
#         return {
#             "sources": self.sources,
#             "dests": self.dests,
#             "usr": self.usr,
#             "shred_ratelimits": self.shred_ratelimits,
#             "auto": self.auto,
#         }
# 
#     @classmethod
#     async def convert(cls, ctx: Context, argument: str):
# 
#         parser = NoExitParser(description="Syndicated Ban Syntax", add_help=False)
#         parser.add_argument("--sources", nargs="*", dest="sources", default=[])
#         parser.add_argument("--destinations", nargs="*", dest="dests", default=[])
#         parser.add_argument(
#             "--auto-destinations", action="store_true", default=False, dest="auto"
#         )
#         parser.add_argument(
#             "--shred-ratelimits",
#             action="store_true",
#             default=False,
#             dest="shred_ratelimits",
#         )
# 
#         vals = parser.parse_args(shlex.split(argument))
# 
#         guilds = set(ctx.bot.guilds)
# 
#         sources = set(filter(lambda g: str(g.id) in vals.sources, guilds))
#         if not sources:
#             raise ParserError("I need at least 1 source.")
# 
#         if vals.auto:
#             destinations = guilds - sources
#         elif vals.dests:
#             destinations = set()
#             for guild in guilds:
#                 to_comp = str(guild.id)
#                 if to_comp in vals.dests and to_comp not in sources:
#                     destinations.add(guild)
#         else:
#             raise ParserError(
#                 "I need either at least one destination, "
#                 " to be told to automatically determine destinations, "
#                 "or a combination of both to add extra destinations beyond the automatic."
#             )
# 
#         return cls(
#             sources=sources,
#             dests=destinations,
#             shred_ratelimits=vals.shred_ratelimits,
#             auto=vals.auto,
#             usr=ctx.author,
#         )


# Path: bansync/bansync.py
import asyncio
import io
import json
import logging
import discord
from datetime import datetime
from typing import (
    AsyncIterator,
    Collection,
    Dict,
    Generator,
    List,
    Optional,
    Set,
    Tuple,
    Union,
    cast,
)
from discord.ext.commands import Greedy
from redbot.core import checks, commands
from redbot.core.bot import Red
from redbot.core.config import Config
from redbot.core.data_manager import cog_data_path
from redbot.core.modlog import create_case as _red_create_case
from redbot.core.utils.chat_formatting import box, pagify
from .converters import MentionOrID, ParserError, SyndicatedConverter

        syncs bans across servers
        """
        guilds: GuildSet = set()
        if not auto:
            while True:
                s = await self.interactive(ctx, guilds)
                if s == -1:
                    break
                if s == -2:
                    return await ctx.send("You took too long, try again later")
                if s is not None:
                    guilds.add(s)

        elif auto is True:
            opt_ins = await self.config.opted_into_automatic()
            guilds = {
                g
                for g in self.bot.guilds
                if g.id in opt_ins and await self.can_sync(g, ctx.author)
            }

        if len(guilds) < 2:
            return await ctx.send("I need at least two servers to sync")

        async with ctx.typing():
            await self.process_sync(usr=ctx.author, sources=guilds, dests=guilds)
        await ctx.tick()

    @checks.is_owner()
    @commands.command(name="syndicatebans")

    async def syndicated_bansync(self, ctx, *, query: SyndicatedConverter):