import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import requests
import time
import webbrowser
import datetime
from threading import Thread, Event
# 프로그램의 창 제목
Title = "치지직 단체 대기방"
# 실제로 방송이 켜져 있는지 확인하는 역할을 하는 Worker 클래스 정의
class Worker(Thread):
def __init__(self, channel_ids, refresh, text_edit):
super().__init__()
self.channel_ids = channel_ids # 입력받은 여러 개의 채널 ID 리스트
self.refresh = refresh # 갱신 간격(초)
self.text_edit = text_edit # 출력창(QTextEdit)에 로그를 출력하기 위한 객체
self._stop_event = Event() # 스레드를 멈추기 위한 이벤트 플래그
def run(self):
# 스레드를 실행하는 메인 로직
while not self._stop_event.is_set(): # stop() 메서드가 호출되지 않은 동안 반복 실행
for channel_id in self.channel_ids[:]: # 채널 ID 리스트를 순회하며 방송 상태 확인
try:
# 헤더 정보 정의 (웹사이트에 접근할 때 사용자 에이전트 정보 제공)
headers = {'User-Agent': 'Mozilla/5.0'}
# API를 통해 방송 정보 요청
request = requests.get(f"https://[Log in to view URL]", headers=headers)
# API 요청이 실패한 경우 상태 코드 출력
if request.status_code != 200:
self.update_text(f"채널 {channel_id}에 대한 요청이 실패했습니다. 상태 코드: {request.status_code}")
continue
# 응답받은 JSON 데이터에서 방송 정보 추출
channel_info = request.json().get("content")
# 잘못된 채널 ID이거나 정보가 누락된 경우 처리
if channel_info is None or channel_info.get("channelId") is None:
self.update_text(f"{channel_id} - 존재하지 않는 채널 ID입니다.")
self.channel_ids.remove(channel_id) # 잘못된 채널 ID는 리스트에서 제거
continue # 다음 채널 확인
# 방송 상태 및 채널 이름 정보 추출
open_live = channel_info.get("openLive") # 방송 켰는지 확인
channel_name = channel_info.get("channelName") # 채널 이름 정보 가져오기
# 방송이 켜진 경우
if open_live:
self.update_text(f"{channel_name} 방송이 켜졌습니다! 10초 후에 접속합니다...")
# 10초 동안 카운트다운 후 웹브라우저로 방송 페이지 열기
for i in range(10, 0, -1):
if self._stop_event.is_set(): # 스레드 중지 요청이 있으면 종료
return
self.update_text(f"{i}초 남았습니다...")
time.sleep(1)
# 방송 URL을 웹브라우저에서 엽니다.
webbrowser.open(f"https://[Log in to view URL]", new=0)
self.channel_ids.remove(channel_id) # 방송이 켜진 채널은 리스트에서 제거
# 방송이 켜지지 않은 경우 로그 기록
date = datetime.datetime.today().strftime('%H:%M:%S')
self.update_text(f'[{date}] {channel_name} 방송 대기중...')
# 네트워크 요청에서 발생한 예외 처리
except requests.exceptions.RequestException as e:
self.update_text(f"오류 발생: {e}")
# 예상하지 못한 예외 처리
except Exception as e:
self.update_text(f"예상치 못한 오류 발생: {e}")
# 모든 채널 확인 후 설정한 시간만큼 대기 후 다시 확인
self.update_text(f"모든 채널을 확인했습니다. {self.refresh}초 후에 다시 확인합니다...\n")
time.sleep(self.refresh)
# 스레드를 중지하는 메서드
def stop(self):
self._stop_event.set()
# QTextEdit에 메시지를 안전하게 추가하는 메서드
def update_text(self, message):
QtCore.QMetaObject.invokeMethod(self.text_edit, "append", QtCore.Qt.QueuedConnection, QtCore.Q_ARG(str, message))
# UI를 구성하는 클래스 정의
class Ui_Form(object):
def setupUi(self, Form):
# 창 설정
Form.setObjectName("Form")
Form.resize(721, 321)
# 시작 버튼
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(30, 20, 75, 23))
self.pushButton.setObjectName("pushButton")
# 로그 출력 창
self.textEdit = QtWidgets.QTextEdit(Form)
self.textEdit.setGeometry(QtCore.QRect(30, 150, 661, 171))
self.textEdit.setObjectName("textEdit")
# 정지 버튼
self.pushButton_2 = QtWidgets.QPushButton(Form)
self.pushButton_2.setGeometry(QtCore.QRect(620, 20, 75, 23))
self.pushButton_2.setObjectName("pushButton_2")
# 채널 ID 입력창
self.lineEdit = QtWidgets.QLineEdit(Form)
self.lineEdit.setGeometry(QtCore.QRect(30, 50, 661, 23))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit.setPlaceholderText("채널 ID를 쉼표로 구분하여 입력하세요 (예: 1234, 5678)") # 안내 문구 추가
# 갱신 간격 입력창
self.lineEdit_2 = QtWidgets.QLineEdit(Form)
self.lineEdit_2.setGeometry(QtCore.QRect(30, 90, 661, 23))
self.lineEdit_2.setObjectName("lineEdit_2")
self.lineEdit_2.setPlaceholderText("갱신 간격(초)를 입력하세요 (기본: 5초)") # 안내 문구 추가
# UI 요소와 텍스트 설정
self.retranslateUi(Form)
# 버튼과 함수 연결
QtCore.QMetaObject.connectSlotsByName(Form)
# 버튼을 클릭할 때 실행할 함수 연결
self.pushButton.clicked.connect(self.start_checking) # 시작 버튼 클릭 시 호출
self.pushButton_2.clicked.connect(self.stop_program) # 정지 버튼 클릭 시 호출
# Worker 스레드 초기화
self.worker = None
# UI에 텍스트를 설정하는 함수
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", Title)) # 창 제목 설정
self.pushButton.setText(_translate("Form", "Start")) # 시작 버튼 텍스트 설정
self.pushButton_2.setText(_translate("Form", "Stop")) # 정지 버튼 텍스트 설정
# 방송 확인을 시작하는 함수
def start_checking(self):
if self.worker is None: # Worker 스레드가 실행 중이 아닌 경우
channel_ids = self.lineEdit.text().split(",") # 쉼표로 구분된 채널 ID 입력값을 리스트로 변환
channel_ids = [channel_id.strip() for channel_id in channel_ids] # 공백 제거
try:
# 사용자가 입력한 갱신 간격이 숫자인지 확인
refresh = int(self.lineEdit_2.text()) if self.lineEdit_2.text() else 5 # 입력값이 없으면 기본값 5초
except ValueError:
self.textEdit.append("유효하지 않은 갱신 간격 값입니다. 숫자를 입력하세요.")
return
# Worker 스레드를 생성하고 시작
self.worker = Worker(channel_ids, refresh, self.textEdit)
self.worker.start() # 스레드 실행
else:
self.textEdit.append("이미 확인 중입니다.") # 이미 실행 중인 경우 로그 메시지 출력
# 프로그램을 정지하는 함수
def stop_program(self):
if self.worker is not None:
self.worker.stop() # Worker 스레드 정지
self.worker.join() # 스레드가 종료될 때까지 대기
self.worker = None # Worker 객체 초기화
self.textEdit.append("프로그램이 정지되었습니다.") # 정지 로그 출력
# 프로그램의 메인 실행 코드
if __name__ == "__main__":
# PyQt5 애플리케이션을 실행하는 부분
app = QtWidgets.QApplication(sys.argv) # QApplication 객체 생성
Form = QtWidgets.QWidget() # QWidget으로 UI 창 생성
ui = Ui_Form()
ui.setupUi(Form) # UI 설정
Form.show() # 창 표시
sys.exit(app.exec_()) # 애플리케이션 종료
# Worker 클래스: 스레드로 채널의 방송 상태를 주기적으로 확인하는 기능을 수행.
#
# run 메서드: 실제로 API 요청을 통해 방송 상태를 확인하고, 방송이 켜져 있으면 웹브라우저를 통해 해당 채널로 접속.
# stop 메서드: 스레드를 안전하게 중지하는 기능.
# update_text 메서드: 텍스트 출력 창에 메시지를 추가하는 함수.
# Ui_Form 클래스: 프로그램의 UI를 설정하고, 버튼을 통해 방송 확인을 시작하거나 정지할 수 있도록 연결.
#
# start_checking 메서드: 채널 ID와 갱신 간격을 입력받아 방송 상태 확인을 시작.
# stop_program 메서드: 방송 상태 확인을 중지.
# 메인 실행 코드: PyQt5 애플리케이션을 시작하고 창을 띄우는 코드.
To embed this project on your website, copy the following code and paste it into your website's HTML: