Fetch JTWC Products #88
This file contains hidden or 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
| name: Fetch JTWC Products | |
| # 触发条件:每10分钟自动运行,且允许手动触发 | |
| on: | |
| schedule: | |
| - cron: '*/10 * * * *' # 每10分钟运行一次 | |
| workflow_dispatch: # 允许手动触发 | |
| jobs: | |
| fetch-and-commit: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # 检出代码仓库 | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # 确保获取所有分支历史 | |
| # 切换到pgtw分支,如果不存在则创建 | |
| - name: Switch to pgtw branch or create it | |
| run: | | |
| if git ls-remote --heads origin pgtw | grep -q pgtw; then | |
| echo "Remote branch pgtw exists" | |
| if git rev-parse --verify pgtw 2>/dev/null; then | |
| git checkout pgtw | |
| else | |
| git checkout -b pgtw origin/pgtw | |
| fi | |
| git pull origin pgtw | |
| else | |
| echo "Branch pgtw does not exist remotely, creating new local branch" | |
| git checkout --orphan pgtw | |
| git rm -rf . 2>/dev/null || true | |
| fi | |
| # 从natyphoon获取活跃台风系统,构造JTWC链接并下载 | |
| - name: Fetch active systems and download JTWC products | |
| run: | | |
| echo "==========================================" | |
| echo " Step 1: Fetch active typhoon list" | |
| echo "==========================================" | |
| # 下载natyphoon目录页 | |
| curl -o natyphoon_index.html "https://www.natyphoon.top/atcf/temp/?C=M;O=A" | |
| echo "=== natyphoon page size: $(wc -c < natyphoon_index.html) bytes ===" | |
| # 提取 FN (文件名) 和 LM (最后修改时间) 两个JS数组 | |
| FN_RAW=$(sed -n 's/^const FN = \[\(.*\)\];$/\1/p' natyphoon_index.html) | |
| LM_RAW=$(sed -n 's/^const LM = \[\(.*\)\];$/\1/p' natyphoon_index.html) | |
| # 转为换行分隔的列表(去掉引号) | |
| echo "$FN_RAW" | tr ',' '\n' | sed 's/"//g' > /tmp/fn_list.txt | |
| echo "$LM_RAW" | tr ',' '\n' | sed 's/"//g' > /tmp/lm_list.txt | |
| FN_COUNT=$(wc -l < /tmp/fn_list.txt) | |
| LM_COUNT=$(wc -l < /tmp/lm_list.txt) | |
| echo "FN entries: $FN_COUNT, LM entries: $LM_COUNT" | |
| # 计算2天前的日期 (格式: YYYY/MM/DD) | |
| CUTOFF_DATE=$(date -u -d '2 days ago' +'%Y/%m/%d') | |
| echo "=== Cutoff date: $CUTOFF_DATE ===" | |
| echo "" | |
| echo "==========================================" | |
| echo " Step 2: Filter active systems (last 2 days)" | |
| echo "==========================================" | |
| # 配对文件名和日期,筛选最近2天的 | |
| rm -f /tmp/active_typhoons.txt | |
| touch /tmp/active_typhoons.txt | |
| paste /tmp/fn_list.txt /tmp/lm_list.txt > /tmp/paired_list.txt | |
| while IFS=$'\t' read -r fname lm_date; do | |
| # lm_date 格式: " 2026/04/08 10:45" (可能有前导空格) | |
| DATE_PART=$(echo "$lm_date" | sed 's/^ *//' | cut -d' ' -f1) | |
| if [[ -n "$DATE_PART" ]] && [[ "$DATE_PART" > "$CUTOFF_DATE" || "$DATE_PART" == "$CUTOFF_DATE" ]]; then | |
| echo " ACTIVE: $fname (last modified: $lm_date)" | |
| echo "$fname" >> /tmp/active_typhoons.txt | |
| fi | |
| done < /tmp/paired_list.txt | |
| ACTIVE_COUNT=$(wc -l < /tmp/active_typhoons.txt | tr -d ' ') | |
| echo "" | |
| echo "Found $ACTIVE_COUNT active system(s)" | |
| if [ "$ACTIVE_COUNT" -eq 0 ]; then | |
| echo "No active systems found in last 2 days." | |
| echo "=== Last 10 entries for debugging ===" | |
| paste /tmp/fn_list.txt /tmp/lm_list.txt | tail -10 | |
| exit 0 | |
| fi | |
| echo "" | |
| echo "==========================================" | |
| echo " Step 3: Construct JTWC URLs and fetch" | |
| echo "==========================================" | |
| # 对每个活跃的台风系统,构造JTWC URL并尝试下载 | |
| while IFS= read -r datfile; do | |
| # 从 b{region}{num}{year}.dat 提取信息 | |
| # 例如 bwp902026.dat -> region=wp, num=90, year=2026, shortyear=26 | |
| REGION=$(echo "$datfile" | sed -E 's/^b([a-z]{2})[0-9]+\.dat$/\1/') | |
| NUMYEAR=$(echo "$datfile" | sed -E 's/^b[a-z]{2}(.*)\.dat$/\1/') | |
| YEAR="${NUMYEAR: -4}" | |
| NUM="${NUMYEAR%${YEAR}}" | |
| SHORT_YEAR="${YEAR: -2}" | |
| echo "" | |
| echo "--- System: $datfile ---" | |
| echo " Region=$REGION, Num=$NUM, Year=$YEAR, ShortYear=$SHORT_YEAR" | |
| # 尝试三种type: web, prog, fix | |
| for TYPE in web prog fix; do | |
| URL="https://www.metoc.navy.mil/jtwc/products/${REGION}${NUM}${SHORT_YEAR}${TYPE}.txt" | |
| OUTFILE="${REGION}${NUM}${SHORT_YEAR}${TYPE}.txt" | |
| echo " Trying: $URL" | |
| HTTP_CODE=$(curl -o "$OUTFILE" -w '%{http_code}' -s "$URL") | |
| if [ "$HTTP_CODE" = "200" ]; then | |
| # 检查内容是否为HTML错误页面 | |
| FIRST_CHAR=$(head -c 1 "$OUTFILE") | |
| if [ "$FIRST_CHAR" = "<" ]; then | |
| echo " -> HTTP 200 but content is HTML (likely error page), skipping" | |
| echo " -> First line: $(head -1 "$OUTFILE")" | |
| rm -f "$OUTFILE" | |
| else | |
| FILESIZE=$(wc -c < "$OUTFILE") | |
| echo " -> SUCCESS ($FILESIZE bytes)" | |
| echo " -> First 3 lines:" | |
| head -3 "$OUTFILE" | sed 's/^/ /' | |
| fi | |
| else | |
| echo " -> HTTP $HTTP_CODE, skipping" | |
| rm -f "$OUTFILE" | |
| fi | |
| done | |
| done < /tmp/active_typhoons.txt | |
| echo "" | |
| echo "==========================================" | |
| echo " Step 4: Summary of downloaded files" | |
| echo "==========================================" | |
| echo "=== Files in current directory ===" | |
| ls -la *.txt 2>/dev/null || echo "(no .txt files downloaded)" | |
| # 清理临时文件 | |
| rm -f /tmp/active_typhoons.txt /tmp/fn_list.txt /tmp/lm_list.txt /tmp/paired_list.txt | |
| # 测试模式:不提交,只打印结果 | |
| - name: Summary (test mode - no commit) | |
| run: | | |
| echo "==========================================" | |
| echo " TEST MODE - No files will be committed" | |
| echo "==========================================" | |
| echo "Downloaded .txt files:" | |
| for f in *.txt; do | |
| if [ -f "$f" ]; then | |
| echo " $f ($(wc -c < "$f") bytes)" | |
| fi | |
| done 2>/dev/null || echo " (none)" |