Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add: initial version of a web-frontend for the Master Server API (#3)
It is a nearly one-to-one copy of the current website serving the Public Server Listing, with a few extra additions. For example: - You can now filter on versions - Version sorting is done correctly for official releases (no more bumping the "latest" every release) - Information is cached properly - Some more information for servers - Server-links are no longer the MySQL-id but a hash of IP+port
- Loading branch information
Showing
46 changed files
with
1,516 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
__pycache__/ | ||
*.pyc | ||
/.env | ||
/node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
__pycache__/ | ||
*.pyc | ||
/.env | ||
/node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# autogenerated pyup.io config file | ||
# see https://pyup.io/docs/configuration/ for all available options | ||
|
||
schedule: every month |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
dev |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
FROM python:3.8-slim | ||
|
||
ARG BUILD_DATE="" | ||
ARG BUILD_VERSION="dev" | ||
|
||
LABEL maintainer="truebrain@openttd.org" | ||
LABEL org.label-schema.schema-version="1.0" | ||
LABEL org.label-schema.build-date=${BUILD_DATE} | ||
LABEL org.label-schema.version=${BUILD_VERSION} | ||
|
||
WORKDIR /code | ||
|
||
COPY requirements.txt \ | ||
LICENSE \ | ||
README.md \ | ||
.version \ | ||
/code/ | ||
# Needed for Sentry to know what version we are running | ||
RUN echo "${BUILD_VERSION}" > /code/.version | ||
|
||
RUN pip --no-cache-dir install -r requirements.txt | ||
|
||
# Validate that what was installed was what was expected | ||
RUN pip freeze 2>/dev/null > requirements.installed \ | ||
&& diff -u --strip-trailing-cr requirements.txt requirements.installed 1>&2 \ | ||
|| ( echo "!! ERROR !! requirements.txt defined different packages or versions for installation" \ | ||
&& exit 1 ) 1>&2 | ||
|
||
COPY webclient /code/webclient | ||
|
||
ENTRYPOINT ["python", "-m", "webclient"] | ||
CMD ["--api-url", "https://api.master.staging.openttd.org", "run", "-p", "80", "-h", "0.0.0.0"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.PHONY: run venv flake8 | ||
|
||
run: .env/pyvenv.cfg | ||
FLASK_ENV=development .env/bin/python3 -m webclient --api-url "http://localhost:8080" run | ||
|
||
venv: .env/pyvenv.cfg | ||
|
||
.env/pyvenv.cfg: requirements.txt | ||
python3 -m venv .env | ||
.env/bin/pip install -r requirements.txt | ||
|
||
flake8: | ||
python3 -m flake8 webclient |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Master Server web front-end | ||
|
||
[![GitHub License](https://img.shields.io/github/license/OpenTTD/master-server-web)](https://github.com/OpenTTD/master-server-web/blob/master/LICENSE) | ||
[![GitHub Tag](https://img.shields.io/github/v/tag/OpenTTD/master-server-web?include_prereleases&label=stable)](https://github.com/OpenTTD/master-server-web/releases) | ||
[![GitHub commits since latest release](https://img.shields.io/github/commits-since/OpenTTD/master-server-web/latest/master)](https://github.com/OpenTTD/master-server-web/commits/master) | ||
|
||
[![GitHub Workflow Status (Testing)](https://img.shields.io/github/workflow/status/OpenTTD/master-server-web/Testing/master?label=master)](https://github.com/OpenTTD/master-server-web/actions?query=workflow%3ATesting) | ||
[![GitHub Workflow Status (Publish Image)](https://img.shields.io/github/workflow/status/OpenTTD/master-server-web/Publish%20image?label=publish)](https://github.com/OpenTTD/master-server-web/actions?query=workflow%3A%22Publish+image%22) | ||
[![GitHub Workflow Status (Deployments)](https://img.shields.io/github/workflow/status/OpenTTD/master-server-web/Deployment?label=deployment)](https://github.com/OpenTTD/master-server-web/actions?query=workflow%3A%22Deployment%22) | ||
|
||
[![GitHub deployments (Staging)](https://img.shields.io/github/deployments/OpenTTD/master-server-web/staging?label=staging)](https://github.com/OpenTTD/master-server-web/deployments) | ||
[![GitHub deployments (Production)](https://img.shields.io/github/deployments/OpenTTD/master-server-web/production?label=production)](https://github.com/OpenTTD/master-server-web/deployments) | ||
|
||
This is a front-end for the Master Server Public Server listing. | ||
It works together with [master-server](https://github.com/OpenTTD/master-server), which serves the HTTP API. | ||
|
||
## Development | ||
|
||
This front-end is written in Python 3.7 with Flask. | ||
|
||
## Usage | ||
|
||
To start it, you are advised to first create a virtualenv: | ||
|
||
```bash | ||
python3 -m venv .env | ||
.env/bin/pip install -r requirements.txt | ||
``` | ||
|
||
After this, you can run the flask application by running: | ||
|
||
```bash | ||
make run | ||
``` | ||
|
||
### Running via docker | ||
|
||
```bash | ||
docker build -t openttd/master-server-web:local . | ||
docker run --rm -p 127.0.0.1:5000:80 openttd/master-server-web:local | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Flask | ||
requests | ||
sentry_sdk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
certifi==2020.6.20 | ||
chardet==3.0.4 | ||
click==7.1.2 | ||
Flask==1.1.2 | ||
idna==2.10 | ||
itsdangerous==1.1.0 | ||
Jinja2==2.11.2 | ||
MarkupSafe==1.1.1 | ||
requests==2.24.0 | ||
sentry-sdk==0.17.3 | ||
urllib3==1.25.10 | ||
Werkzeug==1.0.1 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import click | ||
import flask | ||
import logging | ||
|
||
from werkzeug import serving | ||
|
||
from . import pages # noqa | ||
from .app import app | ||
from .click import click_additional_options | ||
from .helpers import click_urls | ||
from .sentry import click_sentry | ||
|
||
|
||
# Patch the werkzeug logger to only log errors | ||
def log_request(self, code="-", size="-"): | ||
if str(code).startswith(("2", "3")): | ||
return | ||
original_log_request(self, code, size) | ||
|
||
|
||
original_log_request = serving.WSGIRequestHandler.log_request | ||
serving.WSGIRequestHandler.log_request = log_request | ||
|
||
|
||
@click_additional_options | ||
def click_logging(): | ||
logging.basicConfig( | ||
format="%(asctime)s %(levelname)-8s %(message)s", datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO | ||
) | ||
|
||
|
||
@click.group(cls=flask.cli.FlaskGroup, create_app=lambda: app) | ||
@click_logging | ||
@click_sentry | ||
@click_urls | ||
def cli(): | ||
pass | ||
|
||
|
||
if __name__ == "__main__": | ||
cli(auto_envvar_prefix="WEBCLIENT") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import flask | ||
import requests | ||
import urllib | ||
|
||
from .app import app | ||
from .helpers import ( | ||
api_host, | ||
redirect, | ||
) | ||
|
||
_client_id = None | ||
|
||
|
||
def api_call(method, path, params=None, json=None, session=None, return_errors=False): | ||
url = api_host() + "/" + "/".join(urllib.parse.quote(p, safe="") for p in path) | ||
headers = None | ||
if session and session.api_token: | ||
headers = {"Authorization": "Bearer " + session.api_token} | ||
|
||
error_response = redirect("error", message="API call failed; sorry for the inconvenience") | ||
try: | ||
r = method(url, params=params, headers=headers, json=json) | ||
|
||
success = r.status_code in (200, 201, 204) | ||
if not success: | ||
app.logger.warning("API failed: {} {}".format(r.status_code, r.text)) | ||
|
||
if success: | ||
result = None | ||
try: | ||
result = r.json() | ||
except Exception: | ||
result = None | ||
if return_errors: | ||
return (result, None) | ||
else: | ||
return result | ||
elif r.status_code == 404: | ||
if return_errors: | ||
return (None, "Data not found") | ||
error_response = redirect("error", message="Data not found") | ||
elif return_errors: | ||
error = str(r.json().get("errors", "API call failed")) | ||
return (None, error) | ||
except Exception: | ||
pass | ||
|
||
if return_errors: | ||
return (None, "API call failed") | ||
else: | ||
flask.abort(error_response) | ||
|
||
|
||
def api_get(*args, **kwargs): | ||
return api_call(requests.get, *args, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import flask | ||
|
||
app = flask.Flask("webclient") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
def click_additional_options(additional_func): | ||
def decorator(func): | ||
additional_params = [] | ||
for param in getattr(additional_func, "__click_params__", []): | ||
additional_params.append(param.name) | ||
|
||
def inner_decorator(**kwargs): | ||
additional_kwargs = {param: kwargs[param] for param in additional_params} | ||
additional_func(**additional_kwargs) | ||
|
||
# Remove the kwargs that are consumed by the additional_func | ||
[kwargs.pop(kwarg) for kwarg in additional_kwargs] | ||
|
||
func(**kwargs) | ||
|
||
inner_decorator.__click_params__ = getattr(func, "__click_params__", []) + getattr( | ||
additional_func, "__click_params__", [] | ||
) | ||
inner_decorator.__doc__ = func.__doc__ | ||
return inner_decorator | ||
|
||
return decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import click | ||
import datetime | ||
import flask | ||
|
||
from .click import click_additional_options | ||
|
||
_api_url = None | ||
|
||
|
||
@click_additional_options | ||
@click.option( | ||
"--api-url", | ||
help="Master Server API URL.", | ||
default="https://api.master.openttd.org", | ||
show_default=True, | ||
metavar="URL", | ||
) | ||
def click_urls(api_url): | ||
global _api_url | ||
_api_url = api_url | ||
|
||
|
||
def template(*args, **kwargs): | ||
messages = kwargs.setdefault("messages", []) | ||
if "message" in kwargs: | ||
messages.append(kwargs["message"]) | ||
if "message" in flask.request.args: | ||
messages.append(flask.request.args["message"]) | ||
kwargs["globals"] = { | ||
"copyright_year": datetime.datetime.utcnow().year, | ||
} | ||
|
||
response = flask.make_response(flask.render_template(*args, **kwargs)) | ||
response.headers["Content-Security-Policy"] = "default-src 'self'" | ||
return response | ||
|
||
|
||
def api_host(): | ||
return _api_url | ||
|
||
|
||
def redirect(*args, **kwargs): | ||
return flask.redirect(flask.url_for(*args, **kwargs)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import static # noqa | ||
from . import servers # noqa |
Oops, something went wrong.