initial commit
This commit is contained in:
commit
cf7819fb1e
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
.DS_Store
|
||||
*~
|
||||
*.swp
|
||||
.Python
|
||||
rendered/
|
||||
bin/
|
||||
include/
|
||||
lib/
|
||||
static/
|
||||
board.json
|
18
README.md
Normal file
18
README.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Proboards Website Generator
|
||||
|
||||
A quick way to visualise the data obtained by my
|
||||
[proboards-saver](https://code.vanwa.ch/shu/Proboards-Saver) tool.
|
||||
|
||||
Python3 with Jinja2 is needed.
|
||||
|
||||
## Usage
|
||||
|
||||
```generator.py [-h] [--data DATA] [--static STATIC] [--out OUT]
|
||||
|
||||
build a static website out of a proboard json dump
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--data DATA board data (json file)
|
||||
--static STATIC path to the static files (images, attachments)
|
||||
--out OUT path where the website gets rendered to```
|
114
generator.py
Executable file
114
generator.py
Executable file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import argparse, json, os, re, shutil
|
||||
|
||||
from datetime import datetime
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
def fromunixtime(value):
|
||||
return datetime.fromtimestamp(value).strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
def user_replacer(match):
|
||||
return '[url=../../user/' + match.group(2).replace('/', '_').replace(' ', '_').replace('?', '') + '.html]' + match.group(2) + '[/url]'
|
||||
|
||||
def tohtml(value):
|
||||
value = value.replace('{{baseurl}}', 'static')
|
||||
value = value.replace('\n', '<br />')
|
||||
value = re.sub(r'\[url=\/user\/(.*?)\](.*?)\[\/url\]', user_replacer, value)
|
||||
value = re.sub(r'\[url=(.*?)\](.*?)\[/url\]', r'<a href="\1">\2</a>', value)
|
||||
value = re.sub(r'\[video\](.*?)\[/video\]', r'<a href="\1">\1</a>', value)
|
||||
value = re.sub(r'\[color=(.*?)\](.*?)\[/color\]', r'<font color="\1">\2</font>', value)
|
||||
value = re.sub(r'\[b\](.*?)\[/b\]', r'<b>\1</b>', value)
|
||||
value = re.sub(r'\[i\](.*?)\[/i\]', r'<i>\1</i>', value)
|
||||
value = re.sub(r'\[u\](.*?)\[/u\]', r'<u>\1</u>', value)
|
||||
value = re.sub(r'\[img\](.*?)\[/img\]', r'<img src="\1">', value)
|
||||
|
||||
for i in range(25): # ugly hack but works good enough
|
||||
value = re.sub(r'\[quote=(.+?)\](.+)\[/quote\]', r'<fieldset><legend>\1</legend>\2</fieldset>', value, count=1)
|
||||
|
||||
for i in range(25): # same here, shut up
|
||||
value = re.sub(r'\[quote\](.*?)\[/quote\]', r'<fieldset>\1</fieldset>', value)
|
||||
|
||||
return value
|
||||
|
||||
def write_render(rendered, name, outpath):
|
||||
if not os.path.exists(os.path.join(outpath, 'board', 'thread')):
|
||||
os.makedirs(os.path.join(outpath, 'board', 'thread'))
|
||||
|
||||
if not os.path.exists(os.path.join(outpath, 'user')):
|
||||
os.makedirs(os.path.join(outpath, 'user'))
|
||||
|
||||
with open(os.path.join(outpath, name), 'w') as f:
|
||||
f.write(rendered)
|
||||
|
||||
def find_unregistered_users(data):
|
||||
unregistered_users = []
|
||||
for board in data['boards']:
|
||||
for thread in board['threads']:
|
||||
for post in thread['posts']:
|
||||
if post['user']['name'] not in unregistered_users:
|
||||
found = False
|
||||
for user in data['users']:
|
||||
if post['user']['name'] == user['name']:
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
unregistered_users.append(post['user']['name'])
|
||||
|
||||
return unregistered_users
|
||||
|
||||
def render_boards(boards, template_board, template_thread, outpath):
|
||||
for board in boards:
|
||||
rendered_board = template_board.render(board=board)
|
||||
write_render(rendered_board, os.path.join('board', board['title'].replace('/', '_').replace(' ', '_').replace('?', '') + '.html'), outpath)
|
||||
|
||||
for thread in board['threads']:
|
||||
rendered_thread = template_thread.render(thread=thread)
|
||||
write_render(rendered_thread, os.path.join('board', 'thread', thread['title'].replace('/', '_').replace(' ', '_').replace('?', '') + '.html'), outpath)
|
||||
|
||||
render_boards(board['boards'], template_board, template_thread, outpath)
|
||||
|
||||
def render(inputfile, staticpath, outpath):
|
||||
with open(inputfile) as data_file:
|
||||
data = json.load(data_file)
|
||||
|
||||
unregistered_users = find_unregistered_users(data)
|
||||
for unregistered_user in unregistered_users:
|
||||
data['users'].append({ 'name': unregistered_user, 'registered': None })
|
||||
|
||||
env = Environment(loader=FileSystemLoader('./templates'))
|
||||
env.filters['fromunixtime'] = fromunixtime
|
||||
env.filters['tohtml'] = tohtml
|
||||
|
||||
template_users = env.get_template('users.html.j2')
|
||||
template_user = env.get_template('user.html.j2')
|
||||
template_boards = env.get_template('boards.html.j2')
|
||||
template_board = env.get_template('board.html.j2')
|
||||
template_thread = env.get_template('thread.html.j2')
|
||||
|
||||
rendered_users = template_users.render(users=data['users'])
|
||||
rendered_boards = template_boards.render(boards=data['boards'])
|
||||
|
||||
write_render(rendered_users, 'users.html', outpath)
|
||||
write_render(rendered_boards, 'boards.html', outpath)
|
||||
|
||||
shutil.rmtree(os.path.join(outpath, 'board', 'thread', 'static'), ignore_errors=True)
|
||||
shutil.copytree(staticpath, os.path.join(outpath, 'board', 'thread', 'static'))
|
||||
|
||||
for user in data['users']:
|
||||
rendered_user = template_user.render(user=user)
|
||||
write_render(rendered_user, os.path.join('user', user['name'].replace('/', '_').replace(' ', '_').replace('?', '') + '.html'), outpath)
|
||||
|
||||
render_boards(data['boards'], template_board, template_thread, outpath)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='build a static website out of a proboard json dump')
|
||||
parser.add_argument('--data', default='board.json', help='board data (json file)')
|
||||
parser.add_argument('--static', default='static', help='path to the static files (images, attachments)')
|
||||
parser.add_argument('--out', default='rendered', help='path where the website gets rendered to')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
render(args.data, args.static, args.out)
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Jinja2==2.7.3
|
||||
MarkupSafe==0.23
|
23
templates/board.html.j2
Normal file
23
templates/board.html.j2
Normal file
@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link href="styles.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
{% if board.boards |length > 0 %}
|
||||
<ul>
|
||||
{% for board in board.boards %}
|
||||
<li><a href={{ "../board/" + board.title.replace('/', '_').replace(' ', '_').replace('?', '') + ".html" }}>{{ board.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<hr>
|
||||
{% endif %}
|
||||
<ul>
|
||||
{% for thread in board.threads %}
|
||||
<li><a href={{ "thread/" + thread.title.replace('/', '_').replace(' ', '_').replace('?', '') + ".html" }}>{{ thread.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
22
templates/boards.html.j2
Normal file
22
templates/boards.html.j2
Normal file
@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link href="styles.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li><a href="users.html">Users</a></li>
|
||||
</ul>
|
||||
<hr>
|
||||
<ul>
|
||||
{% for board in boards %}
|
||||
<li>
|
||||
<b><a href={{ "board/" + board.title.replace('/', '_').replace(' ', '_').replace('?', '') + ".html" }}>{{ board.title }}</a></b>
|
||||
<i>{{ board.description }}</i>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
20
templates/thread.html.j2
Normal file
20
templates/thread.html.j2
Normal file
@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link href="styles.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{ thread.title }}</h1>
|
||||
{% for post in thread.posts %}
|
||||
<h3><a href={{ "../../user/" + post.user.name.replace('/', '_').replace(' ', '_').replace('?', '') + ".html" }}>{{ post.user.name }}</a> - {{ post.timestamp | fromunixtime }}</h3>
|
||||
<p>{{ post.message | tohtml }}</p>
|
||||
{% for attachment in post.attachments %}
|
||||
--<br>
|
||||
<a href="{{ attachment.url.replace('{{baseurl}}', 'static') }}">{{ attachment.name }}</a>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
23
templates/user.html.j2
Normal file
23
templates/user.html.j2
Normal file
@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link href="styles.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{ user.name }}</h1>
|
||||
<h3>{{ user.status }}</h3>
|
||||
<p>
|
||||
{% if user.registered %}
|
||||
registered {{ user.registered | fromunixtime }}
|
||||
{% else %}
|
||||
unregistered
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if user.signature %}
|
||||
<hr>
|
||||
<i>{{ user.signature | tohtml }}</i>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
19
templates/users.html.j2
Normal file
19
templates/users.html.j2
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link href="styles.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li><a href="boards.html">Boards</a></li>
|
||||
</ul>
|
||||
<hr>
|
||||
<ul>
|
||||
{% for user in users %}
|
||||
<li><a href={{ "user/" + user.name.replace('/', '_').replace(' ', '_').replace('?', '') + ".html" }}>{{ user.name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user