diff --git a/autouploader/__pycache__/config.cpython-310.pyc b/autouploader/__pycache__/config.cpython-310.pyc
new file mode 100644
index 0000000..bab9e2e
Binary files /dev/null and b/autouploader/__pycache__/config.cpython-310.pyc differ
diff --git a/autouploader/__pycache__/config.cpython-311.pyc b/autouploader/__pycache__/config.cpython-311.pyc
new file mode 100644
index 0000000..6063f49
Binary files /dev/null and b/autouploader/__pycache__/config.cpython-311.pyc differ
diff --git a/autouploader/__pycache__/weather.cpython-310.pyc b/autouploader/__pycache__/weather.cpython-310.pyc
new file mode 100644
index 0000000..babf456
Binary files /dev/null and b/autouploader/__pycache__/weather.cpython-310.pyc differ
diff --git a/app/config.sample.py b/autouploader/config.sample.py
similarity index 100%
rename from app/config.sample.py
rename to autouploader/config.sample.py
diff --git a/app/gnu_autoupload.py b/autouploader/gnu_autoupload.py
similarity index 100%
rename from app/gnu_autoupload.py
rename to autouploader/gnu_autoupload.py
diff --git a/app/run.sh b/autouploader/run.sh
similarity index 100%
rename from app/run.sh
rename to autouploader/run.sh
diff --git a/app/weather.py b/autouploader/weather.py
similarity index 63%
rename from app/weather.py
rename to autouploader/weather.py
index f018dac..20c2b15 100644
--- a/app/weather.py
+++ b/autouploader/weather.py
@@ -1,7 +1,9 @@
-# weather.py
import requests
import json
import re
+import sqlite3
+import os
+import time
from datetime import datetime
from config import serviceKey, TODAY
@@ -36,6 +38,7 @@ def get_precipitation_summary(retry=True):
try:
data = response.json()
total_rainfall = 0.0
+ time_precip_list = []
lines = [
'
',
@@ -58,11 +61,17 @@ def get_precipitation_summary(retry=True):
time_str = f"{time[:2]}:{time[2:]}"
lines.append(f'
| {time_str} | {mm}mm |
')
total_rainfall += mm
+ time_precip_list.append((time_str, mm))
lines.append(f'
| 영업시간 중 총 예상 강수량: {total_rainfall:.1f}mm |
')
lines.append('
08:00 파주 조리읍 기상청 단기예보 기준
')
- return ''.join(lines)
+ html_summary = ''.join(lines)
+
+ # SQLite 저장 함수 호출
+ save_weather_to_sqlite(date=TODAY, time_precip_list=time_precip_list, total_rainfall=total_rainfall)
+
+ return html_summary
except json.decoder.JSONDecodeError:
if retry:
@@ -73,6 +82,45 @@ def get_precipitation_summary(retry=True):
print("응답이 JSON 형식이 아닙니다.")
return ''
+def save_weather_to_sqlite(date, time_precip_list, total_rainfall):
+ db_path = '/data/weather.sqlite'
+ os.makedirs(os.path.dirname(db_path), exist_ok=True)
+
+ conn = sqlite3.connect(db_path)
+ curs = conn.cursor()
+
+ # 테이블 생성 (없으면)
+ curs.execute('''
+ CREATE TABLE IF NOT EXISTS precipitation (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ date TEXT NOT NULL,
+ time TEXT NOT NULL,
+ rainfall REAL NOT NULL
+ )
+ ''')
+
+ curs.execute('''
+ CREATE TABLE IF NOT EXISTS precipitation_summary (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ date TEXT NOT NULL UNIQUE,
+ total_rainfall REAL NOT NULL
+ )
+ ''')
+
+ # 기존 데이터 삭제 (동일 날짜)
+ curs.execute('DELETE FROM precipitation WHERE date = ?', (date,))
+ curs.execute('DELETE FROM precipitation_summary WHERE date = ?', (date,))
+
+ # 데이터 삽입
+ curs.executemany('INSERT INTO precipitation (date, time, rainfall) VALUES (?, ?, ?)',
+ [(date, t, r) for t, r in time_precip_list])
+
+ curs.execute('INSERT INTO precipitation_summary (date, total_rainfall) VALUES (?, ?)', (date, total_rainfall))
+
+ conn.commit()
+ conn.close()
+ print(f"[DB 저장 완료] {date} 강수량 데이터 저장됨")
+
# 테스트용
if __name__ == "__main__":
print(get_precipitation_summary())
diff --git a/app/weather_capture.py b/autouploader/weather_capture.py
similarity index 100%
rename from app/weather_capture.py
rename to autouploader/weather_capture.py
diff --git a/build.yml b/build.yml
index d7beb10..8a055bf 100644
--- a/build.yml
+++ b/build.yml
@@ -1,10 +1,26 @@
services:
- fg-auto:
+ gnu-autouploader:
build:
- context: ./build
+ context: ./build/autouploader
dockerfile: Dockerfile
- image: reg.firstgarden.co.kr/fg-auto:latest
- container_name: fg-auto
+ image: reg.firstgarden.co.kr/gnu-autouploader:latest
+ container_name: gnu-autouploader
volumes:
- ./data:/data
+ - ./autouploader:/app
+ restart: unless-stopped
+
+ fg-webhook:
+ build:
+ context: ./build/webhook
+ dockerfile: Dockerfile
+ image: reg.firstgarden.co.kr/fg-webhook:latest
+ container_name: fg-webhook
+ volumes:
+ - ./data:/data
+ - ./webhook:/app
+ ports:
+ - 5000:5000
+ #environment:
+ # - DOMAIN=https://webhook.firstgarden.co.kr
restart: unless-stopped
diff --git a/build/Dockerfile-slim b/build/Dockerfile-slim
deleted file mode 100644
index 4465851..0000000
--- a/build/Dockerfile-slim
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM python:3.10-slim
-
-ENV LANG=ko_KR.UTF-8 \
- LANGUAGE=ko_KR:ko \
- LC_ALL=ko_KR.UTF-8 \
- TZ=Asia/Seoul \
- DEBIAN_FRONTEND=noninteractive
-
-# 필수 패키지 설치
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- locales tzdata bash cron curl unzip wget gnupg ca-certificates \
- xvfb x11-utils libglib2.0-0 libnss3 libgconf-2-4 libfontconfig1 \
- libxss1 libxshmfence1 libasound2 libxtst6 libappindicator3-1 \
- fonts-nanum libu2f-udev \
- libjpeg-dev zlib1g-dev && \
- sed -i '/ko_KR.UTF-8/s/^# //g' /etc/locale.gen && \
- locale-gen && \
- ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime && \
- ln -sf /usr/bin/python3 /usr/bin/python && \
- apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-
-# Chrome 설치
-RUN curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/google-linux-keyring.gpg && \
- echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-linux-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \
- > /etc/apt/sources.list.d/google-chrome.list && \
- apt-get update && \
- apt-get install -y google-chrome-stable && \
- rm -rf /var/lib/apt/lists/*
-
-# Python 패키지 설치
-RUN pip install --no-cache-dir \
- selenium>=4.10 \
- pymysql \
- ftputil \
- pillow \
- pyvirtualdisplay \
- requests
-
-# 작업 디렉토리 설정
-WORKDIR /data
-
-# 글꼴 캐시
-RUN fc-cache -f -v
-
-# 실행 스크립트 복사 및 실행 권한 부여
-COPY run.sh /data/run.sh
-RUN chmod +x /data/run.sh
-
-# crontab 직접 등록
-RUN echo "* * * * * /data/run.sh >> /proc/1/fd/1 2>&1" | crontab -
-
-# 크론 실행
-CMD ["bash", "-c", "cron -f"]
diff --git a/build/Dockerfile b/build/autouploader/Dockerfile
similarity index 89%
rename from build/Dockerfile
rename to build/autouploader/Dockerfile
index e709ca2..685c363 100644
--- a/build/Dockerfile
+++ b/build/autouploader/Dockerfile
@@ -29,14 +29,14 @@ RUN pip install --no-cache-dir \
requests
-WORKDIR /data
+WORKDIR /app
RUN fc-cache -f -v
-COPY run.sh /data/run.sh
-RUN chmod +x /data/run.sh
+COPY run.sh /app/run.sh
+RUN chmod +x /app/run.sh
# crontab 등록
-RUN echo "0 9 * * * /data/run.sh >> /proc/1/fd/1 2>&1" | crontab -
+RUN echo "0 9 * * * /app/run.sh >> /proc/1/fd/1 2>&1" | crontab -
CMD ["/bin/bash", "-c", "cron -f"]
diff --git a/build/run.sh b/build/autouploader/run.sh
similarity index 100%
rename from build/run.sh
rename to build/autouploader/run.sh
diff --git a/build/webhook/Dockerfile b/build/webhook/Dockerfile
new file mode 100644
index 0000000..5a43488
--- /dev/null
+++ b/build/webhook/Dockerfile
@@ -0,0 +1,30 @@
+# Dockerfile for webhook server (Ubuntu 22.04 + Python Flask)
+
+FROM ubuntu:22.04
+
+ENV DEBIAN_FRONTEND=noninteractive \
+ LANG=ko_KR.UTF-8 \
+ LANGUAGE=ko_KR:ko \
+ LC_ALL=ko_KR.UTF-8
+
+# 기본 패키지 설치 및 로케일 설정
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ locales tzdata python3 python3-pip curl ca-certificates && \
+ locale-gen ko_KR.UTF-8 && \
+ ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime && \
+ dpkg-reconfigure --frontend noninteractive tzdata && \
+ ln -sf /usr/bin/python3 /usr/bin/python && \
+ apt-get clean && rm -rf /var/lib/apt/lists/*
+
+# Flask 설치
+RUN pip3 install --no-cache-dir flask requests
+
+# 작업 디렉토리
+WORKDIR /app
+
+# 외부 접속 허용 포트
+EXPOSE 5000
+
+# Flask 앱 실행
+CMD ["python3", "webhook.py"]
diff --git a/data/weather.sqlite b/data/weather.sqlite
new file mode 100644
index 0000000..b189424
Binary files /dev/null and b/data/weather.sqlite differ
diff --git a/data/weather_capture_20250630.png b/data/weather_capture_20250630.png
new file mode 100644
index 0000000..d342362
Binary files /dev/null and b/data/weather_capture_20250630.png differ
diff --git a/docker-compose.yml b/docker-compose.yml
index 802437d..6eca8ee 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,7 +1,16 @@
services:
- fg-auto:
- image: reg.firstgarden.co.kr/fg-auto:latest
- container_name: fg-auto
+ gnu-autouploader:
+ image: reg.firstgarden.co.kr/gnu-autouploader:latest
+ container_name: gnu-autouploader
volumes:
- ./data:/data
+ - ./autouploader:/app
+ restart: unless-stopped
+
+ fg-webhook:
+ image: reg.firstgarden.co.kr/fg-webhook:latest
+ container_name: fg-webhook
+ volumes:
+ - ./data:/data
+ - ./webhook:/app
restart: unless-stopped
diff --git a/build-slim.yml b/webhook-build.yml
similarity index 51%
rename from build-slim.yml
rename to webhook-build.yml
index 79f3018..62da351 100644
--- a/build-slim.yml
+++ b/webhook-build.yml
@@ -2,9 +2,9 @@ services:
fg-auto:
build:
context: ./build
- dockerfile: Dockerfile-slim
- image: reg.firstgarden.co.kr/fg-auto:slim
- container_name: fg-auto
+ dockerfile: Dockerfile
+ image: reg.firstgarden.co.kr/fg-webhook:latest
+ container_name: fg-webhook
volumes:
- ./data:/data
restart: unless-stopped
diff --git a/webhook/webhook.py b/webhook/webhook.py
new file mode 100644
index 0000000..5eb22cb
--- /dev/null
+++ b/webhook/webhook.py
@@ -0,0 +1,75 @@
+import os
+from flask import Flask, request, jsonify
+import sqlite3
+from datetime import datetime
+
+app = Flask(__name__)
+
+DB_PATH = '/data/weather.sqlite'
+
+# 환경변수에서 DOMAIN 읽기, 없으면 기본값 지정 (로컬 테스트용)
+DOMAIN = os.getenv('DOMAIN', 'http://localhost:5000')
+
+def get_rain_data(date):
+ conn = sqlite3.connect(DB_PATH)
+ curs = conn.cursor()
+
+ curs.execute('SELECT time, rainfall FROM precipitation WHERE date = ? ORDER BY time', (date,))
+ time_rain_list = curs.fetchall()
+
+ curs.execute('SELECT total_rainfall FROM precipitation_summary WHERE date = ?', (date,))
+ row = curs.fetchone()
+ total_rainfall = row[0] if row else 0.0
+
+ conn.close()
+ return time_rain_list, total_rainfall
+
+@app.route('/webhook', methods=['POST'])
+def webhook():
+ today = datetime.today().strftime('%Y%m%d')
+ response_text = ""
+
+ try:
+ time_rain_list, total_rainfall = get_rain_data(today)
+
+ if not time_rain_list:
+ response_text = f"{today} 날짜의 강수량 데이터가 없습니다."
+ else:
+ lines = []
+ for time_str, rain in time_rain_list:
+ rain_display = f"{rain}mm" if rain > 0 else "강수 없음"
+ lines.append(f"{time_str} → {rain_display}")
+
+ lines.append(f"\n영업시간 내 총 강수량은 {total_rainfall:.1f}mm 입니다.")
+ response_text = '\n'.join(lines)
+
+ except Exception as e:
+ response_text = f"데이터 조회 중 오류가 발생했습니다: {e}"
+
+ image_filename = f"weather_capture_{today}.png"
+ image_path = f"/data/{image_filename}"
+
+ outputs = [{
+ "simpleText": {
+ "text": response_text
+ }
+ }]
+
+ if os.path.isfile(image_path):
+ image_url = f"{DOMAIN}/data/{image_filename}"
+ outputs.append({
+ "image": {
+ "imageUrl": image_url,
+ "altText": "오늘의 날씨 캡처 이미지"
+ }
+ })
+
+ return jsonify({
+ "version": "2.0",
+ "template": {
+ "outputs": outputs
+ }
+ })
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=5000)