친구랑 캠핑은 싫고 고기는 구워먹고 싶어서 바베큐장을 알아보는데 인기많고 저렴한 곳을 알게되었다.. 저렴해서 그런가 10월 예약이 꽉차있어 취소표 노리고 있는데 아무리 새로고침을 해도 취소표가 안풀리는거임...
바쁜 내가 이걸 계속 새로고침하면서 취소표를 기다릴 수도 없는 노릇..! 취소표가 생겨 예약이 활성화되면 핸드폰으로 알람이 오는 그런 프로그램을 만들고 싶다는 의욕이 갑자기 생겨버렸다.
참고로 악용될 여지가 있기 때문에 정확한 소스 제공은 없다.
아무런 기초 지식이 없어 일단 chatGPT 스승님께 질문!
프로젝트 생성
spring boot로 하려다가 스승님한테 물어보니 스프링부트 없이 java만을 사용하여 구현할 수 있다해서 java 프로젝트를 생성했다. 프로젝트 이름은 'cancelAlarm'으로 결정!
gradle을 사용하기 위해 gradle 관련 파일을 추가했다.
build.gradle과 settings.gradle 추가하고 안에 알맞은 내용 추가 후 인텔리제이 우측 하단에 알람이 뜬다. Load Gradle Project 버튼을 누르면 그레이들 리프레시하면 그레이들을 사용할 수 있게된다.
그다음 build.gradle에 dependency를 추가한다.
implementation 'org.jsoup:jsoup:1.18.1'
HTML 파싱을 위한 JSOUP을 추가한다.
Tomcat 추가
나는 버전 10으로 추가했다. 톰캣 추가하는 방법은 인터넷에 나오니 여기선 스킵!
개발
준비물 : HTML 파싱 대상의 URL, 슬랙 아이디
먼저 HTML을 파싱하고 원하는 요소가 있는지 확인하는 코드를 작성한다.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
try {
Document doc = Jsoup.connect(URLS).get();
//예약 상태 체크
boolean isAvailable = checkAvailability(doc);
System.out.println("isAvailable = " + isAvailable);
System.out.println(LocalDateTime.now());
if (isAvailable) {
sendNotification();
}
} catch(....)
{}
}, 0, 3, TimeUnit.MINUTES); //3분마다 확인
}
스레드를 하나 만들고 3분마다 주기적으로 실행하게 한다.
checkAvailability() 함수는 Document 객체 내에서 원하는 CSS 선택자를 가진 요소의 text를 읽어 원하는 문자가 있는지 검사한다.
즉, 예약 가능이라는 텍스트를 포함한 객체가 있으면 true, 없으면 false 반환
private static boolean checkAvailability(Document doc) {
// 특정 요소를 찾아 예약 가능 여부 반환
return doc.select("CSS 선택자").text().contains("예약가능");
}
선택자는 개발자 도구를 이용하면 좀 편하게 가져올 수 있다.
개발자 도구에서 요소 우클릭 > Copy > Copy selector
슬랙 봇을 만들어야하는데 슬랙 봇 만드는 방법은 쉽고 인터넷에 많이 있으니 참고하여 설정하면 된다.
webhook api를 보내기 위해 HTTP Method와 Content-Type, DoOutput 설정을 해준다.
Slack에서 제공하는 라이브러리를 사용하면 더 쉽게 될 거 같은데 일단 내 컴퓨터에서는 Slack slack = Slack.getInstance();에서 오류가 발생해 Slack 라이브러리 없이 API를 요청했다. (이부분은 나중에 원인을 좀 더 찾아보고 추가 작성하겠다.)
private static void sendNotification() {
// 슬랙 봇으로 알람 쏘기
try {
URL slackUrl = new URL("webhook url");
HttpURLConnection connection = (HttpURLConnection) slackUrl.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
String message = "10월 취소표 알람";
String jsonPayload = "{\"text\": \"" + message + "\"}";
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonPayload.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
}
catch (Exception e) {
e.printStackTrace();
}
}
스레드 주기를 1분으로 설정하고 테스트해보면 잘 돌아가는 걸 볼 수 있다.
여담
핸드폰 슬랙 어플에서 푸시 알람이 안와서 이거 해결하느라 엄청 고생했다..... 개발 시간의 거의 90프로를 잡아먹음.
메시지는 작성이 되는데 계속 푸시 알람이 안와서 개발이 뭔가 잘못됐나 싶어 이리 뒤집어보고 저리 뒤집어 봤는데 결국 어플 설정에서 원인을 찾을 수 있었다.
마이페이지 > 알림 > 알림 일정 > 종료 시간 설정
알림 종료 시간이 너무 이르게 설정되어있어서.. 핸드폰 푸시 알람이 안되었던 것이다.. . . 다들 앱 설정 확인 꼼꼼히 하시길..!
오늘의 삽질도 참 대견했다.