Files
RexiMemo-OSE/server.py
T

87 lines
2.5 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import os
import sys
import time
PORT = int(os.environ.get("REXIMEMO_PORT", "8080"))
DOCS_ARGUMENT = "docs:enabled"
def docs_enabled_from_args():
return DOCS_ARGUMENT in sys.argv[1:]
def _force_project_working_directory():
os.chdir(os.path.dirname(os.path.abspath(__file__)))
def _import_twisted():
try:
from twisted.internet import reactor
from twisted.web import server
except ImportError as exc:
raise SystemExit("Twisted is required. Install dependencies with: python3 -m pip install -r requirements.txt") from exc
return reactor, server
class Log:
def __init__(self):
os.makedirs("logs", exist_ok=True)
self.handle = open("logs/reximemo.log", "a", encoding="utf-8")
def write(self, text, silent=False):
line = "[%s] %s" % (time.strftime("%H:%M:%S"), str(text).rstrip())
if not silent:
print(line)
self.handle.write(line + "\n")
self.handle.flush()
def close(self):
self.handle.close()
def create_site(*, docs_enabled=False):
_force_project_working_directory()
reactor, twisted_server = _import_twisted()
import DB # initializes SQLite
import hatena
log = Log()
hatena.ServerLog = log
class ProxyCompatibleSite(twisted_server.Site):
def buildProtocol(self, addr):
protocol = super().buildProtocol(addr)
original = protocol.dataReceived
def data_received(data):
for host in (b"flipnote.hatena.com", b"ugomemo.hatena.ne.jp"):
data = data.replace(b"GET http://" + host, b"GET ")
data = data.replace(b"POST http://" + host, b"POST ")
return original(data)
protocol.dataReceived = data_received
return protocol
return reactor, ProxyCompatibleSite(hatena.Setup(docs_enabled=docs_enabled)), log
def main():
docs_enabled = docs_enabled_from_args()
reactor, site, log = create_site(docs_enabled=docs_enabled)
log.write("RexiMemo OSE starting on port %d" % PORT)
log.write("DSi mode uses the historical HTTP proxy path; NAS/DNS/auth services are not included.")
if docs_enabled:
log.write("Built-in documentation enabled at /docs")
reactor.listenTCP(PORT, site)
try:
reactor.run()
finally:
log.write("Server shutdown", True)
log.close()
if __name__ == "__main__":
main()