import sys  # 시스템 관련 기능을 제공하는 모듈
from PyQt5 import QtCore, QtGui, QtWidgets  # PyQt5 라이브러리에서 QtCore, QtGui, QtWidgets 모듈을 가져옴
import requests  # HTTP 요청을 보내고 응답을 받기 위한 라이브러리
import time  # 시간 관련 기능을 제공하는 모듈
import webbrowser  # 웹 브라우저를 제어하는 모듈
import datetime  # 날짜와 시간을 다루기 위한 모듈
from threading import Thread, Event  # 쓰레드 기능과 이벤트 처리를 위한 모듈
import os  # 운영 체제와 상호작용하는 기능을 제공하는 모듈

# 프로그램의 설정값
Title = "ㅇㅇㅇ 대기방"  # 프로그램 제목창에 표시될 이름
channel_id = "458f6ec20b034f49e0fc6d03921646d2"  # 스트리머 채널의 ID
background = "background.png"  # 배경 이미지 파일 이름 (720x540 크기, 4:3 비율)

# 배경 이미지 파일은 이 코드파일(knockknock.py)와 동일한 경로에 있어야 함.
# PyInstaller를 통해 EXE 파일로 만들 때 다음과 같은 형식으로 추가할 수 있음:
# pyinstaller --onefile --windowed --add-data "background.png;." knockknock.py

# 방송 대기 프로그램의 핵심 기능을 수행하는 Worker 클래스
class Worker(Thread):
    def __init__(self, channel_id, refresh, text_edit):
        super().__init__()  # Thread 클래스의 초기화
        self.channel_id = channel_id  # 채널 ID 설정
        self.refresh = refresh  # 새로 고침 주기 설정
        self.text_edit = text_edit  # 결과를 표시할 QTextEdit 객체
        self._stop_event = Event()  # 스레드 종료를 위한 이벤트 객체

    def run(self):
        # 스레드가 실행되는 동안 계속 반복
        while not self._stop_event.is_set():
            try:
                headers = {'User-Agent': 'Mozilla/5.0'}  # 봇으로 인식되지 않게 하기 위한 헤더
                request = requests.get(f"https://[Log in to view URL]", headers=headers)  # API 요청
                channel_info = request.json().get("content")  # JSON 형식으로 응답을 파싱

                open_live = channel_info.get("openLive")  # 방송 여부 확인
                channel_name = channel_info.get("channelName")  # 채널 이름 정보

                if open_live:  # 방송 중인 경우
                    self.text_edit.append(f"{channel_name} 방송이 켜졌습니다! 10초 후에 접속합니다...")
                    for i in range(10, 0, -1):  # 10초 카운트 다운
                        if self._stop_event.is_set():  # 스레드가 종료 요청된 경우
                            return
                        self.text_edit.append(f"{channel_name} 방송이 켜졌습니다! {i}초 남았습니다...")
                        time.sleep(1)  # 1초 대기
                    webbrowser.open(f"https://[Log in to view URL]", new=0)  # 방송 링크 열기
                    return

                # 방송이 아닐 경우
                date = datetime.datetime.today().strftime('%H:%M:%S')  # 현재 시간 가져오기
                self.text_edit.append(f'[{date}] {channel_name} 방송 대기중, {self.refresh}초 후 다시 확인합니다...')
                time.sleep(self.refresh)  # 새로 고침 주기만큼 대기

            except requests.exceptions.RequestException as e:  # 요청 예외 처리
                self.text_edit.append(f"오류 발생: {e}")

    def stop(self):
        self._stop_event.set()  # 스레드 종료 요청

# GUI 관련 코드
class Ui_Form(object):
    def __init__(self):
        self.worker = None  # Worker 객체 초기화

    def setupUi(self, Form):
        Form.setObjectName('Form')  # 폼 객체 이름 설정
        Form.resize(780, 640)  # 폼 크기 설정

        # START 버튼 UI 설정
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(30, 20, 75, 23))  # 버튼 위치 및 크기 설정
        self.pushButton.setObjectName("pushButton")  # 버튼 이름 설정
        self.pushButton.clicked.connect(self.start_checking)  # 버튼 클릭 시 start_checking 메서드 연결

        # STOP 버튼 UI 설정
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(675, 20, 75, 23))  # 버튼 위치 및 크기 설정
        self.pushButton_2.setObjectName("pushButton_2")  # 버튼 이름 설정
        self.pushButton_2.clicked.connect(self.stop_program)  # 버튼 클릭 시 stop_program 메서드 연결

        # 결과가 출력될 UI 설정
        self.background_label = QtWidgets.QLabel(Form)
        self.background_label.setGeometry(QtCore.QRect(30, 70, 720, 540))  # 레이블 위치 및 크기 설정

        # 배경 이미지를 QLabel에 설정
        image_path = os.path.join(os.path.dirname(__file__), background)  # 현재 디렉토리의 이미지 경로
        self.background_pixmap = QtGui.QPixmap(image_path)  # 이미지 로드
        self.background_label.setPixmap(self.background_pixmap)  # QLabel에 배경 이미지 설정
        self.background_label.setScaledContents(True)  # QLabel 크기에 맞게 이미지 비율 조절

        # 결과 출력창에 대한 설정
        self.textEdit = QtWidgets.QTextEdit(Form)  # QTextEdit 객체 생성
        self.textEdit.setGeometry(QtCore.QRect(30, 70, 720, 540))  # 텍스트 편집기 위치 및 크기 설정
        # 스타일 시트 수정: 글자 크기, 색상, 굵기, 배경 투명화
        self.textEdit.setStyleSheet("color: black; font-size: 12px; font-weight: bold; "
                                     "background: transparent; padding: 5px; "
                                     "border: none;")  # 테두리 없음
        self.textEdit.setReadOnly(True)  # 텍스트 편집기를 읽기 전용으로 설정

        self.retranslateUi(Form)  # UI 텍스트 번역 설정
        QtCore.QMetaObject.connectSlotsByName(Form)  # 슬롯과 신호 연결

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate  # 텍스트 변환 함수
        Form.setWindowTitle(_translate("Form", Title))  # 창 제목 설정
        self.pushButton.setText(_translate("Form", "Start"))  # START 버튼 텍스트 설정
        self.pushButton_2.setText(_translate("Form", "Stop"))  # STOP 버튼 텍스트 설정

    # 방송 확인 새로 고침 주기 설정
    def start_checking(self):
        if self.worker is None:  # Worker가 None인 경우 (즉, 실행 중이지 않은 경우)
            refresh = 5  # 새로 고침 주기 (5초)
            self.worker = Worker(channel_id, refresh, self.textEdit)  # Worker 객체 생성
            self.worker.start()  # Worker 스레드 시작

    # 프로그램 정지 버튼 기능
    def stop_program(self):
        if self.worker is not None:  # Worker가 실행 중인 경우
            self.worker.stop()  # Worker 종료 요청
            self.worker.join()  # Worker 스레드 종료 대기
            self.worker = None  # Worker 객체 초기화
            self.textEdit.append("프로그램이 정지되었습니다.")  # 정지 메시지 출력

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)  # QApplication 객체 생성
    Form = QtWidgets.QWidget()  # QWidget 객체 생성
    ui = Ui_Form()  # Ui_Form 객체 생성
    ui.setupUi(Form)  # UI 설정
    Form.show()  # 폼을 화면에 표시
    sys.exit(app.exec_())  # 애플리케이션 실행

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: