0.2.0b #1

Merged
Nyako merged 9 commits from dev into main 2026-06-06 12:34:50 +00:00
7 changed files with 36 additions and 93 deletions
Showing only changes of commit 7fe9b73d49 - Show all commits
+2
View File
@@ -3,8 +3,10 @@
.vscode .vscode
old/ old/
data_test/ data_test/
tmp/
config_gb.json config_gb.json
migration.py migration.py
change_log.txt
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
-64
View File
@@ -1,64 +0,0 @@
{
"total_images_analyzed": 14003,
"average_weight": {
"bytes": 2980950.54,
"formatted": "2.84 MB"
},
"storage_stats": {
"folders": {
"img": "38.88 GB",
"json_db": "24.39 MB",
"thumb": "331.45 MB",
"logs": "14.44 MB"
},
"types_in_img": {
"images": "38.56 GB",
"videos": "140.80 MB",
"gifs": "181.30 MB",
"logs": "14.44 MB"
},
"grand_total": "39.24 GB"
},
"ratings_stats": {
"explicit": {
"count": 1605,
"size_formatted": "4.52 GB"
},
"sensitive": {
"count": 6623,
"size_formatted": "19.35 GB"
},
"questionable": {
"count": 1591,
"size_formatted": "4.72 GB"
},
"general": {
"count": 4184,
"size_formatted": "10.29 GB"
}
},
"resolution_stats": {
"largest": {
"filename": "5adc7e0e773417f9c379accf.png",
"md5": "5a63c28906dc7e0e7734c379accf",
"resolution": "9921x14031"
},
"smallest": {
"filename": "8fc614e712ad21d2151ccde8a3c87.gif",
"md5": "8fc614e712ae22151ccde8a3c87",
"resolution": "240x280"
}
},
"weight_stats": {
"largest": {
"filename": "4cf0a32c61c7e7914095d1fe.png",
"md5": "4ab6acf0a32c61c7e79fe",
"size_formatted": "65.21 MB"
},
"smallest": {
"filename": "2e1c8a5870b90c3f538d7.png",
"md5": "28c679ea3470b90c3f538d7",
"size_formatted": "6.49 KB"
}
}
}
+9 -6
View File
@@ -1,11 +1,14 @@
from system_module import db, gelbooru, logger, image_processor
from flask import Flask, render_template, jsonify, send_from_directory, render_template_string, request
import json import json
import requests import os
from pathlib import Path
import subprocess import subprocess
import traceback import traceback
import os from pathlib import Path
import requests
from flask import (Flask, jsonify, render_template, render_template_string,
request, send_from_directory)
from system_module import db, gelbooru, image_processor, logger
if Path("config_gb.json").exists(): if Path("config_gb.json").exists():
CONFIG_FILE = "config_gb.json" CONFIG_FILE = "config_gb.json"
@@ -119,7 +122,7 @@ def api():
return jsonify(results_send) return jsonify(results_send)
elif data["type"] == "autocomplete": elif data["type"] == "autocomplete":
tag_slise = data["q"] tag_slise = data["q"]
result_autocomplete = database.get_autocomplete(tag_slise) result_autocomplete = database.get_top_tag(tag_slise, count_tag_get=10)
return jsonify(result_autocomplete) return jsonify(result_autocomplete)
elif data["type"] == "post": elif data["type"] == "post":
post_id = data["post_id"] post_id = data["post_id"]
+9 -7
View File
@@ -1,8 +1,10 @@
import sqlite3
import os
import json import json
import os
import sqlite3
from datetime import datetime from datetime import datetime
from system_module import gelbooru
from system_module.gelbooru import gelbooru_date_parse
class DB: class DB:
def __init__(self, debug: bool): def __init__(self, debug: bool):
@@ -117,7 +119,7 @@ class DB:
"score": data_add["score"], "score": data_add["score"],
"timestamp": data_add["created_at"], "timestamp": data_add["created_at"],
"parsed_time": parsed_time, "parsed_time": parsed_time,
"display_date": gelbooru.gelbooru_date_parse(data_add["created_at"]), "display_date": gelbooru_date_parse(data_add["created_at"]),
"source": data_add["source"], "source": data_add["source"],
"width": data_add["width"], "width": data_add["width"],
"height": data_add["height"] "height": data_add["height"]
@@ -165,15 +167,15 @@ class DB:
cursor = self.conn.execute(query, (md5,)) cursor = self.conn.execute(query, (md5,))
return cursor.fetchone() is not None return cursor.fetchone() is not None
def get_autocomplete(self, tag_slise: str): def get_top_tag(self, tag_slise: str, count_tag_get: int = 9999999):
query = """ query = """
SELECT value AS tag, COUNT(*) AS count SELECT value AS tag, COUNT(*) AS count
FROM files, json_each(files.tags) FROM files, json_each(files.tags)
WHERE value LIKE ? WHERE value LIKE ?
GROUP BY value GROUP BY value
ORDER BY count DESC ORDER BY count DESC
LIMIT 10 LIMIT {count_tag_get}
""" """.format(count_tag_get=count_tag_get)
cursor = self.conn.execute(query, (f"{tag_slise.lower()}%",)) cursor = self.conn.execute(query, (f"{tag_slise.lower()}%",))
return [{"tag": row["tag"], "count": row["count"]} for row in cursor.fetchall()] return [{"tag": row["tag"], "count": row["count"]} for row in cursor.fetchall()]
+8 -9
View File
@@ -1,8 +1,10 @@
import requests
from datetime import datetime
import os import os
from datetime import datetime
def gelbooru_date_parse(date_str): import requests
def gelbooru_date_parse(date_str: str):
if not date_str: if not date_str:
return 0, "Unknown" return 0, "Unknown"
try: try:
@@ -13,14 +15,14 @@ def gelbooru_date_parse(date_str):
return 0, "Unknown" return 0, "Unknown"
class GB: class GB:
def __init__(self, api_id, api_hash, headers, dw_folder): def __init__(self, api_id: str, api_hash: str, headers: dict[str, str], dw_folder: str):
self.api_id = api_id self.api_id = api_id
self.api_hash = api_hash self.api_hash = api_hash
self.dw_folder = dw_folder self.dw_folder = dw_folder
self.root_url = "https://gelbooru.com/index.php" self.root_url = "https://gelbooru.com/index.php"
self.HEADERS = headers self.HEADERS = headers
def get_from_id(self, id_post): def get_from_id(self, id_post: int):
params = {"page": "dapi", "s": "post", "q": "index", "json": 1, "id": id_post, "api_key":self.api_hash, "user_id":self.api_id} params = {"page": "dapi", "s": "post", "q": "index", "json": 1, "id": id_post, "api_key":self.api_hash, "user_id":self.api_id}
response = requests.get(self.root_url, params=params, headers=self.HEADERS, timeout=15) response = requests.get(self.root_url, params=params, headers=self.HEADERS, timeout=15)
print(response.url) print(response.url)
@@ -28,13 +30,10 @@ class GB:
file_name = response.json()["post"][0]["image"] file_name = response.json()["post"][0]["image"]
return response.json()["post"][0], url_file, file_name return response.json()["post"][0], url_file, file_name
def get_from_md5(self, md5): def get_from_md5(self, md5: str):
params = {"page": "dapi", "s": "post", "q": "index", "json": 1, "tags":"md5:"+md5, "api_key":self.api_hash, "user_id":self.api_id} params = {"page": "dapi", "s": "post", "q": "index", "json": 1, "tags":"md5:"+md5, "api_key":self.api_hash, "user_id":self.api_id}
response = requests.get(self.root_url, params=params, headers=self.HEADERS, timeout=15) response = requests.get(self.root_url, params=params, headers=self.HEADERS, timeout=15)
print(response.url) print(response.url)
url_file = response.json()["post"][0]["file_url"] url_file = response.json()["post"][0]["file_url"]
file_name = response.json()["post"][0]["image"] file_name = response.json()["post"][0]["image"]
return response.json()["post"][0], url_file, file_name return response.json()["post"][0], url_file, file_name
def get_binary_file(self, id_post):
pass
+6 -5
View File
@@ -1,6 +1,7 @@
import subprocess
from PIL import Image
import os import os
import subprocess
from PIL import Image
EXTENSIONS_IMG = ('jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp') EXTENSIONS_IMG = ('jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp')
EXTENSIONS_VID = ('mp4', 'webm') EXTENSIONS_VID = ('mp4', 'webm')
@@ -15,7 +16,7 @@ def check_ffmpeg():
except (FileNotFoundError, subprocess.CalledProcessError): except (FileNotFoundError, subprocess.CalledProcessError):
return False return False
def video_gen(input_path_file, output_path_file, TARGET_MIN_SIZE): def video_gen(input_path_file: str, output_path_file: str, TARGET_MIN_SIZE: int):
vf_scale = f"scale='if(gt(iw,ih),-1,{TARGET_MIN_SIZE})':'if(gt(iw,ih),{TARGET_MIN_SIZE},-1)'" vf_scale = f"scale='if(gt(iw,ih),-1,{TARGET_MIN_SIZE})':'if(gt(iw,ih),{TARGET_MIN_SIZE},-1)'"
cmd = ["ffmpeg", "-y", "-i", input_path_file, "-ss", "00:00:00", "-vframes", "1", "-vf", vf_scale, "-q:v", "2", output_path_file] cmd = ["ffmpeg", "-y", "-i", input_path_file, "-ss", "00:00:00", "-vframes", "1", "-vf", vf_scale, "-q:v", "2", output_path_file]
if os.name == 'nt': creationflags = subprocess.CREATE_NO_WINDOW if os.name == 'nt': creationflags = subprocess.CREATE_NO_WINDOW
@@ -24,7 +25,7 @@ def video_gen(input_path_file, output_path_file, TARGET_MIN_SIZE):
if result.returncode != 0: if result.returncode != 0:
raise Exception(f"FFmpeg error: {result.stderr.decode('utf-8', errors='ignore')}") raise Exception(f"FFmpeg error: {result.stderr.decode('utf-8', errors='ignore')}")
def image_and_gif_gen(input_path_file, output_path_file, TARGET_MIN_SIZE): def image_and_gif_gen(input_path_file: str, output_path_file: str, TARGET_MIN_SIZE: int):
with Image.open(input_path_file) as img: with Image.open(input_path_file) as img:
img_rgba = img.convert("RGBA") img_rgba = img.convert("RGBA")
background = Image.new("RGB", img_rgba.size, (255, 255, 255)) background = Image.new("RGB", img_rgba.size, (255, 255, 255))
@@ -43,7 +44,7 @@ def image_and_gif_gen(input_path_file, output_path_file, TARGET_MIN_SIZE):
resized_img = final_img.resize((new_width, new_height), Image.Resampling.LANCZOS) resized_img = final_img.resize((new_width, new_height), Image.Resampling.LANCZOS)
resized_img.save(output_path_file, "JPEG", quality=85) resized_img.save(output_path_file, "JPEG", quality=85)
def generate_thumb(input_path_file, THUMB_FOLDER, TARGET_MIN_SIZE): def generate_thumb(input_path_file: str, THUMB_FOLDER: str, TARGET_MIN_SIZE: int):
ext_file = input_path_file.split(".")[-1] ext_file = input_path_file.split(".")[-1]
if ext_file not in VALID_EXTENSIONS: if ext_file not in VALID_EXTENSIONS:
return {"status":False, "message":"Расширение не поддерживаеться!"} return {"status":False, "message":"Расширение не поддерживаеться!"}
+1 -1
View File
@@ -18,7 +18,7 @@ class Logger:
self.logger_cli.setLevel(logging.INFO) self.logger_cli.setLevel(logging.INFO)
self.logger_cli.addHandler(console_handler) self.logger_cli.addHandler(console_handler)
def send(self, level_log, type_log, message): def send(self, level_log: str, type_log: str, message: str):
if type_log == "file": if type_log == "file":
getattr(self.logger_file, level_log)(message) getattr(self.logger_file, level_log)(message)
elif type_log == "cli": elif type_log == "cli":