Source code for nefelibata.publishers.neocities
import logging
from pathlib import Path
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Tuple
import requests
from nefelibata.publishers import Publisher
_logger = logging.getLogger(__name__)
blocklist = [".mkd"]
[docs]class NeocitiesPublisher(Publisher):
"""A publisher that uploads the weblog to Neocities."""
def __init__(
self,
root: Path,
config: Dict[str, Any],
username: Optional[str] = None,
password: Optional[str] = None,
api_key: Optional[str] = None,
):
super().__init__(root, config)
if bool(username and password) == (api_key is not None):
raise Exception(
"You must provide exactly ONE of username/password or API key",
)
if username and password:
response = requests.get(
f"https://{username}:{password}@neocities.org/api/key",
)
payload = response.json()
api_key = payload["api_key"]
_logger.warning(
f"Your API key is {api_key}, please remove the username/password from the configuration and add the API key",
)
self.headers = {"Authorization": f"Bearer {api_key}"}
[docs] def publish(self, force: bool = False) -> None:
# store file with the last time weblog was published
last_published_file = self.root / "last_published"
if last_published_file.exists():
last_published = last_published_file.stat().st_mtime
else:
last_published = 0
build = self.root / "build"
filenames: List[Tuple[Path, str]] = []
for path in self.find_modified_files(force, last_published):
if path.suffix not in blocklist:
key = str(path.relative_to(build))
filenames.append((path, key))
# NeoCities API expects a dict in the following format:
# { name_on_server: <file_object> }
args = {pair[1]: open(pair[0], "rb") for pair in filenames}
if not args:
return
url = "https://neocities.org/api/upload"
response = requests.post(url, files=args, headers=self.headers)
try:
response.raise_for_status()
except Exception:
_logger.exception(f"Error uploading files: {response.text}")
return
# update last published
last_published_file.touch()