Example #1
0
def handle(bot: Bot, event: events.TextMessage, match: typing.Match):
    try:
        account = fetch_api("account", api_key=match.group(1))
        server = enums.World(account.get("world"))

        guilds = (
            bot.session.query(models.Guild)
            .filter(models.Guild.guid.in_(account.get("guilds", [])))
            .filter(models.Guild.group_id.isnot(None))
            .options(load_only(models.Guild.name))
        )

        bot.send_message(
            event.id,
            "info_world",
            user=account.get("name"),
            world=server.proper_name,
            guilds=", ".join([_.name for _ in guilds]),
        )
    except InvalidKeyException:
        logging.info("This seems to be an invalid API key.")
        bot.send_message(event.id, "invalid_token")
    except (requests.RequestException, RateLimitException, ApiErrBadData):
        logging.exception("Error during API call")
        bot.send_message(event.id, "error_api")
Example #2
0
def handle(bot: Bot, event: events.TextMessage, match: typing.Match):
    if event.uid not in Config.whitelist_admin:
        return

    try:
        json = fetch_api("account", api_key=match.group(1))
        account = models.Account.get_by_api_info(
            bot.session, guid=json.get("id"), name=json.get("name")
        )

        # Account does not exist
        if not account:
            logging.info("User was not registered.")
            bot.send_message(event.id, "account_unknown", account=json.get("name"))
            return

        # Get previous identity
        previous_identity: typing.Optional[
            models.LinkAccountIdentity
        ] = account.valid_identities.one_or_none()

        # Remove previous links
        account.invalidate(bot.session)

        if previous_identity:
            # Get cldbid and sync groups
            try:
                cldbid = bot.exec_(
                    "clientgetdbidfromuid", cluid=previous_identity.identity.guid
                )[0]["cldbid"]

                result = sync_groups(bot, cldbid, account, remove_all=True)

                logging.info(
                    "%s (%s) marked previous links of %s as ignored",
                    event.name,
                    event.uid,
                    account.name,
                )

                bot.send_message(
                    event.id,
                    "groups_revoked",
                    amount="1",
                    groups=result["removed"],
                )
            except ts3.TS3Error:
                # User might not exist in the db
                logging.info("Failed to remove groups from user", exc_info=True)

        else:
            bot.send_message(event.id, "groups_revoked", amount="0", groups=[])
    except InvalidKeyException:
        logging.info("This seems to be an invalid API key.")
        bot.send_message(event.id, "invalid_token")
    except ApiErrBadData:
        bot.send_message(event.id, "error_api")
Example #3
0
 def create(guid: str, group_id: int = None):
     """
     Retrieves guild details from the API and returns an instance or None if the guild was not found
     :exception NotFoundException
     :exception RateLimitException
     :exception requests.RequestException
     """
     data = ts3bot.fetch_api(f"guild/{guid}")
     return Guild(
         guid=guid,
         name=data.get("name", "undefined"),
         tag=data.get("tag", "undefined"),
         group_id=group_id,
     )
Example #4
0
def handle(bot: Bot, event: events.TextMessage, match: typing.Match):
    if event.uid not in Config.whitelist_admin:
        return

    # Grab client_uid
    try:
        user = bot.exec_("clientgetnamefromdbid", cldbid=match.group(1))
        client_uid = user[0]["cluid"]
    except ts3.query.TS3QueryError:
        bot.send_message(event.id, "user_not_found")
        return

    try:
        json = fetch_api("account", api_key=match.group(2))
        account = models.Account.get_or_create(bot.session, json,
                                               match.group(2))
        identity: models.Identity = models.Identity.get_or_create(
            bot.session, client_uid)

        # Save api key in account
        account.api_key = match.group(2)
        account.is_valid = True
        bot.session.commit()

        transfer_registration(
            bot,
            account,
            event,
            is_admin=True,
            target_identity=identity,
            target_dbid=match.group(1),
        )
    except InvalidKeyException:
        logging.info("This seems to be an invalid API key.")
        bot.send_message(event.id, "invalid_token")
        return
    except (RateLimitException, RequestException, ApiErrBadData):
        bot.send_message(event.id, "error_api")
Example #5
0
def handle(bot: Bot, event: events.TextMessage, match: Match) -> None:
    key = match.group(1)

    # Check with ArenaNet's API
    try:
        account_info = fetch_api("account", api_key=key)

        # Check if one of the guilds is in the alliance
        is_part_of_alliance = (bot.session.query(models.Guild).filter(
            models.Guild.guid.in_(account_info.get("guilds", []))).filter(
                models.Guild.is_part_of_alliance.is_(True)).count() > 0)

        # One of the guilds is in the alliance
        if is_part_of_alliance:
            account: models.Account = models.Account.get_or_create(
                bot.session, account_info, key)
            identity: models.Identity = models.Identity.get_or_create(
                bot.session, event.uid)

            # Check if account is registered to anyone
            linked_identity: Optional[
                models.
                LinkAccountIdentity] = account.valid_identities.one_or_none()

            # Account is already linked
            if linked_identity:
                # Account is linked to another guid
                if linked_identity.identity.guid != event.uid:
                    try:
                        # Get user's DB id
                        cldbid: str = bot.exec_("clientgetdbidfromuid",
                                                cluid=event.uid)[0]["cldbid"]
                    except ts3.TS3Error:
                        LOG.error("Failed to get user's dbid", exc_info=True)
                        bot.send_message(event.id, "error_critical")
                        return

                    force_key_name = f"ts3bot-{cldbid}"

                    # Fetch token info
                    token_info = fetch_api("tokeninfo", api_key=key)

                    # Override registration, same as !register
                    if token_info.get("name", "") == force_key_name:
                        ts3bot.transfer_registration(bot, account, event)

                        LOG.info(
                            "%s (%s) transferred permissions of %s onto themselves.",
                            event.name,
                            event.uid,
                            account_info.get("name"),
                        )
                        return

                    LOG.warning(
                        "%s (%s) tried to use an already registered API key/account. (%s)",
                        event.name,
                        event.uid,
                        account_info.get("name"),
                    )
                    bot.send_message(event.id,
                                     "token_in_use",
                                     api_name=force_key_name)
                else:  # Account is linked to current guid
                    LOG.info(
                        "User %s (%s) tried to register a second time for whatever reason using %s",
                        event.name,
                        event.uid,
                        account_info.get("name", "Unknown account"),
                    )

                    # Save new API key
                    if account.api_key != key:
                        account.api_key = key
                        account.is_valid = True
                        bot.session.commit()
                        bot.send_message(event.id, "registration_exists")
                        return

                    # Same API key supplied, last check was over 12 minutes ago
                    if (ts3bot.timedelta_hours(datetime.datetime.today() -
                                               account.last_check) >= 0.2):
                        # Update saved account info if same API key was posted again with a reasonable time frame
                        account.update(bot.session)
                        try:
                            # Get user's DB id
                            cldbid = bot.exec_("clientgetdbidfromuid",
                                               cluid=event.uid)[0]["cldbid"]

                            # Sync groups
                            ts3bot.sync_groups(bot, cldbid, account)
                            bot.send_message(event.id,
                                             "registration_details_updated")
                        except ts3.TS3Error:
                            # User might not exist in the db
                            LOG.error("Failed to sync user", exc_info=True)
                    else:
                        # Too early
                        bot.send_message(event.id, "registration_too_early")

            else:
                # Otherwise account is not yet linked and can be used

                # Save API key
                account.api_key = key
                account.is_valid = True
                bot.session.commit()

                # Get user's DB id
                cldbid = bot.exec_("clientgetdbidfromuid",
                                   cluid=event.uid)[0]["cldbid"]

                # Unlink previous account from identity
                current_account = models.Account.get_by_identity(
                    bot.session, event.uid)
                if current_account:
                    LOG.info("Delinking %s from cldbid:%s", current_account,
                             cldbid)
                    current_account.invalidate(bot.session)

                # Register link between models
                bot.session.add(
                    models.LinkAccountIdentity(account=account,
                                               identity=identity))
                bot.session.commit()

                # Add all known guilds to user if enabled
                if Config.getboolean(
                        "guild", "assign_on_register") and Config.getboolean(
                            "guild", "allow_multiple_guilds"):
                    cast(AppenderQuery, account.guilds).filter(
                        models.LinkAccountGuild.id.in_(
                            bot.session.query(models.LinkAccountGuild.id).join(
                                models.Guild).filter(
                                    models.Guild.group_id.isnot(
                                        None)).subquery())).update(
                                            {"is_active": True},
                                            synchronize_session="fetch")
                    bot.session.commit()

                # Sync groups
                sync_groups(bot, cldbid, account)

                LOG.info(
                    "Assigned alliance permissions to %s (%s) using %s",
                    event.name,
                    event.uid,
                    account_info.get("name", "Unknown account"),
                )

                # Was registered with other account previously
                if current_account:
                    bot.send_message(event.id,
                                     "registration_update",
                                     account=account.name)
                else:
                    bot.send_message(event.id, "welcome_registered")

                    # Tell user about !guild if it's enabled
                    if Config.getboolean("commands", "guild"):
                        if Config.getboolean(
                                "guild",
                                "assign_on_register") and Config.getboolean(
                                    "guild", "allow_multiple_guilds"):
                            bot.send_message(event.id, "welcome_registered_3")
                        else:
                            bot.send_message(event.id, "welcome_registered_2")

        else:
            bot.send_message(
                event.id,
                "invalid_world",
                world=enums.World(account_info.get("world")).proper_name,
            )

    except InvalidKeyException:
        LOG.info("This seems to be an invalid API key.")
        bot.send_message(event.id, "invalid_token_retry")
    except (RateLimitException, RequestException, ApiErrBadData):
        bot.send_message(event.id, "error_api")