Compare commits
2 Commits
d59a38721e
...
72c9855cbe
Author | SHA1 | Date |
---|---|---|
Ales (Shagi) Zabala Alava | 72c9855cbe | |
Ales (Shagi) Zabala Alava | 5d81b66aab |
|
@ -0,0 +1,26 @@
|
|||
|
||||
repos:
|
||||
# Using this mirror lets us use mypyc-compiled black, which is about 2x faster
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 24.2.0
|
||||
hooks:
|
||||
- id: black
|
||||
# It is recommended to specify the latest version of Python
|
||||
# supported by your project here, or alternatively use
|
||||
# pre-commit's default_language_version, see
|
||||
# https://pre-commit.com/#top_level-default_language_version
|
||||
language_version: python3.11
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort (python)
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.3.0
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
# - id: ruff-format We don't need this because we have black and isort.
|
|
@ -0,0 +1,6 @@
|
|||
# Changelog
|
||||
|
||||
## 1.1
|
||||
|
||||
* chore: pre-commit configuration
|
||||
* fix: fix jinja dependency and apply ruff formating
|
|
@ -1 +1 @@
|
|||
VERSION = "1.0"
|
||||
VERSION = "1.1"
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import os
|
||||
from shutil import copy
|
||||
import subprocess
|
||||
from shutil import copy
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
from jinja2.utils import Markup
|
||||
import srt
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
from markupsafe import Markup
|
||||
from negromate.songs.loader import load_songs
|
||||
|
||||
|
||||
|
@ -16,23 +15,23 @@ class SongPage:
|
|||
def get_context_data(self):
|
||||
parsed_srt = None
|
||||
if self.song.srt:
|
||||
with self.song.srt.open('r') as srtfile:
|
||||
with self.song.srt.open("r") as srtfile:
|
||||
try:
|
||||
srt_str = srtfile.read().encode('utf-8').decode('utf-8-sig')
|
||||
srt_str = srtfile.read().encode("utf-8").decode("utf-8-sig")
|
||||
parsed_srt = list(srt.parse(srt_str))
|
||||
except Exception as e:
|
||||
print("{}: srt parse error: {}".format(self.song.path.name, e))
|
||||
root_path = os.path.relpath(self.song.root, self.song.path)
|
||||
return {
|
||||
'song': self,
|
||||
'parsed_srt': parsed_srt,
|
||||
'root_path': root_path,
|
||||
"song": self,
|
||||
"parsed_srt": parsed_srt,
|
||||
"root_path": root_path,
|
||||
}
|
||||
|
||||
def render(self, builder, context):
|
||||
ctx = self.get_context_data()
|
||||
ctx.update(context)
|
||||
builder.render('song.html', self.song.path, ctx)
|
||||
builder.render("song.html", self.song.path, ctx)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.song, name)
|
||||
|
@ -47,10 +46,10 @@ class Builder:
|
|||
|
||||
self.env = Environment(
|
||||
loader=FileSystemLoader(template_folder),
|
||||
autoescape=select_autoescape(['html']),
|
||||
autoescape=select_autoescape(["html"]),
|
||||
)
|
||||
self.env.filters['url'] = self.url
|
||||
self.env.filters['display_boolean'] = self.display_boolean
|
||||
self.env.filters["url"] = self.url
|
||||
self.env.filters["display_boolean"] = self.display_boolean
|
||||
self.current_path = self.root_folder
|
||||
|
||||
def url(self, path):
|
||||
|
@ -58,17 +57,17 @@ class Builder:
|
|||
|
||||
def display_boolean(self, value):
|
||||
if value:
|
||||
return Markup('✓')
|
||||
return Markup("✓")
|
||||
else:
|
||||
return Markup('✗')
|
||||
return Markup("✗")
|
||||
|
||||
def render(self, template, target, context):
|
||||
html_file = target / 'index.html'
|
||||
html_file = target / "index.html"
|
||||
page_template = self.env.get_template(template)
|
||||
root_path = os.path.relpath(self.root_folder, target)
|
||||
context['root_path'] = root_path
|
||||
context["root_path"] = root_path
|
||||
|
||||
with html_file.open('w') as page:
|
||||
with html_file.open("w") as page:
|
||||
page.write(page_template.render(context))
|
||||
|
||||
def build(self):
|
||||
|
@ -77,50 +76,52 @@ class Builder:
|
|||
pending_songs = [SongPage(s) for s in pending_songs]
|
||||
|
||||
global_context = {
|
||||
'songs': songs,
|
||||
'root_folder': self.root_folder,
|
||||
"songs": songs,
|
||||
"root_folder": self.root_folder,
|
||||
}
|
||||
|
||||
for song in songs:
|
||||
self.current_path = song.path
|
||||
song.render(self, global_context)
|
||||
|
||||
self.render('index.html', self.root_folder, global_context)
|
||||
self.render("index.html", self.root_folder, global_context)
|
||||
|
||||
home = self.root_folder / 'home'
|
||||
home = self.root_folder / "home"
|
||||
self.current_path = home
|
||||
if not home.exists():
|
||||
home.mkdir()
|
||||
self.render('home.html', home, global_context)
|
||||
self.render("home.html", home, global_context)
|
||||
|
||||
playlist = self.root_folder / 'playlist'
|
||||
playlist = self.root_folder / "playlist"
|
||||
self.current_path = playlist
|
||||
if not playlist.exists():
|
||||
playlist.mkdir()
|
||||
|
||||
self.render('playlist.html', playlist, global_context)
|
||||
self.render("playlist.html", playlist, global_context)
|
||||
|
||||
todo = self.root_folder / 'todo'
|
||||
todo = self.root_folder / "todo"
|
||||
self.current_path = todo
|
||||
if not todo.exists():
|
||||
todo.mkdir()
|
||||
todo_context = {
|
||||
'pending_songs': pending_songs,
|
||||
"pending_songs": pending_songs,
|
||||
}
|
||||
todo_context.update(global_context)
|
||||
self.render('todo.html', todo, todo_context)
|
||||
self.render("todo.html", todo, todo_context)
|
||||
|
||||
static = self.root_folder / 'static'
|
||||
static = self.root_folder / "static"
|
||||
|
||||
if not static.exists():
|
||||
static.mkdir()
|
||||
|
||||
subprocess.check_call([
|
||||
'rsync',
|
||||
'-ra',
|
||||
str(self.static_folder),
|
||||
str(self.root_folder.absolute()),
|
||||
])
|
||||
subprocess.check_call(
|
||||
[
|
||||
"rsync",
|
||||
"-ra",
|
||||
str(self.static_folder),
|
||||
str(self.root_folder.absolute()),
|
||||
]
|
||||
)
|
||||
|
||||
libreto = self.root_folder / 'static/libreto/libreto.pdf'
|
||||
libreto = self.root_folder / "static/libreto/libreto.pdf"
|
||||
copy(str(self.libreto.absolute()), str(libreto.absolute()))
|
||||
|
|
|
@ -1,36 +1,45 @@
|
|||
from pathlib import Path
|
||||
|
||||
from ..builder import Builder
|
||||
|
||||
|
||||
name = 'build'
|
||||
help_text = 'Generate static website'
|
||||
name = "build"
|
||||
help_text = "Generate static website"
|
||||
initial_config = {
|
||||
'template_folder': '~/negro_mate/web/templates',
|
||||
'static_folder': '~/negro_mate/web/static',
|
||||
"template_folder": "~/negro_mate/web/templates",
|
||||
"static_folder": "~/negro_mate/web/static",
|
||||
}
|
||||
|
||||
|
||||
def options(parser, config, **kwargs):
|
||||
parser.add_argument(
|
||||
'-s', '--song_folder', type=Path,
|
||||
default=config['global']['song_folder'],
|
||||
help="Folder with the song database, defaults to {}".format(
|
||||
config['global']['song_folder']))
|
||||
"-s",
|
||||
"--song_folder",
|
||||
type=Path,
|
||||
default=config["global"]["song_folder"],
|
||||
help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-l', '--lyrics_file', type=Path,
|
||||
default=config['global']['lyrics_file'],
|
||||
help="File with the lyrics of the songs, defaults to {}".format(
|
||||
config['global']['lyrics_file']))
|
||||
"-l",
|
||||
"--lyrics_file",
|
||||
type=Path,
|
||||
default=config["global"]["lyrics_file"],
|
||||
help="File with the lyrics of the songs, defaults to {}".format(config["global"]["lyrics_file"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-t', '--template_folder', type=Path,
|
||||
default=config['build']['template_folder'],
|
||||
help="Folder with jinja2 templates, defaults to {}".format(
|
||||
config['build']['template_folder']))
|
||||
"-t",
|
||||
"--template_folder",
|
||||
type=Path,
|
||||
default=config["build"]["template_folder"],
|
||||
help="Folder with jinja2 templates, defaults to {}".format(config["build"]["template_folder"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-S', '--static_folder', type=Path,
|
||||
default=config['build']['static_folder'],
|
||||
help="Folder with static content, defaults to {}".format(
|
||||
config['build']['static_folder']))
|
||||
"-S",
|
||||
"--static_folder",
|
||||
type=Path,
|
||||
default=config["build"]["static_folder"],
|
||||
help="Folder with static content, defaults to {}".format(config["build"]["static_folder"]),
|
||||
)
|
||||
|
||||
|
||||
def run(args, **kwargs):
|
||||
|
|
|
@ -1,48 +1,52 @@
|
|||
from pathlib import Path
|
||||
import getpass
|
||||
import subprocess
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
from negromate.songs import logger
|
||||
|
||||
|
||||
name = 'ipfs'
|
||||
help_text = 'Upload the web to IPFS'
|
||||
name = "ipfs"
|
||||
help_text = "Upload the web to IPFS"
|
||||
initial_config = {
|
||||
'api': 'http://ipfs.negromate.rocks',
|
||||
'pinfile': '~/.negromate/ipfs.hash',
|
||||
'realm': 'IPFS Gitea Negromate',
|
||||
"api": "http://ipfs.negromate.rocks",
|
||||
"pinfile": "~/.negromate/ipfs.hash",
|
||||
"realm": "IPFS Gitea Negromate",
|
||||
}
|
||||
|
||||
|
||||
def options(parser, config, **kwargs):
|
||||
parser.add_argument(
|
||||
'-s', '--song_folder', type=Path,
|
||||
default=config['global']['song_folder'],
|
||||
help="Folder with the song database, defaults to {}".format(
|
||||
config['global']['song_folder']))
|
||||
"-s",
|
||||
"--song_folder",
|
||||
type=Path,
|
||||
default=config["global"]["song_folder"],
|
||||
help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-a', '--api', default=config[name]['api'],
|
||||
help="IPFS API server, defaults to {}.".format(config[name]['api']))
|
||||
"-a", "--api", default=config[name]["api"], help="IPFS API server, defaults to {}.".format(config[name]["api"])
|
||||
)
|
||||
parser.add_argument(
|
||||
'-r', '--realm', default=config[name]['realm'],
|
||||
help="IPFS API basic authentication realm, defaults to {}.".format(config[name]['realm']))
|
||||
"-r",
|
||||
"--realm",
|
||||
default=config[name]["realm"],
|
||||
help="IPFS API basic authentication realm, defaults to {}.".format(config[name]["realm"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-p', '--pinfile', default=config[name]['pinfile'], type=Path,
|
||||
help="file to store the current ipfs hash, defaults to {}".format(
|
||||
config[name]['pinfile']))
|
||||
"-p",
|
||||
"--pinfile",
|
||||
default=config[name]["pinfile"],
|
||||
type=Path,
|
||||
help="file to store the current ipfs hash, defaults to {}".format(config[name]["pinfile"]),
|
||||
)
|
||||
|
||||
|
||||
def run(args, **kwargs):
|
||||
# Setup HTTP Basic authentication
|
||||
user = input('Username: ')
|
||||
password = getpass.getpass('Password:')
|
||||
user = input("Username: ")
|
||||
password = getpass.getpass("Password:")
|
||||
auth_handler = urllib.request.HTTPBasicAuthHandler()
|
||||
auth_handler.add_password(
|
||||
realm=args.realm,
|
||||
uri=args.api,
|
||||
user=user,
|
||||
passwd=password)
|
||||
auth_handler.add_password(realm=args.realm, uri=args.api, user=user, passwd=password)
|
||||
opener = urllib.request.build_opener(auth_handler)
|
||||
urllib.request.install_opener(opener)
|
||||
|
||||
|
@ -54,37 +58,41 @@ def run(args, **kwargs):
|
|||
"--quieter",
|
||||
args.song_folder.expanduser(),
|
||||
]
|
||||
new_hash = subprocess.check_output(command).decode('utf-8').strip()
|
||||
logger.info('New hash: {}'.format(new_hash))
|
||||
new_hash = subprocess.check_output(command).decode("utf-8").strip()
|
||||
logger.info("New hash: {}".format(new_hash))
|
||||
|
||||
# pin in server
|
||||
data = urllib.parse.urlencode({
|
||||
'arg': new_hash,
|
||||
'progress': 'false',
|
||||
})
|
||||
url = '{}/api/v0/pin/add?{}'.format(args.api, data)
|
||||
data = urllib.parse.urlencode(
|
||||
{
|
||||
"arg": new_hash,
|
||||
"progress": "false",
|
||||
}
|
||||
)
|
||||
url = "{}/api/v0/pin/add?{}".format(args.api, data)
|
||||
logger.debug("server pin request: {}".format(url))
|
||||
request = urllib.request.Request(url, method='POST')
|
||||
request = urllib.request.Request(url, method="POST")
|
||||
urllib.request.urlopen(request)
|
||||
logger.info('Hash pinned on server.')
|
||||
logger.info("Hash pinned on server.")
|
||||
|
||||
# update ipns on server
|
||||
data = urllib.parse.urlencode({
|
||||
'arg': new_hash,
|
||||
'resolve': 'true',
|
||||
})
|
||||
data = urllib.parse.urlencode(
|
||||
{
|
||||
"arg": new_hash,
|
||||
"resolve": "true",
|
||||
}
|
||||
)
|
||||
url = "{}/api/v0/name/publish?{}".format(args.api, data)
|
||||
logger.debug("server ipns request: {}".format(url))
|
||||
request = urllib.request.Request(url, method='POST')
|
||||
request = urllib.request.Request(url, method="POST")
|
||||
urllib.request.urlopen(request)
|
||||
logger.info('IPNS name updated.')
|
||||
logger.info("IPNS name updated.")
|
||||
|
||||
# read previous hash and update value
|
||||
pinfile = args.pinfile.expanduser()
|
||||
if pinfile.exists():
|
||||
with pinfile.open() as f:
|
||||
previous_hash = f.read()
|
||||
logger.info('Previous hash: {}'.format(previous_hash))
|
||||
logger.info("Previous hash: {}".format(previous_hash))
|
||||
else:
|
||||
if not pinfile.parent.exists():
|
||||
pinfile.parent.mkdir()
|
||||
|
@ -93,26 +101,28 @@ def run(args, **kwargs):
|
|||
if previous_hash is not None and previous_hash != new_hash:
|
||||
# remove previous pin on local
|
||||
command = [
|
||||
'ipfs',
|
||||
'pin',
|
||||
'rm',
|
||||
"ipfs",
|
||||
"pin",
|
||||
"rm",
|
||||
previous_hash,
|
||||
]
|
||||
result = subprocess.run(command)
|
||||
if result.returncode != 0:
|
||||
logger.info('Previous {} hash not removed: {}'.format(previous_hash, result.stdout))
|
||||
logger.info("Previous {} hash not removed: {}".format(previous_hash, result.stdout))
|
||||
else:
|
||||
logger.info('Previous hash unpinned on local')
|
||||
logger.info("Previous hash unpinned on local")
|
||||
|
||||
# remove previous pin on server
|
||||
data = urllib.parse.urlencode({
|
||||
'arg': previous_hash,
|
||||
})
|
||||
data = urllib.parse.urlencode(
|
||||
{
|
||||
"arg": previous_hash,
|
||||
}
|
||||
)
|
||||
url = "{}/api/v0/pin/rm?{}".format(args.api, data)
|
||||
logger.debug("server unpin request: {}".format(url))
|
||||
request = urllib.request.Request(url, method='POST')
|
||||
request = urllib.request.Request(url, method="POST")
|
||||
urllib.request.urlopen(request)
|
||||
logger.info('Previous hash unpinned on server')
|
||||
logger.info("Previous hash unpinned on server")
|
||||
|
||||
with pinfile.open('w') as f:
|
||||
with pinfile.open("w") as f:
|
||||
f.write(new_hash)
|
||||
|
|
|
@ -1,38 +1,51 @@
|
|||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
name = 'rsync'
|
||||
help_text = 'Sincronize the static web with the server'
|
||||
|
||||
name = "rsync"
|
||||
help_text = "Sincronize the static web with the server"
|
||||
initial_config = {
|
||||
'host': 'negromate.rocks',
|
||||
'user': 'root',
|
||||
'port': '22',
|
||||
'destination': "/var/www/html",
|
||||
"host": "negromate.rocks",
|
||||
"user": "root",
|
||||
"port": "22",
|
||||
"destination": "/var/www/html",
|
||||
}
|
||||
|
||||
|
||||
def options(parser, config, **kwargs):
|
||||
parser.add_argument(
|
||||
'-s', '--song_folder', type=Path,
|
||||
default=config['global']['song_folder'],
|
||||
help="Folder with the song database, defaults to {}".format(
|
||||
config['global']['song_folder']))
|
||||
"-s",
|
||||
"--song_folder",
|
||||
type=Path,
|
||||
default=config["global"]["song_folder"],
|
||||
help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-H', '--host', default=config[name]['host'],
|
||||
help="Target server, defaults to {}.".format(config[name]['host']))
|
||||
"-H", "--host", default=config[name]["host"], help="Target server, defaults to {}.".format(config[name]["host"])
|
||||
)
|
||||
parser.add_argument(
|
||||
'-u', '--user', default=config[name]['user'],
|
||||
help="User in the server, defaults to {}.".format(config[name]['user']))
|
||||
"-u",
|
||||
"--user",
|
||||
default=config[name]["user"],
|
||||
help="User in the server, defaults to {}.".format(config[name]["user"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-p', '--port', default=config[name]['port'], type=int,
|
||||
help="Port of the ssh server, defaults to {}.".format(config[name]['port']))
|
||||
"-p",
|
||||
"--port",
|
||||
default=config[name]["port"],
|
||||
type=int,
|
||||
help="Port of the ssh server, defaults to {}.".format(config[name]["port"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-d', '--destination', default=config[name]['destination'],
|
||||
help="Folder of the server, defaults to {}".format(config[name]['destination']))
|
||||
"-d",
|
||||
"--destination",
|
||||
default=config[name]["destination"],
|
||||
help="Folder of the server, defaults to {}".format(config[name]["destination"]),
|
||||
)
|
||||
|
||||
|
||||
def run(args, **kwargs):
|
||||
contents = str(args.song_folder.expanduser()) + '/'
|
||||
contents = str(args.song_folder.expanduser()) + "/"
|
||||
destination = "{user}@{host}:{folder}".format(
|
||||
user=args.user,
|
||||
host=args.host,
|
||||
|
@ -41,7 +54,7 @@ def run(args, **kwargs):
|
|||
command = [
|
||||
"rsync",
|
||||
"-av",
|
||||
'--rsh=ssh -p {}'.format(args.port),
|
||||
"--rsh=ssh -p {}".format(args.port),
|
||||
contents,
|
||||
destination,
|
||||
]
|
||||
|
|
|
@ -1,30 +1,40 @@
|
|||
from functools import partial
|
||||
from http.server import test, SimpleHTTPRequestHandler
|
||||
from http.server import SimpleHTTPRequestHandler, test
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
name = 'run'
|
||||
help_text = 'Start web server to test the website'
|
||||
name = "run"
|
||||
help_text = "Start web server to test the website"
|
||||
initial_config = {
|
||||
'port': '8000',
|
||||
'bind': '',
|
||||
"port": "8000",
|
||||
"bind": "",
|
||||
}
|
||||
|
||||
|
||||
def options(parser, config, **kwargs):
|
||||
parser.add_argument(
|
||||
'-s', '--song_folder', type=Path,
|
||||
default=config['global']['song_folder'],
|
||||
help="Folder with the song database, defaults to {}".format(
|
||||
config['global']['song_folder']))
|
||||
"-s",
|
||||
"--song_folder",
|
||||
type=Path,
|
||||
default=config["global"]["song_folder"],
|
||||
help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-p', '--port', default=config[name]['port'], type=int,
|
||||
help='Specify alternate port, defaults to {}'.format(config[name]['port']))
|
||||
"-p",
|
||||
"--port",
|
||||
default=config[name]["port"],
|
||||
type=int,
|
||||
help="Specify alternate port, defaults to {}".format(config[name]["port"]),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--bind', '-b', default=config[name]['bind'], metavar='ADDRESS',
|
||||
help='Specify alternate bind address, defaults to {}'.format(
|
||||
config[name]['bind'] or 'all interfaces',
|
||||
))
|
||||
"--bind",
|
||||
"-b",
|
||||
default=config[name]["bind"],
|
||||
metavar="ADDRESS",
|
||||
help="Specify alternate bind address, defaults to {}".format(
|
||||
config[name]["bind"] or "all interfaces",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def run(args, **kwargs):
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.black]
|
||||
line_length = 120
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
lines_after_imports = 2
|
||||
|
||||
[tool.pylint.'MESSAGES CONTROL']
|
||||
max-line-length = 120
|
||||
disable = "invalid-name, unused-wildcard-import, wildcard-import"
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
exclude = [
|
||||
"build",
|
||||
]
|
||||
include = ["negromate/*"]
|
||||
fix = false
|
||||
force-exclude = true
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
webvtt-py
|
||||
Jinja2
|
||||
Jinja2==3.1.3
|
||||
ass==0.4.4
|
||||
negromate.songs==1.2
|
||||
negromate.songs==1.3
|
||||
|
|
Loading…
Reference in New Issue