First working release
This commit is contained in:
commit
882bf9ab71
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
own-modules
|
||||||
|
config.own
|
||||||
|
*.db
|
90
DanbooruApi.own
Normal file
90
DanbooruApi.own
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
use okhttp, types, json, functional
|
||||||
|
|
||||||
|
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 getPosts(params) {
|
||||||
|
url = "https://danbooru.donmai.us/posts.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
|
||||||
|
post.tags = tomap(post.tag_string.split(" "), def(k) = k, def(v) = 1)
|
||||||
|
this.post = post
|
||||||
|
}
|
||||||
|
|
||||||
|
def isImage(post) {
|
||||||
|
ext = post.file_ext
|
||||||
|
return ext == "jpg" || ext == "png"
|
||||||
|
}
|
||||||
|
|
||||||
|
def getResolution(post) {
|
||||||
|
w = int(post.image_width ?? 0)
|
||||||
|
h = int(post.image_height ?? 0)
|
||||||
|
if w == 0 || h == 0 return ""
|
||||||
|
return "" + w + "x" + h
|
||||||
|
}
|
||||||
|
|
||||||
|
def getImageUrl(post) {
|
||||||
|
fileSize = post.file_size ?? 0
|
||||||
|
if (fileSize >= 9500000) {
|
||||||
|
return post.large_file_url
|
||||||
|
}
|
||||||
|
return post.file_url
|
||||||
|
}
|
||||||
|
|
||||||
|
def getSampleImageUrl(post) {
|
||||||
|
return post.large_file_url
|
||||||
|
}
|
||||||
|
|
||||||
|
def getScore(post) = int(post.score ?? 0)
|
||||||
|
|
||||||
|
def getArtists(post) {
|
||||||
|
return match int(post.tag_count_artist ?? 0) {
|
||||||
|
case 0: []
|
||||||
|
case 1: [post.tag_string_artist]
|
||||||
|
case _: post.tag_string_artist.split(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def getCharacters(post) {
|
||||||
|
return match int(post.tag_count_character ?? 0) {
|
||||||
|
case 0: []
|
||||||
|
case 1: [post.tag_string_character]
|
||||||
|
case _: post.tag_string_character.split(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def getSource(post) {
|
||||||
|
src = post.source
|
||||||
|
if src.contains("twitter") {
|
||||||
|
return src.replace("twitter", "x")
|
||||||
|
}
|
||||||
|
pixivId = post.pixiv_id ?? 0
|
||||||
|
if pixivId {
|
||||||
|
return "https://www.pixiv.net/en/artworks/" + pixivId
|
||||||
|
}
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
}
|
37
config.own.sample
Normal file
37
config.own.sample
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
config = {
|
||||||
|
"telegram": {
|
||||||
|
"token": "required",
|
||||||
|
},
|
||||||
|
"danbooru": {
|
||||||
|
// Danbooru user:api_key
|
||||||
|
"auth": "Basic ZGFuYm9vcnV1c2VyOmFwaWtleQ==",
|
||||||
|
"params": "?page=20",
|
||||||
|
"blacklistTags": "comic doujin_cover".split(" "),
|
||||||
|
},
|
||||||
|
"targets": [{
|
||||||
|
"name": "Artists",
|
||||||
|
"chat": "-100123456",
|
||||||
|
"topic": 0,
|
||||||
|
"minScore": 0, // minimal post score threshold for filtering
|
||||||
|
"tags": "daeraeband doraski doushimasho emyo enka_(bcat) guweiz haluka_(aixioo) hamahama houtengeki kagematsuri kcar66t mikuro mocha_(cotton) mohaka_(m_0haka) namyo omelet_tomato rin_yuu sak_(lemondisk) sakiyamama saru saya_pr sion005 zerocat".split(" "),
|
||||||
|
},{
|
||||||
|
"name": "Azur Lane",
|
||||||
|
"chat": "-100123456",
|
||||||
|
"topic": 7,
|
||||||
|
"minScore": 4,
|
||||||
|
"tags": "azur_lane".split(" "),
|
||||||
|
},{
|
||||||
|
"name": "Blue Archive",
|
||||||
|
"chat": "-100123456",
|
||||||
|
"topic": 9,
|
||||||
|
"minScore": 4,
|
||||||
|
"tags": "blue_archive".split(" "),
|
||||||
|
},{
|
||||||
|
"name": "Anime",
|
||||||
|
"chat": "12345",
|
||||||
|
"topic": 0,
|
||||||
|
"minScore": 6,
|
||||||
|
"tags": "bocchi_the_rock!".split(" "),
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
100
danboo.own
Normal file
100
danboo.own
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
use std, functional, types, date
|
||||||
|
|
||||||
|
include "own-modules/telegram-bot/TelegramBot.own"
|
||||||
|
include "config.own"
|
||||||
|
include "database.own"
|
||||||
|
include "DanbooruApi.own"
|
||||||
|
|
||||||
|
bot = new TelegramBot(config.telegram.token)
|
||||||
|
api = new DanbooruApi(config.danbooru.auth)
|
||||||
|
|
||||||
|
// Get posts from API
|
||||||
|
posts = api.getPosts(config.danbooru.params)
|
||||||
|
// Skip previously processed
|
||||||
|
lastPostId = getLastPostId()
|
||||||
|
skipToPostId = lastPostId
|
||||||
|
filteredPosts = stream(posts)
|
||||||
|
.filter(def(p) = p.isImage(p.post))
|
||||||
|
.sortBy(def(p) = p.id)
|
||||||
|
.dropWhile(def(p) = p.id <= skipToPostId)
|
||||||
|
.peek(def(p) = lastPostId = p.id)
|
||||||
|
.toArray()
|
||||||
|
setLastPostId(lastPostId)
|
||||||
|
|
||||||
|
// Process
|
||||||
|
blacklistTags = config.danbooru.blacklistTags
|
||||||
|
for post : filteredPosts {
|
||||||
|
p = post.post
|
||||||
|
// Check global blacklist
|
||||||
|
blacklisted = stream(blacklistTags)
|
||||||
|
.anyMatch(def(tt) = arrayKeyExists(tt, p.tags))
|
||||||
|
if (blacklisted) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
score = post.getScore(p)
|
||||||
|
|
||||||
|
for target : config.targets {
|
||||||
|
minScore = target.minScore ?? 0
|
||||||
|
if (score < minScore) continue
|
||||||
|
|
||||||
|
matched = stream(target.tags)
|
||||||
|
.anyMatch(def(tt) = arrayKeyExists(tt, p.tags))
|
||||||
|
if (!matched) continue
|
||||||
|
|
||||||
|
url = "https://danbooru.donmai.us/posts/" + p.id
|
||||||
|
println "%s: %s -> %s".sprintf(newDate(), url, target.name)
|
||||||
|
|
||||||
|
caption = getCaption(post)
|
||||||
|
buttonText = sprintf("%s 📈%d", post.getResolution(p), score)
|
||||||
|
markup = jsonencode({"inline_keyboard": [
|
||||||
|
[{"text":buttonText, "url":url}]
|
||||||
|
]})
|
||||||
|
bot.invoke("sendPhoto", {
|
||||||
|
"chat_id": target.chat,
|
||||||
|
"message_thread_id": target.topic,
|
||||||
|
"photo": post.getImageUrl(p),
|
||||||
|
"parse_mode": "html",
|
||||||
|
"caption": caption,
|
||||||
|
"reply_markup": markup
|
||||||
|
}, def(r) {
|
||||||
|
if !r.contains("wrong file identifier") return 1
|
||||||
|
bot.invoke("sendPhoto", {
|
||||||
|
"chat_id": target.chat,
|
||||||
|
"message_thread_id": target.topic,
|
||||||
|
"photo": post.getSampleImageUrl(p),
|
||||||
|
"parse_mode": "html",
|
||||||
|
"caption": "small " + caption,
|
||||||
|
"reply_markup": markup
|
||||||
|
}, def(r) = 1)
|
||||||
|
})
|
||||||
|
sleep(2000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closeDB()
|
||||||
|
thread(def() {
|
||||||
|
sleep(2000)
|
||||||
|
exit(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
def strToHashtag(str) =
|
||||||
|
"#" + str.toLowerCase()
|
||||||
|
.replaceAll("[^a-z_0-9\s]", "")
|
||||||
|
.replaceAll("\s+", "_")
|
||||||
|
|
||||||
|
def getCaption(post) {
|
||||||
|
p = post.post
|
||||||
|
characters = post.getCharacters(p)
|
||||||
|
if characters.length > 0 {
|
||||||
|
charactersHashTag = map(characters, ::strToHashtag).joinToString(" ")
|
||||||
|
} else {
|
||||||
|
charactersHashTag = "#original"
|
||||||
|
}
|
||||||
|
sourceUrl = post.getSource(p)
|
||||||
|
return "%s | <a href=\"%s\">source</a>".sprintf(
|
||||||
|
charactersHashTag,
|
||||||
|
sourceUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
37
database.own
Normal file
37
database.own
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use jdbc
|
||||||
|
|
||||||
|
conn = getConnection("jdbc:sqlite:danboo.db")
|
||||||
|
|
||||||
|
st = conn.createStatement()
|
||||||
|
st.executeUpdate(
|
||||||
|
"CREATE TABLE IF NOT EXISTS meta (
|
||||||
|
prop TEXT PRIMARY KEY,
|
||||||
|
num_value INTEGER,
|
||||||
|
str_value TEXT
|
||||||
|
)")
|
||||||
|
st.executeUpdate(
|
||||||
|
"INSERT OR IGNORE INTO meta(prop, num_value, str_value) VALUES('last_id', 0, '')")
|
||||||
|
st.close()
|
||||||
|
|
||||||
|
stGetNumValue = conn.prepareStatement(
|
||||||
|
"SELECT num_value FROM meta WHERE prop = ?")
|
||||||
|
stSetNumValue = conn.prepareStatement(
|
||||||
|
"UPDATE meta SET num_value = ? WHERE prop = ?")
|
||||||
|
|
||||||
|
def getLastPostId() {
|
||||||
|
stGetNumValue.setString(1, "last_id")
|
||||||
|
rs = stGetNumValue.executeQuery()
|
||||||
|
return rs.getInt(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
def setLastPostId(postId) {
|
||||||
|
stSetNumValue.setInt(1, postId)
|
||||||
|
stSetNumValue.setString(2, "last_id")
|
||||||
|
stSetNumValue.executeUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
def closeDB() {
|
||||||
|
stGetNumValue.close()
|
||||||
|
stSetNumValue.close()
|
||||||
|
conn.close()
|
||||||
|
}
|
6
modules.json
Normal file
6
modules.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "18f1894447dfa72000a83011511a817c",
|
||||||
|
"name": "telegram-bot"
|
||||||
|
}
|
||||||
|
]
|
39
modules.own
Normal file
39
modules.own
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use std
|
||||||
|
|
||||||
|
if (ARGS.length >= 2 && ARGS[0] == "owm") {
|
||||||
|
use files, json, java
|
||||||
|
|
||||||
|
File = newClass("java.io.File")
|
||||||
|
runtime = newClass("java.lang.Runtime").getRuntime()
|
||||||
|
|
||||||
|
def loadModulesJson(path = "modules.json") {
|
||||||
|
f = fopen(path, "r")
|
||||||
|
modules = jsondecode(readText(f))
|
||||||
|
fclose(f)
|
||||||
|
return modules
|
||||||
|
}
|
||||||
|
def exec(cmd, dir = ".") = runtime.exec(cmd, null, new File(dir))
|
||||||
|
|
||||||
|
match (ARGS[1]) {
|
||||||
|
case "install": {
|
||||||
|
modulesDir = "own-modules"
|
||||||
|
if (!exists(modulesDir)) {
|
||||||
|
mkdir(modulesDir)
|
||||||
|
}
|
||||||
|
for module : loadModulesJson() {
|
||||||
|
print module.name
|
||||||
|
moduleDir = modulesDir + "/" + module.name
|
||||||
|
if (!exists(moduleDir)) {
|
||||||
|
mkdir(moduleDir)
|
||||||
|
cmd = "git clone https://gist.github.com/" + module.id + ".git " + module.name
|
||||||
|
exec(cmd, modulesDir)
|
||||||
|
println " installed"
|
||||||
|
} else {
|
||||||
|
exec("git pull origin master", moduleDir)
|
||||||
|
println " updated"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user