import base64 import os.path from mastodon import Mastodon from sys import argv import json import pathlib import random import requests class Config: auth: str block_tags: list[str] danbooru_api_key: str danbooru_username: str nsfw_tags: list[str] search_tags: list[str] text_cw: str text_filler: list[str] url: str def __init__(self, config_name: str): with open(f"config/{config_name}.json") as file: config = json.load(file) self.block_tags = config["blockTags"] self.danbooru_api_key = config["danbooruApiKey"] self.danbooru_username = config["danbooruUsername"] self.nsfw_tags = config["nsfwTags"] self.search_tags = config["searchTags"] self.text_cw = config["textCW"] self.text_filler = config["textFiller"] self.url = config["url"] self.auth = "Basic " + base64.b64encode( bytes(self.danbooru_username + ":" + self.danbooru_api_key, "utf-8")).decode("utf-8") def random_image(config: Config) -> dict | None: tags = [] for tag in config.block_tags: tags.append("-" + tag.strip()) for tag in config.search_tags: tags.append(tag.strip()) tags = " ".join(tags) params = { "random": "1", "tags": tags } resp = requests.get(config.url + "/posts.json", params=params, headers={"Authorization": config.auth}) if not resp.ok: print(resp.json()) return None elif not resp.json(): return None return random.choice(resp.json()) # Exit if config isn't specified if len(argv) < 2: print(f"Usage: python3 {argv[0]} ") exit() config = Config(argv[1]) # Check auth auth = requests.get(config.url + "/profile.json", headers={"Authorization": config.auth}) print(auth.status_code) print(auth.json()) if not auth.ok or auth.json()["id"] is None: print("Authentication failed") exit() post = random_image(config) if post is None: print("Couldn't get an image") exit() filename = f'download/image.{post["file_ext"]}' post_url = config.url + "/posts/" + str(post["id"]) print(post) image = requests.get(post["file_url"]) if not image.ok: print("Couldn't download image") exit() if not os.path.isdir("download"): if not os.path.exists("download"): os.makedirs("download") else: print("\"download\" exists but isn't a directory") exit() with open(filename, "wb") as f: f.write(image.content) # Image is NSFW if rated Explicit, Sensitive or Unknown is_nsfw = not post["rating"].startswith("g") or post["rating"] == None if not is_nsfw: for tag in config.nsfw_tags: # Check if any config defined NSFW tags are present if tag in post["tag_string"].split(): is_nsfw = True # This sucks but it works :3 post_content = [ random.choice(config.text_filler), "\n\n", "Artist: " + post["tag_string_artist"] + "\n" if len(post["tag_string_artist"]) > 0 else "", "Characters: " + post["tag_string_character"] + "\n" if len( post["tag_string_character"]) > 0 else "", "Source: " + post["source"] if len(post["source"]) > 0 else "", "\n\n" + post_url if post_url != "" else "" ] mastodon = Mastodon(access_token=f"auth/{argv[1]}.auth.secret") media = mastodon.media_post( media_file=filename ) status = mastodon.status_post( "".join(post_content), media_ids=[media["id"]], sensitive=is_nsfw, spoiler_text="(NSFW) " + config.text_cw if is_nsfw else config.text_cw, visibility="unlisted" ) print(status["url"]) pathlib.Path(filename).unlink()