Initital version

Typical workflow:

1. python backup.py <blog-name>
2. (cd src && nikola build)
3. Profit
This commit is contained in:
Anders Englöf Ytterström 2025-01-30 19:31:40 +01:00
commit 337a55d00d
10 changed files with 1578 additions and 0 deletions

4
.env-example Normal file
View file

@ -0,0 +1,4 @@
export TBS_CONSUMER_KEY=
export TBS_CONSUMER_SECRET=
export TBS_OAUTH_TOKEN=
export TBS_OAUTH_SECRET=

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
.env
venv
src/posts
src/images
site
__pycache__
src/cache
src/.doit.db

94
backup.py Normal file
View file

@ -0,0 +1,94 @@
import pytumblr
import sys
import os
from time import sleep
from jinja2 import Environment, PackageLoader, select_autoescape
import re
from urllib.parse import urlparse
from pathlib import Path
import requests
jenv = Environment(
loader=PackageLoader("src.prerenders"),
autoescape=select_autoescape()
)
def progress_bar(iteration, total, prefix='', suffix='', length=30, fill=''):
percent = ("{0:.1f}").format(100 * (iteration / float(total)))
filled_length = int(length * iteration // total)
bar = fill * filled_length + '-' * (length - filled_length)
sys.stdout.write(f'\r{prefix} |{bar}| {percent}% {suffix}')
sys.stdout.flush()
tokens = []
for envkey in ["TBS_CONSUMER_KEY", "TBS_CONSUMER_SECRET", "TBS_OAUTH_TOKEN", "TBS_OAUTH_SECRET"]:
ek = os.environ.get(envkey)
if not ek:
print(f"missing {envkey} variable, exiting")
exit(1)
tokens.append(ek)
# https://github.com/tumblr/pytumblr?tab=readme-ov-file
client = pytumblr.TumblrRestClient(
*tokens
)
def queue_media_download(data):
A = "./src/images"
R = r"<img src=\"(.+?)\""
for subject in ["body", "answer", "question"]:
if subject in data:
for url in re.findall(R, data[subject]):
u = urlparse(url)
filename = os.path.basename(u.path)
dirname = os.path.dirname(u.path)
target = f"{A}{dirname}/{filename}"
if Path(target).exists():
continue
Path(f"{A}{dirname}").mkdir(parents=True, exist_ok=True)
response = requests.get(url)
with open(target, mode="wb") as file:
file.write(response.content)
data[subject] = data[subject].replace("srcset=", "notsrcset=")
data[subject] = data[subject].replace(url, f"../images{dirname}/{filename}")
def prerender(data):
template = jenv.get_template(f"{data["type"]}.md")
filename = data["id"]
queue_media_download(data)
contents = template.render(**data)
target = f"./src/posts/{filename}.md"
if not Path(target).exists():
with open(target, "w") as f:
f.write(contents)
try:
blog = sys.argv[1]
except IndexError:
print("missing blogname argument, exiting")
exit(2)
L = 50
params = {"limit": L, "offset": 0}
info = client.blog_info(blog)
total = info["blog"]["total_posts"]
P = total // L + 1
for i in range(P):
params["offset"] = i * L
posts = client.posts(blog, **params)
for post in posts["posts"]:
match post["type"]:
case "answer":
prerender(post)
case "text":
prerender(post)
case "photo":
prerender(post)
case other:
print("->", post["type"], post.keys())
progress_bar(i, P, prefix='Downloading:', suffix='', length=30)
if len(posts["posts"]) < L:
break
sleep(0.5)

4
requirements.txt Normal file
View file

@ -0,0 +1,4 @@
Jinja2==3.1.5
Nikola==8.3.1
PyTumblr==0.1.2
requests==2.32.3

17
src/README.txt Normal file
View file

@ -0,0 +1,17 @@
This folder contains the source used to generate a static site using Nikola.
Installation and documentation at https://getnikola.com/
Configuration file for the site is ``conf.py``.
To build the site::
nikola build
To see it::
nikola serve -b
To check all available commands::
nikola help

1414
src/conf.py Normal file

File diff suppressed because it is too large Load diff

BIN
src/files/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

View file

@ -0,0 +1,12 @@
.. title: {{summary.splitlines()[0]}}
.. slug: {{id}}
.. date: {{date}}
.. tags: {{",".join(tags).lower().replace("ø", "o").replace("ö", "o").replace("å", "a")}}
.. author: the-old-mayhem
.. link: https://the-old-mayhem.tumblr.com/
.. description:
.. category: answer
> {{question}}
{{answer}}

View file

@ -0,0 +1,14 @@
.. title: {{summary.splitlines()[0]}}
.. slug: {{id}}
.. date: {{date}}
.. tags: {{",".join(tags).lower().replace("ø", "o").replace("ö", "o").replace("å", "a")}}
.. author: the-old-mayhem
.. link: https://the-old-mayhem.tumblr.com/
.. description:
.. category: photo
{% for photo in photos %}
<img src="{{photo.original_size.url}}">
{{photo.caption}}
{% endfor %}
{{caption}}

View file

@ -0,0 +1,11 @@
.. title: {{summary.splitlines()[0]}}
.. slug: {{id}}
.. date: {{date}}
.. tags: {{",".join(tags).lower().replace("ø", "o").replace("ö", "o").replace("å", "a")}}
.. author: the-old-mayhem
.. link: https://the-old-mayhem.tumblr.com/
.. description:
.. category: text
{{body}}