-
-
Notifications
You must be signed in to change notification settings - Fork 24
256 lines (215 loc) · 9.88 KB
/
Copy pathsteam_mod_update_notifier.yml
File metadata and controls
256 lines (215 loc) · 9.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
name: Steam Mod Update Notifier
on:
schedule:
- cron: '0 6 * * *'
workflow_dispatch:
concurrency:
group: steam-mod-update-notifier
cancel-in-progress: false
permissions:
contents: read
actions: write
issues: write
jobs:
check-steam-mod-updates:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Check Steam Workshop mods and notify
shell: bash
env:
GH_TOKEN: ${{ secrets.API_TOKEN_GITHUB }}
GITHUB_API: https://api.github.com
STEAM_PUBLISHED_FILE_DETAILS_API: https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/
run: |
set -euo pipefail
if ! command -v jq >/dev/null 2>&1; then
echo "jq is required on the self-hosted runner." >&2
exit 1
fi
REPO="${GITHUB_REPOSITORY}"
# Ordered list of tracked mods.
MOD_IDS=(
"2243307127"
"2858562094"
"2509174436"
"2970440958"
"3496956814"
"2532715348"
"2856497654"
"2992438857"
)
declare -A MOD_NAMES=(
["2243307127"]="TFE"
["2858562094"]="WtWSMS"
["2509174436"]="RoA"
["2970440958"]="AEP"
["3496956814"]="Confederations & Leagues"
["2532715348"]="Invictus"
["2856497654"]="Terra Indomita"
["2992438857"]="Antiquitas"
)
urlencode() {
jq -rn --arg v "$1" '$v|@uri'
}
github_api() {
local method="$1"
local path="$2"
local body="${3:-}"
local tmp_body
local tmp_status
tmp_body="$(mktemp)"
tmp_status="$(mktemp)"
if [[ -n "$body" ]]; then
curl -sS \
-X "$method" \
-H "Authorization: Bearer ${GH_TOKEN}" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
-H "Content-Type: application/json" \
-d "$body" \
-o "$tmp_body" \
-w "%{http_code}" \
"${GITHUB_API}${path}" >"$tmp_status"
else
curl -sS \
-X "$method" \
-H "Authorization: Bearer ${GH_TOKEN}" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
-o "$tmp_body" \
-w "%{http_code}" \
"${GITHUB_API}${path}" >"$tmp_status"
fi
cat "$tmp_status"
echo
cat "$tmp_body"
rm -f "$tmp_body" "$tmp_status"
}
scrape_changelog_notes() {
local workshop_id="$1"
local previous_ts="$2"
python3 "${GITHUB_WORKSPACE}/.github/scripts/steam_changelog_scraper.py" "$workshop_id" "$previous_ts"
}
echo "Fetching published file details from Steam..."
steam_args=(--data "itemcount=${#MOD_IDS[@]}")
for i in "${!MOD_IDS[@]}"; do
steam_args+=(--data-urlencode "publishedfileids[$i]=${MOD_IDS[$i]}")
done
steam_response="$(curl -sS -X POST "${STEAM_PUBLISHED_FILE_DETAILS_API}" "${steam_args[@]}")"
mapfile -t steam_rows < <(
echo "$steam_response" | jq -r '.response.publishedfiledetails[]? | [.publishedfileid, .time_updated, (.title // "")] | @tsv'
)
if [[ "${#steam_rows[@]}" -eq 0 ]]; then
echo "No Steam Workshop details were returned." >&2
exit 1
fi
declare -A STEAM_TIME_UPDATED
declare -A STEAM_TITLES
for row in "${steam_rows[@]}"; do
id="$(echo "$row" | cut -f1)"
ts="$(echo "$row" | cut -f2)"
title="$(echo "$row" | cut -f3-)"
STEAM_TIME_UPDATED["$id"]="$ts"
STEAM_TITLES["$id"]="$title"
done
had_error=0
for id in "${MOD_IDS[@]}"; do
mod_name="${MOD_NAMES[$id]}"
workshop_url="https://steamcommunity.com/sharedfiles/filedetails/?id=${id}"
variable_name="STEAM_MOD_${id}_TIME_UPDATED"
current_ts="${STEAM_TIME_UPDATED[$id]:-}"
if [[ -z "$current_ts" || ! "$current_ts" =~ ^[0-9]+$ ]]; then
echo "[$mod_name] Missing or invalid current timestamp from Steam for id ${id}."
had_error=1
continue
fi
readarray -t variable_result < <(github_api GET "/repos/${REPO}/actions/variables/${variable_name}")
variable_status="${variable_result[0]}"
variable_body="${variable_result[@]:1}"
if [[ "$variable_status" == "404" ]]; then
create_payload="$(jq -nc --arg name "$variable_name" --arg value "$current_ts" '{name: $name, value: $value}')"
readarray -t create_result < <(github_api POST "/repos/${REPO}/actions/variables" "$create_payload")
create_status="${create_result[0]}"
if [[ "$create_status" == "201" ]]; then
echo "[$mod_name] Repository variable ${variable_name} initialized to ${current_ts}."
else
echo "[$mod_name] Failed to create repository variable ${variable_name}. HTTP ${create_status}."
had_error=1
fi
continue
fi
if [[ "$variable_status" != "200" ]]; then
echo "[$mod_name] Failed to read repository variable ${variable_name}. HTTP ${variable_status}."
had_error=1
continue
fi
previous_ts="$(printf '%s\n' "$variable_body" | jq -r '.value // empty')"
if [[ -z "$previous_ts" || ! "$previous_ts" =~ ^[0-9]+$ ]]; then
echo "[$mod_name] Repository variable ${variable_name} has invalid value '${previous_ts}'. Reinitializing."
update_payload="$(jq -nc --arg name "$variable_name" --arg value "$current_ts" '{name: $name, value: $value}')"
readarray -t reset_result < <(github_api PATCH "/repos/${REPO}/actions/variables/${variable_name}" "$update_payload")
reset_status="${reset_result[0]}"
if [[ "$reset_status" == "204" ]]; then
echo "[$mod_name] Repository variable ${variable_name} reset to ${current_ts}."
else
echo "[$mod_name] Failed to reset repository variable ${variable_name}. HTTP ${reset_status}."
had_error=1
fi
continue
fi
if (( current_ts <= previous_ts )); then
echo "[$mod_name] No new update detected (stored=${previous_ts}, current=${current_ts})."
continue
fi
echo "[$mod_name] New update detected (stored=${previous_ts}, current=${current_ts})."
current_date="$(date -u -d "@${current_ts}" '+%Y-%m-%d %H:%M UTC')"
release_notes="$(scrape_changelog_notes "$id" "$previous_ts")"
if [[ -z "$release_notes" ]]; then
release_notes="Release notes could not be retrieved from Steam changelog page for this update."
fi
marker="<!-- steam-mod-update:${id}:${current_ts} -->"
marker_query="$(urlencode "$marker")"
search_path="/search/issues?q=repo:${REPO}+type:issue+in:body+${marker_query}&per_page=1"
readarray -t search_result < <(github_api GET "$search_path")
search_status="${search_result[0]}"
search_body="${search_result[@]:1}"
if [[ "$search_status" != "200" ]]; then
echo "[$mod_name] Failed to search for existing notification issue. HTTP ${search_status}."
had_error=1
continue
fi
existing_count="$(printf '%s\n' "$search_body" | jq -r '.total_count // 0')"
if [[ "$existing_count" =~ ^[0-9]+$ ]] && (( existing_count > 0 )); then
echo "[$mod_name] Notification already exists for this update; skipping issue creation."
else
issue_title="${mod_name} has been updated on ${current_date}"
printf -v issue_body '%s\n\nSteam Workshop mod **%s** was updated.\n\n- Mod ID: %s\n- Update date (UTC): %s\n- Workshop page: %s\n\n## Release Notes\n\n%s\n' \
"$marker" "$mod_name" "$id" "$current_date" "$workshop_url" "$release_notes"
issue_payload="$(jq -nc --arg title "$issue_title" --arg body "$issue_body" '{title: $title, body: $body}')"
readarray -t issue_result < <(github_api POST "/repos/${REPO}/issues" "$issue_payload")
issue_status="${issue_result[0]}"
if [[ "$issue_status" == "201" ]]; then
echo "[$mod_name] Created notification issue: ${issue_title}"
else
echo "[$mod_name] Failed to create notification issue. HTTP ${issue_status}."
had_error=1
continue
fi
fi
update_payload="$(jq -nc --arg name "$variable_name" --arg value "$current_ts" '{name: $name, value: $value}')"
readarray -t update_result < <(github_api PATCH "/repos/${REPO}/actions/variables/${variable_name}" "$update_payload")
update_status="${update_result[0]}"
if [[ "$update_status" == "204" ]]; then
echo "[$mod_name] Updated repository variable ${variable_name} to ${current_ts}."
else
echo "[$mod_name] Failed to update repository variable ${variable_name}. HTTP ${update_status}."
had_error=1
fi
done
if (( had_error != 0 )); then
echo "One or more mods could not be processed completely."
exit 1
fi
echo "Steam mod update check finished successfully."