Skip to content

Commit e4bad7f

Browse files
authored
Merge pull request #1 from tofran/2022-updates
Added looping feature, better dependency management and continuous delivery
2 parents 629803b + bf94a20 commit e4bad7f

File tree

5 files changed

+113
-20
lines changed

5 files changed

+113
-20
lines changed

.github/workflows/build.yaml

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Build and push
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
tags:
8+
pull_request:
9+
release:
10+
types:
11+
- published
12+
workflow_dispatch:
13+
14+
jobs:
15+
build:
16+
name: Build and publish image
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
20+
packages: write
21+
steps:
22+
- uses: actions/checkout@v3
23+
24+
- name: Login to Docker Hub
25+
uses: docker/login-action@v2
26+
with:
27+
username: ${{ github.actor }}
28+
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
29+
30+
- name: Login to GitHub container registry
31+
uses: docker/login-action@v2
32+
with:
33+
registry: ghcr.io
34+
username: ${{ github.actor }}
35+
password: ${{ secrets.GITHUB_TOKEN }}
36+
37+
- name: Set up QEMU
38+
uses: docker/setup-qemu-action@v2
39+
40+
- name: Set up Docker Buildx
41+
uses: docker/setup-buildx-action@v2
42+
43+
- name: Docker metadata
44+
id: docker_metadata
45+
uses: docker/metadata-action@v4
46+
with:
47+
images: |
48+
name=ghcr.io/${{ github.repository }}
49+
name=${{ github.repository }},enable=${{ github.event_name != 'pull_request' }}
50+
tags: |
51+
type=sha
52+
type=ref,event=branch
53+
type=ref,event=pr
54+
type=semver,pattern={{version}}
55+
type=semver,pattern={{major}}.{{minor}}
56+
type=semver,pattern={{major}}
57+
58+
- name: Build and push
59+
id: docker_build
60+
uses: docker/build-push-action@v3
61+
with:
62+
context: ./
63+
file: ./Dockerfile
64+
platforms: linux/amd64, linux/arm64, linux/386
65+
push: true
66+
tags: ${{ steps.docker_metadata.outputs.tags }}
67+
labels: ${{ steps.docker_metadata.outputs.labels }}
68+
cache-from: type=gha
69+
cache-to: type=gha,mode=max

Dockerfile

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
FROM python:alpine
1+
FROM python:3.11-alpine
22

3-
RUN pip install --upgrade pip && pip install requests
3+
ENV PYTHONUNBUFFERED=1
44

5-
COPY ./advent_of_code_notify.py ./advent_of_code_notify.py
5+
WORKDIR /app
6+
7+
COPY ./requirements.txt ./
8+
RUN pip install --upgrade pip && pip install -r requirements.txt
69

7-
CMD ["/advent_of_code_notify.py"]
10+
COPY ./advent_of_code_notify.py ./advent_of_code_notify.py
11+
CMD "./advent_of_code_notify.py"

README.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,32 @@ I'm using this to track the progress of a group of friends on Discord.
88

99
## Usage
1010

11-
Just run this image periodically (at a minimum interval of 15 min):
11+
Just run this image whenever you want to check for updates:
1212

1313
```sh
1414
$ docker run \
1515
-e WEBHOOK_URL="your webhook url" \
1616
-e ADVENT_OF_CODE_SESSION_ID="your advent of code session id" \
1717
-e ADVENT_OF_CODE_LEADERBOARD_ID="numeric leaderboard id" \
18-
-e CACHE_FILE=/cache/cache.json \
18+
-e CACHE_FILE="/cache/cache.json" \
19+
# (Optional) -e LOOP_SLEEP_SECONDS="900" \
1920
-v "$(pwd)/cache/:/cache/" \
2021
ghcr.io/tofran/advent-of-code-leaderboard-notifier
2122
```
2223

24+
It should exit successfully. Run it periodically (at a minimum interval of 15 min),
25+
or pass the `LOOP_SLEEP_SECONDS` env var to make the script loop.
26+
2327
### Configuration
2428

2529
- `ADVENT_OF_CODE_LEADERBOARD_ID`: The unique ID of the leaderboard. It's an integer you can get from the end of leaderboard url or the prefix of the invite code.
2630
- `ADVENT_OF_CODE_SESSION_ID`: Your advent of code session id.
27-
To retrieve it, go visit adventofcode.com, open developer tools > storage > cookies > copy the value of your `session` cookie.
28-
- `WEBHOOK_URL`: Where to send the webhook. Can be for example a discord webhook.
31+
To retrieve it, visit adventofcode.com, open developer tools > storage > cookies > copy the value of your `session` cookie.
32+
- `WEBHOOK_URL`: Where to send the webhook. For example a Discord webhook URL.
2933
- `ADVENT_OF_CODE_YEAR`: Optional, defaults to the current year if already in december, otherwise the previous one.
3034
- `CACHE_FILE`: Optional, defaults to `./cache.json`
35+
- `LOOP_SLEEP_SECONDS`: Optional, defaults to `0`, meaning it only runs once and terminates the process. Otherwise set it to how many seconds to sleep between runs. It is recommended a value greater than `900` (15 min).
36+
- `WEBHOOK_MAX_CONTENT_LENGTH`: Optional, the maximum number of characters that can be sent to the webhook. Defaults to `2000`.
3137

3238

3339
## License

advent_of_code_notify.py

+25-12
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
# tofran, dec 2020
88
# https://github.com/tofran/advent-of-code-leaderboard-notifier
99

10-
import os
11-
import requests
1210
import json
11+
import os
1312
from datetime import date
13+
from time import sleep
14+
15+
import requests
1416

1517
LEADERBOARD_ENDPOINT_TEMPLATE = (
1618
"https://adventofcode.com/"
@@ -27,20 +29,19 @@ def get_default_year():
2729
return today.year - 1
2830

2931

30-
ADVENT_OF_CODE_YEAR = int(os.getenv("ADVENT_OF_CODE_YEAR", get_default_year()))
3132
ADVENT_OF_CODE_LEADERBOARD_ID = os.getenv("ADVENT_OF_CODE_LEADERBOARD_ID")
3233
ADVENT_OF_CODE_SESSION_ID = os.getenv("ADVENT_OF_CODE_SESSION_ID")
33-
34+
ADVENT_OF_CODE_YEAR = int(os.getenv("ADVENT_OF_CODE_YEAR", get_default_year()))
35+
LOOP_SLEEP_SECONDS = int(os.getenv("LOOP_SLEEP_SECONDS", "0"))
36+
WEBHOOK_MAX_CONTENT_LENGTH = int(os.getenv("WEBHOOK_MAX_CONTENT_LENGTH", "2000"))
3437
WEBHOOK_URL = os.getenv("WEBHOOK_URL")
3538

3639
assert ADVENT_OF_CODE_LEADERBOARD_ID, "ADVENT_OF_CODE_LEADERBOARD_ID missing"
3740
assert ADVENT_OF_CODE_SESSION_ID, "ADVENT_OF_CODE_SESSION_ID missing"
3841
assert WEBHOOK_URL, "WEBHOOK_URL missing"
3942

40-
WEBHOOK_MAX_CONTENT_LENGTH = int(os.getenv("WEBHOOK_MAX_CONTENT_LENGTH", "2000"))
41-
4243

43-
def get_leaderboard_enpoint(as_json_api=True):
44+
def get_leaderboard_endpoint(as_json_api=True):
4445
return LEADERBOARD_ENDPOINT_TEMPLATE.format(
4546
year=ADVENT_OF_CODE_YEAR,
4647
leaderboard_id=ADVENT_OF_CODE_LEADERBOARD_ID,
@@ -67,7 +68,7 @@ def save_cached_leaderboard(data):
6768

6869
def fetch_leaderboard():
6970
response = requests.get(
70-
get_leaderboard_enpoint(as_json_api=True),
71+
get_leaderboard_endpoint(as_json_api=True),
7172
cookies={
7273
"session": ADVENT_OF_CODE_SESSION_ID
7374
}
@@ -93,8 +94,8 @@ def get_name(leaderboard, member_id):
9394

9495
def send_webhook_notification(content):
9596
if len(content) > WEBHOOK_MAX_CONTENT_LENGTH:
96-
content = "The diff is too big, check the leaderbord: {}".format(
97-
get_leaderboard_enpoint(as_json_api=False)
97+
content = "The diff is too big, check the leaderboard: {}".format(
98+
get_leaderboard_endpoint(as_json_api=False)
9899
)
99100

100101
requests.post(
@@ -113,13 +114,14 @@ def get_leaderboard_diff(old_leaderboard, new_leaderboard):
113114
)
114115

115116

116-
def main():
117+
def run():
117118
old_leaderboard = get_cached_leaderboard()
118119
new_leaderboard = fetch_leaderboard()
119120

120121
diff = get_leaderboard_diff(old_leaderboard, new_leaderboard)
121122

122123
if not diff:
124+
print("No changes detected.")
123125
return
124126

125127
messages = [
@@ -131,12 +133,23 @@ def main():
131133
for member_id, day, part in diff
132134
]
133135

134-
print("Leaderboard chnaged:", messages)
136+
print("Leaderboard changed:", messages)
135137

136138
send_webhook_notification("\n".join(messages))
137139

138140
save_cached_leaderboard(new_leaderboard)
139141

140142

143+
def main():
144+
if LOOP_SLEEP_SECONDS <= 0:
145+
run()
146+
return
147+
148+
while True:
149+
run()
150+
print(f"Sleeping {LOOP_SLEEP_SECONDS}s")
151+
sleep(LOOP_SLEEP_SECONDS)
152+
153+
141154
if __name__ == "__main__":
142155
main()

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
requests==2.*

0 commit comments

Comments
 (0)