use okhttp, types, json, functional URL = "https://danbooru.donmai.us/posts" NO_IMAGE = "https://upload.wikimedia.org/wikipedia/commons/1/14/No_Image_Available.jpg" class DanbooruApi { def DanbooruApi(auth) { this.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0" } if auth != "" { this.headers["Authorization"] = auth } } def getPost(id) { url = URL + "/" + id + ".json" response = okhttp.request() .headers(this.headers) .url(url) .get() .newCall(okhttp.client) .execute() .body() .string() if (!length(response)) return [] post = jsondecode(response) if (typeof(post) != MAP) return [] return new Post(post) } def getPosts(params) { url = URL + ".json" + params response = okhttp.request() .headers(this.headers) .url(url) .get() .newCall(okhttp.client) .execute() .body() .string() if (!length(response)) return [] posts = jsondecode(response) if (typeof(posts) != ARRAY) return [] return map(posts, def(p) = new Post(p)) } } class Post { def Post(post) { this.id = int(post.id) ?? 0 this.tags = tomap(post.tag_string.split(" "), def(k) = k, def(v) = 1) this.post = post } def isImage() { ext = this.post.file_ext return ext == "jpg" || ext == "png" } def getResolution() { w = int(this.post.image_width ?? 0) h = int(this.post.image_height ?? 0) if w == 0 || h == 0 return "" return "" + w + "x" + h } def getImageUrl() { fileSize = this.post.file_size ?? 0 if (fileSize >= 9500000) { return this.post.large_file_url ?? NO_IMAGE } return this.post.file_url ?? NO_IMAGE } def getSampleImageUrl() = this.post.large_file_url ?? NO_IMAGE def containsTags(tags) = stream(tags) .anyMatch(def(t) = arrayKeyExists(t, this.tags)) def getScore() = int(this.post.score ?? 0) def getArtists() = match int(this.post.tag_count_artist ?? 0) { case 0: [] case 1: [this.post.tag_string_artist] case _: this.post.tag_string_artist.split(" ") } def getCopyrights() = match int(this.post.tag_count_copyright ?? 0) { case 0: [] case 1: [this.post.tag_string_copyright] case _: this.post.tag_string_copyright.split(" ") } def getCharacters() = match int(this.post.tag_count_character ?? 0) { case 0: [] case 1: [this.post.tag_string_character] case _: this.post.tag_string_character.split(" ") } def getSource() { src = this.post.source if src.contains("twitter") { return src.replace("twitter", "x") } pixivId = this.post.pixiv_id ?? 0 if pixivId { return "https://www.pixiv.net/en/artworks/" + pixivId } return URL + "/" + this.post.id } } // Helpers def strToHashtag(str) = "#" + str.toLowerCase() .replaceAll("[^a-z_0-9\s]", "") .replaceAll("\s+", "_") def getCharacterHashtags(post) { characters = post.getCharacters() if characters.isEmpty() { return "#original" } copyrights = post.getCopyrights() hashtags = [] for character : characters { hashtag = strToHashtag(character) // Clean-up copyright suffix for copyright : copyrights { replaceFrom = "_" + copyright hashtag = hashtag.replace(replaceFrom, "") } hashtags += hashtag } return hashtags.joinToString(" ") } def getCaption(post) = sprintf( "%s | source", getCharacterHashtags(post), post.getSource() )