mirror of
https://git.ari.lt/ari.lt/blog.ari.lt.git
synced 2025-02-04 09:39:25 +01:00
update @ Sun Dec 15 03:35:24 EET 2024
Signed-off-by: Ari Archer <ari@ari.lt>
This commit is contained in:
parent
c85b02469c
commit
fb78c01bfe
3 changed files with 103 additions and 22 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,6 +9,7 @@ venv/
|
||||||
/blog_json_hash.txt
|
/blog_json_hash.txt
|
||||||
/manifest.json
|
/manifest.json
|
||||||
/recents_json_hash.txt
|
/recents_json_hash.txt
|
||||||
|
/media/media_json_hash.txt
|
||||||
/recents.json
|
/recents.json
|
||||||
/rss.xml
|
/rss.xml
|
||||||
/sitemap.xml
|
/sitemap.xml
|
||||||
|
|
1
media/media.json
Normal file
1
media/media.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
123
scripts/blog.py
123
scripts/blog.py
|
@ -551,6 +551,20 @@ def select_posts(posts: dict[str, dict[str, typing.Any]]) -> tuple[str, ...]:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def select_medias() -> tuple[str, ...]:
|
||||||
|
return tuple(
|
||||||
|
map(
|
||||||
|
lambda opt: opt.split("|", maxsplit=1)[0].strip(),
|
||||||
|
select_multi(
|
||||||
|
tuple(
|
||||||
|
f"{mdx} | {mdy['type']}, {mdy['alt']} for {mdy['purpose']} | {mdy['title']}, {mdy['credit']}"
|
||||||
|
for mdx, mdy in MEDIA_INDEX.items()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if NCI:
|
if NCI:
|
||||||
try:
|
try:
|
||||||
import readline
|
import readline
|
||||||
|
@ -765,7 +779,7 @@ def parse_inline_media_embed(
|
||||||
{"type": "linebreak"},
|
{"type": "linebreak"},
|
||||||
{
|
{
|
||||||
"type": "emphasis",
|
"type": "emphasis",
|
||||||
"raw": f"{mdx['alt']} | \"{mdx['title']}\" by {mdx['credit']} ({mdx['license']}). Purpose: {html_escape(mdx['purpose'])}. Uploaded on {datetime.datetime.utcfromtimestamp(mdx['created']).strftime('%a, %d %b %Y %H:%M:%S GMT')}. ",
|
"raw": f"{mdx['alt']} | \"{mdx['title']}\" by {mdx['credit']} ({mdx['license']}). Purpose: {html_escape(mdx['purpose'])}. Uploaded on {datetime.datetime.utcfromtimestamp(mdx['uploaded']).strftime('%a, %d %b %Y %H:%M:%S GMT')}. ",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "link",
|
"type": "link",
|
||||||
|
@ -952,7 +966,7 @@ def new(config: dict[str, typing.Any]) -> int:
|
||||||
"description": description.strip(),
|
"description": description.strip(),
|
||||||
"content": content,
|
"content": content,
|
||||||
"keywords": keywords,
|
"keywords": keywords,
|
||||||
"created": datetime.datetime.utcnow().timestamp(),
|
"uploaded": datetime.datetime.utcnow().timestamp(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK
|
return OK
|
||||||
|
@ -1486,7 +1500,10 @@ def apis(config: dict[str, typing.Any]) -> int:
|
||||||
)
|
)
|
||||||
lnew(f"generated {recents.name!r}")
|
lnew(f"generated {recents.name!r}")
|
||||||
|
|
||||||
for api in recents.name, CONFIG_FILE:
|
for api in recents.name, CONFIG_FILE, "media/media.json":
|
||||||
|
if not os.path.isfile(api):
|
||||||
|
continue
|
||||||
|
|
||||||
with open(api, "rb") as content:
|
with open(api, "rb") as content:
|
||||||
h: str = hashlib.sha256(content.read()).hexdigest()
|
h: str = hashlib.sha256(content.read()).hexdigest()
|
||||||
|
|
||||||
|
@ -1509,11 +1526,12 @@ def clean(config: dict[str, typing.Any]) -> int:
|
||||||
except IsADirectoryError:
|
except IsADirectoryError:
|
||||||
shutil.rmtree(file)
|
shutil.rmtree(file)
|
||||||
|
|
||||||
for pattern in (
|
for pattern in {
|
||||||
config["posts-dir"],
|
config["posts-dir"],
|
||||||
"index.html",
|
"index.html",
|
||||||
f"{config['assets-dir']}/*.min.*",
|
f"{config['assets-dir']}/*.min.*",
|
||||||
"blog_json_hash.txt",
|
"blog_json_hash.txt",
|
||||||
|
"media/media_json_hash.txt",
|
||||||
"manifest.json",
|
"manifest.json",
|
||||||
f"{config['assets-dir']}/fonts/*.min.*",
|
f"{config['assets-dir']}/fonts/*.min.*",
|
||||||
"recents_json_hash.txt",
|
"recents_json_hash.txt",
|
||||||
|
@ -1522,7 +1540,7 @@ def clean(config: dict[str, typing.Any]) -> int:
|
||||||
"robots.txt",
|
"robots.txt",
|
||||||
"sitemap.xml",
|
"sitemap.xml",
|
||||||
"stats",
|
"stats",
|
||||||
):
|
}:
|
||||||
if os.path.exists(pattern):
|
if os.path.exists(pattern):
|
||||||
remove(pattern)
|
remove(pattern)
|
||||||
else:
|
else:
|
||||||
|
@ -1623,6 +1641,8 @@ def blog(config: dict[str, typing.Any]) -> int:
|
||||||
def media(config: dict[str, typing.Any]) -> int:
|
def media(config: dict[str, typing.Any]) -> int:
|
||||||
"""add media"""
|
"""add media"""
|
||||||
|
|
||||||
|
assert config is config, "Unused"
|
||||||
|
|
||||||
path: str = iinput("media path")
|
path: str = iinput("media path")
|
||||||
path = os.path.expanduser(path)
|
path = os.path.expanduser(path)
|
||||||
|
|
||||||
|
@ -1655,15 +1675,9 @@ def media(config: dict[str, typing.Any]) -> int:
|
||||||
|
|
||||||
os.makedirs("media", exist_ok=True)
|
os.makedirs("media", exist_ok=True)
|
||||||
|
|
||||||
if os.path.exists("media/media.json"):
|
|
||||||
with open("media/media.json", "r") as fp:
|
|
||||||
index: dict[str, dict[str, typing.Any]] = json.load(fp)
|
|
||||||
else:
|
|
||||||
index = {}
|
|
||||||
|
|
||||||
# Check if it exists
|
# Check if it exists
|
||||||
|
|
||||||
if hash_hex in index:
|
if hash_hex in MEDIA_INDEX:
|
||||||
return err(f"media pointing to {path!r} already exists")
|
return err(f"media pointing to {path!r} already exists")
|
||||||
|
|
||||||
# Process stuff
|
# Process stuff
|
||||||
|
@ -1693,7 +1707,7 @@ def media(config: dict[str, typing.Any]) -> int:
|
||||||
optimize=True,
|
optimize=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
index[hash_hex] = {
|
MEDIA_INDEX[hash_hex] = {
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"width": width,
|
"width": width,
|
||||||
"height": height,
|
"height": height,
|
||||||
|
@ -1702,14 +1716,14 @@ def media(config: dict[str, typing.Any]) -> int:
|
||||||
elif mime.startswith("audio/"):
|
elif mime.startswith("audio/"):
|
||||||
shutil.copy(path, fpath)
|
shutil.copy(path, fpath)
|
||||||
|
|
||||||
index[hash_hex] = {
|
MEDIA_INDEX[hash_hex] = {
|
||||||
"type": "audio",
|
"type": "audio",
|
||||||
"alt": iinput("alt text"),
|
"alt": iinput("alt text"),
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
return err(f"unsupported MIME: {mime!r}")
|
return err(f"unsupported MIME: {mime!r}")
|
||||||
|
|
||||||
index[hash_hex].update(
|
MEDIA_INDEX[hash_hex].update(
|
||||||
{
|
{
|
||||||
"purpose": purpose,
|
"purpose": purpose,
|
||||||
"title": title,
|
"title": title,
|
||||||
|
@ -1723,16 +1737,70 @@ def media(config: dict[str, typing.Any]) -> int:
|
||||||
|
|
||||||
lnew(f"media {hash_hex} created")
|
lnew(f"media {hash_hex} created")
|
||||||
|
|
||||||
# Update media.json
|
return OK
|
||||||
|
|
||||||
with open("media/media.json", "w") as fp:
|
|
||||||
json.dump(index, fp, indent=config["indent"])
|
|
||||||
|
|
||||||
with open("media/media_json_hash.txt", "w") as fp:
|
@cmds.new
|
||||||
with open("media/media.json", "rb") as fk:
|
def lsmedia(config: dict[str, typing.Any]) -> int:
|
||||||
fp.write(hashlib.sha256(fk.read()).hexdigest())
|
"""list media"""
|
||||||
|
|
||||||
lnew("Updated media.json and media_json_hash.txt")
|
assert config is config, "Unused"
|
||||||
|
|
||||||
|
for mdx, mdy in MEDIA_INDEX.items():
|
||||||
|
print(mdx)
|
||||||
|
|
||||||
|
for k, v in mdy.items():
|
||||||
|
print(" ", k, "=", v)
|
||||||
|
|
||||||
|
return OK
|
||||||
|
|
||||||
|
|
||||||
|
@cmds.new
|
||||||
|
def rmmedia(config: dict[str, typing.Any]) -> int:
|
||||||
|
"""remove media"""
|
||||||
|
|
||||||
|
assert config is config, "Unusued"
|
||||||
|
|
||||||
|
for mdx in select_medias():
|
||||||
|
imp(f"Removing media {mdx}")
|
||||||
|
os.remove(f"media/{mdx}.{MEDIA_INDEX[mdx]['ext']}")
|
||||||
|
del MEDIA_INDEX[mdx]
|
||||||
|
|
||||||
|
return OK
|
||||||
|
|
||||||
|
|
||||||
|
@cmds.new
|
||||||
|
def purgemedia(config: dict[str, typing.Any]) -> int:
|
||||||
|
"""purge unused or unindexed media"""
|
||||||
|
|
||||||
|
posts: typing.Any = config["posts"].values()
|
||||||
|
unused: set[str] = set()
|
||||||
|
|
||||||
|
for mdx in MEDIA_INDEX:
|
||||||
|
used: bool = False
|
||||||
|
|
||||||
|
for post in posts:
|
||||||
|
if f"<@{mdx}>" in post["content"]:
|
||||||
|
used = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not used:
|
||||||
|
unused.add(mdx)
|
||||||
|
|
||||||
|
# Cannot change dict size during iteration
|
||||||
|
for mdy in unused:
|
||||||
|
log(f"Unindexing unused media {mdy}")
|
||||||
|
del MEDIA_INDEX[mdy]
|
||||||
|
|
||||||
|
for file in os.listdir("media"):
|
||||||
|
if file == "media.json": # Ignore index file
|
||||||
|
continue
|
||||||
|
|
||||||
|
pid: str = os.path.splitext(os.path.basename(file))[0]
|
||||||
|
|
||||||
|
if pid not in MEDIA_INDEX:
|
||||||
|
imp(f"Removing unindexed media {pid}")
|
||||||
|
os.remove(f"media/{file}")
|
||||||
|
|
||||||
return OK
|
return OK
|
||||||
|
|
||||||
|
@ -1761,6 +1829,11 @@ def main() -> int:
|
||||||
MEDIA_INDEX.update(json.load(fp))
|
MEDIA_INDEX.update(json.load(fp))
|
||||||
|
|
||||||
log("Loaded the media index (media/media.json)")
|
log("Loaded the media index (media/media.json)")
|
||||||
|
else:
|
||||||
|
os.makedirs("media", exist_ok=True)
|
||||||
|
|
||||||
|
with open("media/media.json", "w") as fp:
|
||||||
|
fp.write("{}")
|
||||||
|
|
||||||
sort(cfg)
|
sort(cfg)
|
||||||
|
|
||||||
|
@ -1792,6 +1865,12 @@ def main() -> int:
|
||||||
log(f"dumping config to {config.name!r}")
|
log(f"dumping config to {config.name!r}")
|
||||||
json.dump(cfg, config, indent=cfg["indent"] if NCI else None)
|
json.dump(cfg, config, indent=cfg["indent"] if NCI else None)
|
||||||
|
|
||||||
|
# Update media.json
|
||||||
|
|
||||||
|
with open("media/media.json", "w") as fp:
|
||||||
|
log("dumping media.json")
|
||||||
|
json.dump(MEDIA_INDEX, fp, indent=cfg["indent"])
|
||||||
|
|
||||||
log(f"goodbye world, return {code}, total {ctimer() - main_t} s")
|
log(f"goodbye world, return {code}, total {ctimer() - main_t} s")
|
||||||
|
|
||||||
return code
|
return code
|
||||||
|
|
Loading…
Add table
Reference in a new issue