Example #1
0
def clean(config: CleanTootsConfig, delete: bool, headless: bool):
    """
    Delete Toots based on rules in config file.

    Without the `--delete` flag, toots will only be displayed.
    """
    if not _config_has_sections(config):
        return
    h = html2text.HTML2Text()
    h.ignore_links = True
    h.ignore_emphasis = True
    h.ignore_images = True
    h.ignore_tables = True

    for section in config.sections():
        section = config[section]
        user_secret_file = config.file(section.get("user_secret_file"))
        mastodon = Mastodon(access_token=user_secret_file)
        user = mastodon.me()
        page = mastodon.account_statuses(user["id"])
        would_delete = []
        protected = []
        while page:
            for toot in page:
                protection_reason = _toot_protection_reason(toot, section)
                if protection_reason:
                    protected.append({"toot": toot, "reason": protection_reason})
                else:
                    would_delete.append(toot)

            page = mastodon.fetch_next(page)

        _delete_or_log(delete, h, headless, mastodon, protected, would_delete)
Example #2
0
def clear_credentials(config: CleanTootsConfig):
    """Delete all credential files described in config file."""
    if not _config_has_sections(config):
        return
    for section_name in config.sections():
        section = config[section_name]
        try:
            os.remove(config.file(section.get("app_secret_file")))
        except FileNotFoundError:
            pass
        try:
            os.remove(config.file(section.get("user_secret_file")))
        except FileNotFoundError:
            pass
        click.secho(f"Removed files for {section_name}", fg="green")
Example #3
0
def list_(config: CleanTootsConfig):
    """Display parsed config."""
    if not _config_has_sections(config):
        return
    for section_name in config.sections():
        click.secho(section_name, bold=True)
        section = config[section_name]
        for key, value in section.items():
            click.secho(f"{key} = {value}")
        click.echo()
Example #4
0
def login(config: CleanTootsConfig, only_missing: bool):
    """Fetch credentials for each app described in config file."""
    if not _config_has_sections(config):
        return
    prompt = True
    for section in config.sections():
        section = config[section]
        app_file_exists = config.isfile(section.get("app_secret_file"))
        user_file_exists = config.isfile(section.get("user_secret_file"))

        if not (only_missing and app_file_exists):
            Mastodon.create_app(
                "cleantoots",
                api_base_url=section.get("api_base_url"),
                to_file=config.file(section.get("app_secret_file")),
            )

        mastodon = Mastodon(
            client_id=config.file(section.get("app_secret_file")))
        if not (only_missing and user_file_exists and app_file_exists):
            _open_url(mastodon.auth_request_url(), echo=prompt)
            prompt = False
            code = click.prompt("Enter code for {}".format(
                section.get("api_base_url")))
            mastodon.log_in(code=code,
                            to_file=config.file(
                                section.get("user_secret_file")))
Example #5
0
def cli(ctx, config_dir, config_file):
    """
    Provide an easy interface for deleting old toots.

    \b
    Steps, in order:
    1. run `config setup`
    2. run `config login`
    3. run `clean --delete`
    """
    ctx.obj = CleanTootsConfig(config_dir, config_file)
    log_file = os.path.join(config_dir, "cleantoots.log")
    logging.config.dictConfig({
        "version": 1,
        "formatters": {
            "precise": {
                "format": "{asctime} | {name} | {levelname} | {message}",
                "style": "{",
            }
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "stream": sys.stdout,
                "level": "INFO",
                "formatter": "precise",
            },
            "file": {
                "class": "logging.handlers.RotatingFileHandler",
                "filename": log_file,
                "maxBytes": 1024 * 100,
                "backupCount": 3,
                "level": "INFO",
                "formatter": "precise",
            },
        },
        "loggers": {
            "cleantoots": {
                "level": "INFO",
                "handlers": ["console", "file"]
            }
        },
    })