Skip to content

Latest commit

 

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ojm-bot

마곡 인근 식당 3곳의 오늘 점심 메뉴를 평일 오전 10시 30분(KST)에 슬랙 오늘-점심-모묵지 채널로 자동 전송한다. 메시지 1개 + 3곳을 합친 이미지 1장.

식당 출처 뽑는 방식
밥플러스 마곡디어반 카카오 채널 _HGxjan 날짜 매칭 후 중식 메뉴판을 이미지 판독으로 선별
사랑해밥상 마곡 카카오 채널 _xerxkxen 주간 식단표에서 오늘 요일 칸만 잘라냄
밥짓는부엌 네이버 플레이스 소식 1578060862 하루 1장, 중식/석식 구분 없음

한 곳이 실패해도 나머지는 보낸다. 실패한 곳은 코멘트에 안내 한 줄로 남는다. 3곳이 한 이미지에 섞이므로 각각에 식당명 + 날짜 띠와 테두리를 구워 카드로 만든다 (슬랙 렌더링·모바일 알림 미리보기에 의존하지 않고 출처가 따라붙게). 띠 높이·글자 크기는 원본 해상도와 무관하게 동일하다.

왜 이미지를 한 장으로 합치나

슬랙에 이미지를 여러 장 붙이면 공통 비율로 가운데만 남기고 잘라낸다 — 실제로 사랑해밥상은 띠와 드레싱 줄이, 밥짓는부엌은 좌우 열이 날아갔다. 카드 비율을 맞춰도 슬랙 타일 비율에 다시 맞춰 자르므로, 아예 한 장으로 합쳐 타일링 자체를 없앤다.

배치는 세로로 긴 카드는 두 장씩 나란히, 가로로 넓은 카드는 한 줄을 통째로 쓴다. 밥짓는부엌처럼 가로형 2단 메뉴판을 절반 폭에 넣으면 글씨가 읽을 수 없게 작아지기 때문이다 (같은 폭으로 3분할하면 내용 배율 0.23배 → 한 줄을 다 주면 0.68배). 짝이 없어 세로형 카드가 혼자 한 줄을 쓰게 되면 폭을 62%로 제한해 이미지가 쓸데없이 길어지지 않게 한다.

동작

  1. 주말이거나 한국 공휴일(holidays 라이브러리, 대체·임시공휴일 포함)이면 전송 생략 (예약 실행은 val.town cron이 평일만 트리거하지만, Actions 탭의 수동 Run workflow는 그 스케줄을 안 타므로 봇 코드에서도 막는다)
  2. 식당 3곳을 각각 수집 → 성공한 것만 카드로 만들어 한 메시지에 묶어 업로드
  3. 이미지는 파일 업로드 방식 (image block 핫링크는 카카오/네이버 CDN을 슬랙이 못 가져와 불안정)

밥플러스

제목에 오늘 날짜(M/D)가 포함된 게시물을 찾고, 그 게시물들의 이미지를 모아 OCR·테마색·뱃지 점수가 가장 높은 것을 중식 메뉴판으로 고른다 (중식 가산 / 석식·미운영 감점, 음식 사진 제외). 전송은 고화질(xlarge)로.

사랑해밥상 — 주간 식단표에서 오늘 칸 크롭

  1. 게시 시각으로 이번 주 표를 찾는다. published_at이 속한 주의 월요일 = 표의 시작일 (과거 25주 전부 일치). 표 안 날짜 글자를 읽는 것보다 확실하다.
  2. 픽셀 밝기로 격자선을 검출한다. 세로선이 정확히 6개(=요일 5칸)일 때만 표로 인정하므로 이 검출이 '주간 식단표인가' 판별기를 겸한다(공지·이벤트·일일메뉴는 여기서 걸러진다). 가로선은 라벨열까지 통째로 가로지르는 것만 센다 — 샐러드바 내부 잔선을 세면 행 개수가 이미지마다 6~9개로 흔들려 자를 위치를 못 잡는다.
  3. date.today().weekday()를 열 인덱스로 써서 라벨열 + 오늘 요일열을 이어붙인다. 석식행이 요일별로 나뉘어 있으면 포함하고, 석식은 운영하지 않습니다 통짜 배너면 잘라낸다.
  4. 안전핀으로 그 칸의 날짜를 OCR해 7일 이상 어긋나면 크롭을 포기하고 원본 통짜를 보낸다. 판단이 아니라 거부권만 갖는다 — 못 읽거나 달력에 없는 값이면 그냥 통과. (과거 25주 125칸 측정: 유효한 날짜인데 7일 이상 틀린 오독 0건, ±1일 오독 5건)

격자 검출 실패·거부권 발동 시엔 원본 식단표 전체를 보낸다. 조용히 틀린 날 메뉴를 보내지 않는다.

밥짓는부엌

소식 피드가 SSR HTML 안 __APOLLO_STATE__에 통째로 들어있어 별도 API가 필요 없다. 제목이 오늘의 메뉴처럼 날짜가 빠지는 날이 있어 createdString(YYYYMMDD)으로 맞춘다. 하루에 메뉴판과 홍보글이 같이 올라오면 제목에 날짜가 박힌 쪽을 집는다. 네이버는 UA만 있는 요청을 429로 막으므로 Accept-Language·Referer까지 보낸다.

테스트

DRY_RUN=1 python3 lunch_bot.py   # 슬랙 전송 없이 ./dryrun/lunch.png 로 합친 이미지 저장
python3 test_lunch_bot.py        # 격자 검출·요일 열 선택 자체 점검 (네트워크 불필요)

실행

  • 자동: 외부 스케줄러(val.town)가 평일 10:30 KSTworkflow_dispatch로 트리거 (관리자가 매일 오전 11시경 게시물을 수정하는 것과 겹쳐 메뉴판이 잠시 빠졌다 나타나는 시간대를 피하기 위함)
    • 같은 날 여러 번 실행돼도 GitHub Actions 캐시 마커로 중복 전송을 방지한다
  • 수동: Actions 탭 → "오늘 점심 모묵지 알림" → Run workflow

한 식당만 다시 보내기 (ONLY)

세 곳 중 한 곳만 실패한 날, 그 한 곳만 따로 보낼 때 쓴다. 그냥 재실행하면 이미 나간 나머지 두 곳까지 중복 전송된다.

  1. 오늘 전송 마커 캐시를 지운다 (안 지우면 조용히 스킵된다)
    gh cache delete lunch-sent-$(TZ=Asia/Seoul date +%F)
  2. Actions 탭 → Run workflow → "이 식당만 전송" 에서 식당을 고른다 (비우면 전체)

CLI로는 이렇게:

gh workflow run lunch.yml -f only=밥짓는부엌

로컬 확인은 ONLY 환경변수로:

DRY_RUN=1 ONLY=밥짓는부엌 python3 lunch_bot.py

식당명은 SOURCES 표시 이름과 정확히 같아야 한다 (밥플러스·사랑해밥상·밥짓는부엌).

설정 (Secrets)

이름 설명
SLACK_BOT_TOKEN 슬랙 봇 토큰 xoxb-... (스코프: files:write, chat:write)
SLACK_CHANNEL_ID 전송할 채널 ID (예: C0BDDENKY3B = 오늘-점심-모묵지)

봇은 대상 채널에 멤버여야 한다 (/invite @오늘 점심 모묵지 봇). 밥플러스 카카오 채널을 바꾸려면 CHANNEL_ID 환경변수(기본 _HGxjan)를 워크플로우에 추가한다.

카드에 한글을 쓰려면 러너에 한글 폰트가 있어야 한다 (워크플로우에서 fonts-nanum 설치). 폰트를 못 찾으면 카드 렌더를 건너뛰고 원본 이미지를 그대로 보낸다 — 메뉴는 나가야 하므로.

About

밥플러스 마곡디어반점, 사랑해밥상, 밥짓는부엌의 점심 메뉴판 이미지를 슬랙 채널 `오늘-점심-모묵지`으로 전송하는 작업을 위한 레포입니다.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages