Skip to content

Commit af12a3a

Browse files
committed
dockerize
1 parent 645f708 commit af12a3a

File tree

10 files changed

+116
-101
lines changed

10 files changed

+116
-101
lines changed

.github/workflows/image.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Docker
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
7+
jobs:
8+
build:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
packages: write
13+
id-token: write
14+
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
19+
- name: Log in to the Container registry
20+
uses: docker/login-action@v3
21+
with:
22+
registry: ghcr.io
23+
username: ${{ github.actor }}
24+
password: ${{ secrets.GITHUB_TOKEN }}
25+
26+
- name: Extract metadata (tags, labels) for Docker
27+
id: meta
28+
uses: docker/metadata-action@v5
29+
with:
30+
images: ghcr.io/${{ github.repository }}
31+
32+
- name: Set up Docker Buildx
33+
uses: docker/setup-buildx-action@v3
34+
35+
- name: Build and push Docker image
36+
uses: docker/build-push-action@v6
37+
with:
38+
context: .
39+
platforms: linux/amd64
40+
file: Dockerfile
41+
push: true
42+
cache-from: type=gha
43+
cache-to: type=gha,mode=max
44+
tags: ${{ steps.meta.outputs.tags }}
45+
labels: ${{ steps.meta.outputs.labels }}
46+
47+
deploy:
48+
if: ${{ github.ref == 'refs/heads/master' }}
49+
needs: build
50+
runs-on: ubuntu-latest
51+
steps:
52+
- name: deploy
53+
env:
54+
DEPLOY_WEBHOOK_URL: ${{ secrets.DEPLOY_WEBHOOK_URL }}
55+
run: curl -X POST $DEPLOY_WEBHOOK_URL

Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM python:3.13.2-alpine3.21
2+
3+
RUN pip install --upgrade pip wheel
4+
5+
RUN python -m ensurepip --upgrade && \
6+
pip install setuptools --upgrade
7+
8+
COPY requirements.txt /requirements.txt
9+
RUN pip install -r requirements.txt
10+
11+
COPY . /app
12+
WORKDIR /app
13+
14+
ENTRYPOINT ["python", "app.py"]

README.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,21 @@ There are several tools, e.g.:
55

66
## Deployment
77
1. Install the packages from requirements.txt.
8-
2. Edit the following settings in config.yml:
9-
- `host: "127.0.0.1"`
10-
- `port: 5000`
11-
- `url: "https://some.website.org"`
12-
- everything else is best left by default
13-
3. Run `python app.py`
8+
2. Run the app:
9+
```bash
10+
python app.py
11+
12+
# or customize the host, port, and app URL
13+
HOST=127.0.0.1 PORT=5000 APP_URL=https://some.website.org python app.py
14+
```
15+
16+
## Test docker build locally
17+
18+
```bash
19+
docker build -t litools .
20+
21+
docker run -p 5000:5000 litools
22+
```
1423

1524
## Feedback
1625
Any suggestions for possible improvements and bug reports are welcome.

api.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@
55
import time
66
from datetime import datetime
77
from dateutil import tz
8-
import yaml
98
import traceback
109
import os
1110
from threading import Lock
12-
from consts import API_TOURNEY_PAGE_DELAY, CONFIG_FILE, VERBOSE
13-
14-
15-
log_file: str = None
11+
from consts import API_TOURNEY_PAGE_DELAY, VERBOSE
12+
from elements import get_log_file
1613

1714

1815
class Endpoint:
@@ -223,26 +220,17 @@ def get_ndjson(self, api, url, token, Accept="application/x-ndjson"):
223220
def log(text, to_print=False, to_save=True, verbose=1):
224221
if verbose > VERBOSE:
225222
return
226-
global log_file
227-
if log_file is None:
228-
try:
229-
with open(os.path.abspath(f"./{CONFIG_FILE}")) as stream:
230-
config = yaml.safe_load(stream)
231-
log_file = config.get('log', "")
232-
except:
233-
log_file = ""
234223
now_utc = datetime.now(tz=tz.tzutc())
235224
line = f"{now_utc: %Y-%m-%d %H:%M:%S} UTC: {text}"
236225
if to_print:
237226
print(line)
238-
if not log_file or not to_save:
227+
if not to_save:
239228
return
240229
try:
241-
with open(log_file, "a", encoding="utf-8") as file:
230+
with open(get_log_file(), "a", encoding="utf-8") as file:
242231
file.write(f"{line}\n")
243232
except Exception as exception:
244233
traceback.print_exception(type(exception), exception, exception.__traceback__)
245-
log_file = ""
246234

247235

248236
def log_exception(exception, to_print=True, to_save=True):

app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,4 +692,4 @@ def revoke_token(token_hash):
692692
log(f"Started: {LITOOLS_VERSION}", to_print=True, to_save=True)
693693
thread = threading.Thread(name="chat_loop", target=chat_loop)
694694
thread.start()
695-
serve(app.run(), host=get_host(), port=get_port(), threads=get_num_threads())
695+
serve(app.run(host=get_host(), port=get_port()), threads=get_num_threads())

chat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
class ChatAnalysis:
4545
re_kid_years = re.compile(r"(?:\b|\D)({})(?:\b|\D)".format("|".join(
46-
[f"{y}\s*(?:г|л|y|j)|{datetime.now().year - y}" for y in range(6, 12)])), re.IGNORECASE)
46+
[f"{y}\\s*(?:г|л|y|j)|{datetime.now().year - y}" for y in range(6, 12)])), re.IGNORECASE)
4747
re_tourn_id = re.compile(r"^\w{8}$")
4848

4949
def __init__(self):

chat_message.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import yaml
1+
import os
22
import html
33
from datetime import datetime, timedelta
44
from enum import IntFlag
55
from elements import STYLE_WORD_BREAK
66
from chat_re import list_res, list_res_variety, re_spaces, Lang
77
from database import Messages
88
from elements import Reason, deltaseconds, get_user_comm_href, get_highlight_style, get_flair_element, log, log_exception
9-
from consts import CONFIG_FILE
109

1110

1211
class AddButtons(IntFlag):
@@ -17,21 +16,19 @@ class AddButtons(IntFlag):
1716

1817

1918
def load_res():
20-
with open(CONFIG_FILE) as stream:
21-
config = yaml.safe_load(stream)
22-
timeouts = config.get('timeouts', "En Spam").lower()
23-
list_re = []
24-
list_re_variety = []
25-
for lang in Lang:
26-
if lang.name.lower() in timeouts:
27-
for re in list_res[lang]:
28-
re.lang = lang
29-
list_re.extend(list_res[lang])
30-
for lang in Lang:
31-
if (lang.name.lower() in timeouts) and (lang in list_res_variety):
32-
for re in list_res_variety[lang]:
33-
re.lang = lang
34-
list_re_variety.extend(list_res_variety[lang])
19+
timeouts = os.getenv('TIMEOUTS', "Spam En Ru De Hi Es It Fr Tr").lower()
20+
list_re = []
21+
list_re_variety = []
22+
for lang in Lang:
23+
if lang.name.lower() in timeouts:
24+
for re in list_res[lang]:
25+
re.lang = lang
26+
list_re.extend(list_res[lang])
27+
for lang in Lang:
28+
if (lang.name.lower() in timeouts) and (lang in list_res_variety):
29+
for re in list_res_variety[lang]:
30+
re.lang = lang
31+
list_re_variety.extend(list_res_variety[lang])
3532
return list_re, list_re_variety
3633

3734

config.yml

Lines changed: 0 additions & 9 deletions
This file was deleted.

elements.py

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,20 @@
22
from dateutil import tz
33
from dateutil.relativedelta import relativedelta
44
from enum import IntEnum, Enum, IntFlag
5-
import yaml
65
import traceback
76
import os
87
import html
98
import re
109
import hashlib
1110
import math
1211
import base64
13-
import random
1412
import struct
1513
from itertools import chain
1614
from pygal.style import DarkStyle
1715
from api import ApiType
1816
from consts import *
1917

2018

21-
log_file: str = None
22-
db_file = ""
23-
host = "127.0.0.1"
24-
port = 5000
25-
num_threads = 2
26-
uri = ""
27-
embed_lichess = False
2819
refresh_insights_times = {}
2920

3021
STYLE_WORD_BREAK = "word-break:break-word;" # "word-break:break-all;"
@@ -120,65 +111,39 @@ def add_timeout_msg(timeouts, msg):
120111
timeouts[msg.username] = msg
121112

122113

123-
def load_config():
124-
global log_file, db_file, host, port, num_threads, uri, embed_lichess
125-
if log_file is None:
126-
try:
127-
with open(os.path.abspath(f"./{CONFIG_FILE}")) as stream:
128-
config = yaml.safe_load(stream)
129-
log_file = config.get('log', "")
130-
db_file = config.get('db', "")
131-
host = config.get('host', host)
132-
port = config.get('port', port)
133-
num_threads = config.get('num_threads', num_threads)
134-
uri = config.get('url', "")
135-
embed_lichess = config.get('embed_lichess', False)
136-
except Exception as e:
137-
print(f"There appears to be a syntax problem with {CONFIG_FILE}: {e}")
138-
log_file = ""
114+
def get_log_file():
115+
return os.getenv("LOG_FILE", "./log/log.txt")
139116

140117

141118
def get_token():
142-
try:
143-
with open(os.path.abspath(f"./{CONFIG_FILE}")) as stream:
144-
config = yaml.safe_load(stream)
145-
token = config.get('token', "")
146-
except Exception as e:
147-
log(f"There appears to be a syntax problem with {CONFIG_FILE}: {e}", to_print=True, to_save=True)
148-
token = ""
119+
token = os.getenv("TOKEN")
149120
if token:
150121
log("using token", to_print=True, to_save=True)
151122
return token
152123

153124

154125
def get_db():
155-
load_config()
156-
return db_file
126+
return os.getenv("DB_FILE", "./db/litools.sqlite")
157127

158128

159129
def get_host():
160-
load_config()
161-
return host
130+
return os.getenv("HOST", "0.0.0.0")
162131

163132

164133
def get_port():
165-
load_config()
166-
return port
134+
return int(os.getenv("PORT", 5000))
167135

168136

169137
def get_num_threads():
170-
load_config()
171-
return num_threads
138+
return int(os.getenv("NUM_THREADS", 2))
172139

173140

174141
def get_uri():
175-
load_config()
176-
return uri
142+
return os.getenv("APP_URL", "http://localhost:5000")
177143

178144

179145
def get_embed_lichess():
180-
load_config()
181-
return embed_lichess
146+
return bool(os.getenv("EMBED_LICHESS", False))
182147

183148

184149
def needs_to_refresh_insights(user_id, now=None):
@@ -982,21 +947,17 @@ def to_Tag(reason):
982947
def log(text, to_print=False, to_save=True, verbose=1):
983948
if verbose > VERBOSE:
984949
return
985-
global log_file
986-
if log_file is None:
987-
load_config()
988950
now_utc = datetime.now(tz=tz.tzutc())
989951
line = f"{now_utc: %Y-%m-%d %H:%M:%S} UTC: {text}"
990952
if to_print:
991953
print(line)
992-
if not log_file or not to_save:
954+
if not to_save:
993955
return
994956
try:
995-
with open(log_file, "a", encoding="utf-8") as file:
957+
with open(get_log_file(), "a", encoding="utf-8") as file:
996958
file.write(f"{line}\n")
997959
except Exception as exception:
998960
traceback.print_exception(type(exception), exception, exception.__traceback__)
999-
log_file = ""
1000961

1001962

1002963
def log_exception(exception, to_print=True, to_save=True):
@@ -1010,6 +971,7 @@ def log_read(lines_per_page=100, page=0, reverse=True):
1010971
if lines_per_page < 0 or page < 0:
1011972
return ""
1012973
max_size = 50_000_000
974+
log_file = get_log_file()
1013975
file_size = os.stat(log_file).st_size
1014976
with open(log_file, "r", encoding="utf-8") as file:
1015977
if file_size > max_size:

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ peewee==3.15.4
1717
ply==3.11
1818
pygal==3.0.0
1919
python-dateutil==2.8.2
20-
PyYAML==6.0
2120
rcssmin==1.2.0
2221
requests==2.28.1
2322
six==1.16.0

0 commit comments

Comments
 (0)