@@ -1,3 +1,5 @@ | |||||
*.pyc | *.pyc | ||||
__pycache__/ | __pycache__/ | ||||
config/ | |||||
data/ | |||||
venv/ | venv/ |
@@ -1,19 +1,29 @@ | |||||
#! /usr/bin/env python3 | #! /usr/bin/env python3 | ||||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
from pathlib import Path | |||||
from flask import Flask, g | from flask import Flask, g | ||||
from flask_mako import MakoTemplates, render_template | from flask_mako import MakoTemplates, render_template | ||||
from calefaction import __version__ as version | |||||
from calefaction.config import Config | |||||
from calefaction.eve import EVE | |||||
from calefaction.util import catch_errors, set_up_hash_versioning | from calefaction.util import catch_errors, set_up_hash_versioning | ||||
basepath = Path(__file__).resolve().parent | |||||
app = Flask(__name__) | app = Flask(__name__) | ||||
config = Config(basepath / "config") | |||||
eve = EVE() | |||||
MakoTemplates(app) | MakoTemplates(app) | ||||
set_up_hash_versioning(app) | set_up_hash_versioning(app) | ||||
@app.before_request | @app.before_request | ||||
def prepare_request(): | def prepare_request(): | ||||
g.something = None # ... | |||||
g.config = config | |||||
g.eve = eve | |||||
g.version = version | |||||
@app.route("/") | @app.route("/") | ||||
@catch_errors(app) | @catch_errors(app) | ||||
@@ -0,0 +1 @@ | |||||
__version__ = "0.1" |
@@ -0,0 +1,24 @@ | |||||
# -*- coding: utf-8 -*- | |||||
import yaml | |||||
__all__ = ["Config"] | |||||
class Config: | |||||
def __init__(self, confdir): | |||||
self._filename = confdir / "config.yml" | |||||
self._data = None | |||||
self._load() | |||||
def _load(self): | |||||
with self._filename.open("rb") as fp: | |||||
self._data = yaml.load(fp) | |||||
def get(self, key="", default=None): | |||||
obj = self._data | |||||
for item in key.split("."): | |||||
if item not in obj: | |||||
return default | |||||
obj = obj[item] | |||||
return obj |
@@ -0,0 +1,14 @@ | |||||
# -*- coding: utf-8 -*- | |||||
from .image import ImageServer | |||||
__all__ = ["EVE"] | |||||
class EVE: | |||||
def __init__(self): | |||||
self._image = ImageServer() | |||||
@property | |||||
def image(self): | |||||
return self._image |
@@ -0,0 +1,50 @@ | |||||
# -*- coding: utf-8 -*- | |||||
__all__ = ["ImageServer"] | |||||
class ImageServer: | |||||
def __init__(self): | |||||
self._url = "https://imageserver.eveonline.com/" | |||||
@property | |||||
def alliance_widths(self): | |||||
return [32, 64, 128] | |||||
@property | |||||
def corp_widths(self): | |||||
return [32, 64, 128, 256] | |||||
@property | |||||
def character_widths(self): | |||||
return [32, 64, 128, 256, 512, 1024] | |||||
@property | |||||
def faction_widths(self): | |||||
return [32, 64, 128] | |||||
@property | |||||
def inventory_widths(self): | |||||
return [32, 64] | |||||
@property | |||||
def render_widths(self): | |||||
return [32, 64, 128, 256, 512] | |||||
def alliance(self, id, width): | |||||
return self._url + "Alliance/{}_{}.png".format(id, width) | |||||
def corp(self, id, width): | |||||
return self._url + "Corporation/{}_{}.png".format(id, width) | |||||
def character(self, id, width): | |||||
return self._url + "Character/{}_{}.jpg".format(id, width) | |||||
def faction(self, id, width): | |||||
return self._url + "Alliance/{}_{}.jpg".format(id, width) | |||||
def inventory(self, id, width): | |||||
return self._url + "Type/{}_{}.jpg".format(id, width) | |||||
def render(self, id, width): | |||||
return self._url + "Render/{}_{}.jpg".format(id, width) |
@@ -30,7 +30,10 @@ def set_up_hash_versioning(app): | |||||
if endpoint == "staticv": | if endpoint == "staticv": | ||||
filename = values["filename"] | filename = values["filename"] | ||||
fpath = path.join(app.static_folder, filename) | fpath = path.join(app.static_folder, filename) | ||||
mtime = path.getmtime(fpath) | |||||
try: | |||||
mtime = path.getmtime(fpath) | |||||
except OSError: | |||||
return url_for("static", filename=filename) | |||||
cache = app._hash_cache.get(fpath) | cache = app._hash_cache.get(fpath) | ||||
if cache and cache[0] == mtime: | if cache and cache[0] == mtime: | ||||
hashstr = cache[1] | hashstr = cache[1] | ||||
@@ -1,3 +1,4 @@ | |||||
Flask==0.11.1 | Flask==0.11.1 | ||||
Flask-Mako==0.4 | Flask-Mako==0.4 | ||||
PyYAML==3.12 | |||||
requests==2.12.4 | requests==2.12.4 |
@@ -1,14 +1,29 @@ | |||||
/* FONT... */ | |||||
/* MOBILE... */ | /* MOBILE... */ | ||||
@import url(//fonts.googleapis.com/css?family=Open+Sans:400,400italic,700); | |||||
body { | body { | ||||
display: flex; | display: flex; | ||||
min-height: 100vh; | min-height: 100vh; | ||||
flex-direction: column; | flex-direction: column; | ||||
margin: 0; | margin: 0; | ||||
font-family: sans-serif; | |||||
background-color: #173350; | |||||
color: #E6EAEF; | |||||
font-family: "Open Sans", sans-serif; | |||||
line-height: 1.3; | |||||
color: #EAEAEA; | |||||
background-color: black; | |||||
background-size: cover; | |||||
background-position: center; | |||||
background-attachment: fixed; | |||||
} | |||||
a { | |||||
color: #78CEFF; | |||||
text-decoration: none; | |||||
} | |||||
a:hover { | |||||
color: #68BEDD; | |||||
text-decoration: underline; | |||||
} | } | ||||
#container { | #container { | ||||
@@ -21,27 +36,46 @@ body { | |||||
} | } | ||||
main, header, footer { | main, header, footer { | ||||
background-color: rgba(0, 0, 0, 0.85); | |||||
background-color: rgba(0, 0, 0, 0.8); | |||||
border-color: #4A4A4A; | |||||
} | |||||
main { | |||||
margin: 2em auto; | |||||
padding: 0 1em; | |||||
border-width: 1px; | |||||
border-style: solid; | |||||
} | |||||
header { | |||||
font-size: 120%; | |||||
border-bottom-width: 1px; | |||||
border-bottom-style: solid; | |||||
} | |||||
footer { | |||||
font-size: 85%; | |||||
border-top-width: 1px; | |||||
border-top-style: solid; | |||||
} | } | ||||
main, header > div, footer > div { | main, header > div, footer > div { | ||||
max-width: 1000px; | max-width: 1000px; | ||||
width: 80%; | width: 80%; | ||||
padding: 1em; | |||||
} | } | ||||
main { | |||||
margin: 2em auto; | |||||
border: 1px solid #364A5F; | |||||
header > div { | |||||
margin: 0 auto; | |||||
padding: 0.5em; | |||||
} | } | ||||
header > div, footer > div { | |||||
footer > div { | |||||
margin: 0 auto; | margin: 0 auto; | ||||
padding: 1em; | |||||
} | } | ||||
header > div > div { | header > div > div { | ||||
display: inline-block; | display: inline-block; | ||||
vertical-align: middle; | |||||
} | } | ||||
header > div > .left { | header > div > .left { | ||||
@@ -54,24 +88,25 @@ header > div > .right { | |||||
width: 30%; | width: 30%; | ||||
} | } | ||||
header { | |||||
font-size: 120%; | |||||
border-bottom: 1px solid #364A5F; | |||||
header a { | |||||
color: #EAEAEA; | |||||
} | } | ||||
footer { | |||||
font-size: 85%; | |||||
border-top: 1px solid #364A5F; | |||||
header a:hover { | |||||
color: #CACACA; | |||||
} | } | ||||
a { | |||||
color: #78CEFF; | |||||
text-decoration: none; | |||||
header .aligned { | |||||
vertical-align: middle; | |||||
} | } | ||||
a:hover { | |||||
color: #68BEDD; | |||||
text-decoration: underline; | |||||
#corp-masthead { | |||||
height: 30px; | |||||
margin-right: 0.5em; | |||||
} | |||||
#login-button { | |||||
height: 30px; | |||||
} | } | ||||
#error pre { | #error pre { |
@@ -0,0 +1,7 @@ | |||||
body { | |||||
background-image: url("/static/images/amarr.jpg"); | |||||
} | |||||
main, header, footer { | |||||
border-color: #5F4A26; | |||||
} |
@@ -0,0 +1,7 @@ | |||||
body { | |||||
background-image: url("/static/images/caldari.jpg"); | |||||
} | |||||
main, header, footer { | |||||
border-color: #364A5F; | |||||
} |
@@ -0,0 +1,7 @@ | |||||
body { | |||||
background-image: url("/static/images/gallente.jpg"); | |||||
} | |||||
main, header, footer { | |||||
border-color: #365F4A; | |||||
} |
@@ -0,0 +1,7 @@ | |||||
body { | |||||
background-image: url("/static/images/minmatar.jpg"); | |||||
} | |||||
main, header, footer { | |||||
border-color: #5F3C42; | |||||
} |
@@ -6,21 +6,22 @@ | |||||
<head> | <head> | ||||
<meta charset="utf-8"> | <meta charset="utf-8"> | ||||
<title> | <title> | ||||
<%block name="title">CORP_NAME...</%block> | |||||
<%block name="title">${g.config.get("corp.name")}</%block> | |||||
</title> | </title> | ||||
<link rel="stylesheet" href="${url_for('staticv', filename='style.css')}" type="text/css" /> | |||||
<!-- FAVICONS... --> | |||||
<link rel="stylesheet" type="text/css" href="${url_for('staticv', filename='main.css')}" /> | |||||
<link rel="stylesheet" type="text/css" href="${url_for('staticv', filename='styles/minmatar.css')}" /> | |||||
% for size in g.eve.image.corp_widths: | |||||
<link rel="icon" type="image/png" sizes="${size}x${size}" href="${g.eve.image.corp(g.config.get('corp.id'), size)}" /> | |||||
% endfor | |||||
</head> | </head> | ||||
<body> | <body> | ||||
${next.body()} | ${next.body()} | ||||
<footer> | <footer> | ||||
<div> | <div> | ||||
<% | |||||
copyright_year = datetime.now().year | |||||
%> | |||||
Copyright © ${copyright_year} COPYRIGHT_HOLDER... | |||||
<% copyright_year = datetime.now().year %> | |||||
Copyright © ${copyright_year} ${g.config.get("corp.copyright")} | |||||
• | • | ||||
Running <a href="https://github.com/earwig/calefaction">Calefaction</a> CALEFACTION_VERSION... | |||||
Running <a href="https://github.com/earwig/calefaction">Calefaction</a> ${g.version} | |||||
• | • | ||||
<a href="https://eveonline.com">EVE Online</a> and all related trademarks are property of <a href="https://ccpgames.com">CCP hf</a>. | <a href="https://eveonline.com">EVE Online</a> and all related trademarks are property of <a href="https://ccpgames.com">CCP hf</a>. | ||||
</div> | </div> | ||||
@@ -1,9 +1,14 @@ | |||||
<%inherit file="_layout.mako"/> | <%inherit file="_layout.mako"/> | ||||
<%block name="lefthead"> | <%block name="lefthead"> | ||||
[CORP_LOGO] CORP_NAME... | |||||
<nav>Campaign: XYZ | Map | Intel | Members</nav> | |||||
<a href="/"> | |||||
<img id="corp-masthead" class="aligned" src="${g.eve.image.corp(g.config.get('corp.id'), 256)}"/> | |||||
</a> | |||||
<a href="/" class="aligned">${g.config.get("corp.name")}</a> | |||||
<nav> | |||||
Campaign: XYZ | Map | Intel | Members... | |||||
</nav> | |||||
</%block> | </%block> | ||||
<%block name="righthead-"> | |||||
PLAYER_NAME [logout] | |||||
<%block name="righthead"> | |||||
PLAYER_NAME... [logout] | |||||
</%block> | </%block> | ||||
${next.body()} | ${next.body()} |
@@ -1,6 +1,6 @@ | |||||
<%inherit file="_base.mako"/> | <%inherit file="_base.mako"/> | ||||
<%block name="title"> | <%block name="title"> | ||||
Error – ...name... | |||||
Error – ${g.config.get("corp.name")} | |||||
</%block> | </%block> | ||||
<div id="container"> | <div id="container"> | ||||
<div> | <div> | ||||
@@ -1,8 +1,11 @@ | |||||
<%inherit file="_layout.mako"/> | <%inherit file="_layout.mako"/> | ||||
<%block name="lefthead"> | <%block name="lefthead"> | ||||
[C_LOGO] C_NAME... | |||||
<a href="/"> | |||||
<img id="corp-masthead" class="aligned" src="${g.eve.image.corp(g.config.get('corp.id'), 256)}"/> | |||||
</a> | |||||
<a href="/" class="aligned">${g.config.get("corp.name")}</a> | |||||
</%block> | </%block> | ||||
<%block name="righthead"> | <%block name="righthead"> | ||||
<img id="login-button" src="${url_for('staticv', filename='images/eve-login.png')}"/> | |||||
<img id="login-button" class="aligned" src="${url_for('staticv', filename='images/eve-login.png')}"/> | |||||
</%block> | </%block> | ||||
<p>Hello, world!</p> | <p>Hello, world!</p> |