summaryrefslogtreecommitdiff
path: root/9kwpyqt.py
diff options
context:
space:
mode:
Diffstat (limited to '9kwpyqt.py')
-rwxr-xr-x9kwpyqt.py330
1 files changed, 330 insertions, 0 deletions
diff --git a/9kwpyqt.py b/9kwpyqt.py
new file mode 100755
index 0000000..9acf9eb
--- /dev/null
+++ b/9kwpyqt.py
@@ -0,0 +1,330 @@
+#!/usr/bin/env python3
+
+import random
+import sys
+import time
+from PyQt5.QtCore import Qt, QTimer, QUrl
+from PyQt5.QtWidgets import QApplication, QWidget
+from PyQt5.QtWidgets import QLayout, QHBoxLayout, QVBoxLayout, QSizePolicy
+from PyQt5.QtWidgets import QLabel, QLineEdit, QPushButton, QProgressBar
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtMultimedia import QSound
+from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
+
+API_URL = "http://www.9kw.eu/index.cgi"
+API_KEY = ""
+soundfile = "notify.wav"
+
+
+class CaptchaGUI(QWidget):
+ sound = False # QSound()
+ image = False # QImage()
+ imageR = False # QImage() resized
+ timer = False # QTimer() for 30sec timing
+
+ running = False
+ startCredits = None
+ currentCredits = 0
+ currentCaptchaID = None
+ currentCommited = 0
+ currentSkipped = 0
+ currentQueued = 0
+ apiurl = API_URL+"?source=pythonapi&apikey="+API_KEY+"&"
+ offlinemessage = "Click \"Start\" to fetch next captcha."
+
+ def __init__(self, parent=None):
+ super(CaptchaGUI, self).__init__(parent)
+ self.setMinimumWidth(400)
+
+ # Top: Credits and Stats
+ self.accountLabel = QLabel("credits")
+ self.accountLabel.setAlignment(Qt.AlignLeft)
+ # self.timerLabel = QLabel("30 Sek")
+ # self.timerLabel.setAlignment(Qt.AlignCenter)
+ # self.timerProgress = QProgressBar()
+ # self.timerProgress.setRange(0,30)
+ # self.timerProgress.setValue(23.65)
+ # self.timerProgress.setTextVisible(True)
+ # self.timerProgress.text = "Bla und so"
+
+ self.statsLabel = QLabel("online stats")
+ self.statsLabel.setAlignment(Qt.AlignRight)
+
+ # self.timerLabel.setStyleSheet("QLabel { color: darkred; }")
+ # self.timerLabel.setStyleSheet("QLabel { background-color: gray; }")
+
+ self.LayoutStats = QHBoxLayout()
+ self.LayoutStats.addWidget(self.accountLabel)
+ # self.LayoutStats.addWidget(self.timerLabel)
+ # self.LayoutStats.addWidget(self.timerProgress)
+ self.LayoutStats.addWidget(self.statsLabel)
+ self.LayoutStats.sizeConstraint = QLayout.SetMinimumSize
+
+ # Middle: Captchaimage
+ # self.captchaLabel = QLabel("Captcha:")
+ self.captchaImage = QLabel("")
+ self.captchaImage.setAlignment(Qt.AlignCenter)
+ self.captchaImage.setMinimumHeight(400)
+ self.captchaImage.setSizePolicy(
+ QSizePolicy.MinimumExpanding,
+ QSizePolicy.MinimumExpanding
+ )
+
+ self.captchaBox = QHBoxLayout()
+ # self.captchaBox.addWidget(self.captchaLabel)
+ self.captchaBox.addWidget(self.captchaImage)
+
+ # Bottom: Input + Submit/Skip-Buttons
+ self.captchaInputLine = QLineEdit()
+ self.startstopButton = QPushButton("Start")
+ self.startstopButton.setCheckable(True)
+ self.submitButton = QPushButton("&Submit")
+ self.skipButton = QPushButton("S&kip")
+ self.startstopButton.clicked.connect(self.toggleRunning)
+ self.submitButton.clicked.connect(self.submitCaptcha)
+ self.skipButton.clicked.connect(self.skipCaptcha)
+
+ self.LayoutSubmitLine = QHBoxLayout()
+ self.LayoutSubmitLine.addWidget(self.startstopButton)
+ self.LayoutSubmitLine.addWidget(self.captchaInputLine)
+
+ self.LayoutSubmitButtons = QHBoxLayout()
+ self.LayoutSubmitButtons.addWidget(self.submitButton)
+ self.LayoutSubmitButtons.addWidget(self.skipButton)
+
+ self.LayoutSubmit = QVBoxLayout()
+ self.LayoutSubmit.addLayout(self.LayoutSubmitLine)
+ self.LayoutSubmit.addLayout(self.LayoutSubmitButtons)
+
+ # Compile layout
+ mainLayout = QVBoxLayout()
+ mainLayout.addLayout(self.LayoutStats)
+ mainLayout.addLayout(self.captchaBox)
+ mainLayout.addLayout(self.LayoutSubmit)
+ self.setLayout(mainLayout)
+ self.setWindowTitle("Captcha 9kw PyQt")
+
+ # load soundfile
+ self.sound = QSound(soundfile)
+
+ # Initialize network
+ self.NetworkManager = QNetworkAccessManager()
+ QTimer.singleShot(500, self.getCredits)
+ QTimer.singleShot(500, self.getQueue)
+ QTimer.singleShot(500, self.getCaptchaID)
+
+ self.timer = QTimer()
+ self.timer.timeout.connect(self.onTimeout)
+ self.timer.setSingleShot(True)
+
+ ##################################################
+ # Handle gui
+ ##################################################
+ def resizeEvent(self, evt=None):
+ if self.image:
+ self.imageR = self.image.scaled(self.captchaImage.size(),
+ Qt.KeepAspectRatio)
+ self.captchaImage.setPixmap(self.imageR)
+
+ def updateStats(self):
+ if self.startCredits:
+ credittext = "%d ¥ (%s%d)" % (self.currentCredits, (self.currentCredits - self.startCredits > 0) and '+' or '', (self.currentCredits - self.startCredits))
+ else:
+ credittext = "%d ¥" % (self.currentCredits)
+ self.accountLabel.setText(credittext)
+ labeltext = "%d Commited | %d Skipped | %d in Queue" % (self.currentCommited, self.currentSkipped, self.currentQueued)
+ self.statsLabel.setText(labeltext)
+
+ def keyPressEvent(self, event):
+ key = event.key()
+ if key == Qt.Key_Escape:
+ self.skipCaptcha()
+ elif key == Qt.Key_Enter or key == Qt.Key_Return:
+ if self.skipButton.hasFocus():
+ self.skipCaptcha()
+ else:
+ self.submitCaptcha()
+
+ def setCaptchaImage(self, image=None):
+ pixmap = QPixmap()
+ result = pixmap.loadFromData(image)
+ if result:
+ self.image = pixmap
+ self.imageR = self.image.scaled(self.captchaImage.size(),
+ Qt.KeepAspectRatio)
+ self.captchaImage.setPixmap(self.imageR)
+ self.captchaInputLine.setFocus()
+ self.sound.play()
+ self.timer.start(30000)
+ self.captchaImage.setText("")
+ else:
+ self.captchaImage.setText("Could not display image. Skip!")
+ self.skipCaptcha()
+
+ def removeCaptchaImage(self):
+ self.image = False
+ self.captchaImage.setPixmap(QPixmap())
+
+ def toggleRunning(self):
+ self.running = not self.running
+ self.offlinemessage = "Click \"Start\" to fetch next captcha."
+ self.startstopButton.setText(self.running and "Stop" or "Start")
+ self.startstopButton.setChecked(self.running)
+
+ ##################################################
+ # Handle network
+ ##################################################
+ def getCredits(self):
+ url = QUrl(self.apiurl+"action=usercaptchaguthaben")
+ self.networkCredits = QNetworkRequest(url)
+ self.networkCreditsReply = self.NetworkManager.get(self.networkCredits)
+ self.networkCreditsReply.finished.connect(self.getCreditsFinished)
+
+ def getCreditsFinished(self):
+ content = str(self.networkCreditsReply.readAll(), encoding='utf-8')
+ if content.isnumeric():
+ self.currentCredits = int(content)
+ if not self.startCredits:
+ self.startCredits = self.currentCredits
+ self.updateStats()
+ else:
+ self.accountLabel.setText("Error?")
+ self.networkCreditsReply.deleteLater()
+ QTimer.singleShot(10000, self.getCredits)
+
+ def getQueue(self):
+ url = QUrl("http://www.9kw.eu/grafik/servercheck.txt")
+ self.networkQueue = QNetworkRequest(url)
+ self.networkQueueReply = self.NetworkManager.get(self.networkQueue)
+ self.networkQueueReply.finished.connect(self.getQueueFinished)
+
+ def getQueueFinished(self):
+ content = str(self.networkQueueReply.readAll(), encoding='utf-8')
+ datatmp = content.split('|')
+ data = dict()
+ for stat in datatmp:
+ tmp = stat.split('=')
+ data[tmp[0]] = tmp[1]
+ self.currentQueued = int(data['queue'])
+ self.updateStats()
+ self.networkQueueReply.deleteLater()
+ QTimer.singleShot(5000, self.getQueue)
+
+ def getCaptchaID(self):
+ if not self.running:
+ self.captchaImage.setText(self.offlinemessage)
+ QTimer.singleShot(500, self.getCaptchaID)
+ return
+ self.captchaImage.setText("")
+ url = QUrl(self.apiurl+"action=usercaptchanew&text=yes&mouse=0&confirm=0")
+ self.networkCaptchaID = QNetworkRequest(url)
+ self.networkCaptchaIDReply = self.NetworkManager.get(self.networkCaptchaID)
+ self.networkCaptchaIDReply.finished.connect(self.getCaptchaIDFinished)
+
+ def getCaptchaIDFinished(self):
+ content = str(self.networkCaptchaIDReply.readAll(), encoding='utf-8')
+ self.networkCaptchaIDReply.deleteLater()
+ if content == 'NO CAPTCHA':
+ status = self.captchaImage.text()+"."
+ self.captchaImage.setText(status)
+ QTimer.singleShot(1000, self.getCaptchaID)
+ elif not content.isnumeric():
+ self.captchaImage.setText("Unknown error? ID not 'NO CAPTCHA' nor number")
+ else:
+ self.currentCaptchaID = int(content)
+ self.getCaptchaIMG()
+
+ def getCaptchaIMG(self):
+ url = QUrl(self.apiurl+"action=usercaptchashow&id="+str(self.currentCaptchaID))
+ self.networkCaptchaIMG = QNetworkRequest(url)
+ self.networkCaptchaIMGReply = self.NetworkManager.get(self.networkCaptchaIMG)
+ self.networkCaptchaIMGReply.finished.connect(self.getCaptchaIMGFinished)
+
+ def getCaptchaIMGFinished(self):
+ image = self.networkCaptchaIMGReply.readAll()
+ self.setCaptchaImage(image)
+ self.networkCaptchaIMGReply.deleteLater()
+
+ def setCaptchaAnswer(self, answer, skip=False):
+ if skip:
+ url = QUrl(self.apiurl+"action=usercaptchaskip&id="+str(self.currentCaptchaID))
+ self.networkCaptchaAnswer = QNetworkRequest(url)
+ self.networkCaptchaAnswerReply = self.NetworkManager.get(self.networkCaptchaAnswer)
+ self.networkCaptchaAnswerReply.finished.connect(self.setCaptchaAnswerSkipped)
+ else:
+ url = QUrl(self.apiurl+"action=usercaptchacorrect&id="+str(self.currentCaptchaID)+"&antwort="+answer+"&extended=1")
+ self.networkCaptchaAnswer = QNetworkRequest(url)
+ self.networkCaptchaAnswerReply = self.NetworkManager.get(self.networkCaptchaAnswer)
+ self.networkCaptchaAnswerReply.finished.connect(self.setCaptchaAnswerCommit)
+
+ def setCaptchaAnswerCommit(self):
+ message = str(self.networkCaptchaAnswerReply.readAll(), encoding='utf-8')
+ self.networkCaptchaAnswerReply.deleteLater()
+ if not message:
+ # TODO: Server error? Retry! (Status 200 + no 'OK'?)
+ self.networkCaptchaAnswerReply = self.NetworkManager.get(self.networkCaptchaAnswer)
+ self.networkCaptchaAnswerReply.finished.connect(self.setCaptchaAnswerCommit)
+ else:
+ self.currentCommited += 1
+ self.currentCaptchaID = None
+ if message.startswith('OK') and '|' in message:
+ parts = message.split('|')
+ creds = int(parts[1])
+ self.currentCredits += creds
+ self.updateStats()
+ self.getCaptchaID()
+
+ def setCaptchaAnswerSkipped(self):
+ message = str(self.networkCaptchaAnswerReply.readAll(), encoding='utf-8')
+ self.networkCaptchaAnswerReply.deleteLater()
+ if not message:
+ # Server error? Retry! (Status 200 + no 'OK'?)
+ self.networkCaptchaAnswerReply = self.NetworkManager.get(self.networkCaptchaAnswer)
+ self.networkCaptchaAnswerReply.finished.connect(self.setCaptchaAnswerSkipped)
+ else:
+ self.currentSkipped += 1
+ self.currentCaptchaID = None
+ self.updateStats()
+ self.getCaptchaID()
+
+ ##################################################
+ # Handle logic
+ ##################################################
+ def skipCaptcha(self):
+ self.submitCaptcha(skip=True)
+
+ def submitCaptcha(self, skip=False):
+ answer = self.captchaInputLine.text()
+ if not answer:
+ skip = True
+ self.timer.stop()
+ self.setCaptchaAnswer(answer, skip)
+ self.captchaInputLine.setText("")
+ self.removeCaptchaImage()
+
+ def onTimeout(self):
+ self.running = False
+ self.offlinemessage = "30 seconds passed without input."
+ self.startstopButton.setText(self.running and "Stop" or "Start")
+ self.startstopButton.setChecked(self.running)
+ self.skipCaptcha()
+
+ def onQuit(self):
+ if self.currentCaptchaID:
+ self.running = False
+ self.setCaptchaAnswer("", skip=True, queue=False)
+
+
+def main():
+ # NOTE(andre): urlopen() will first try ipv6, if available
+ # hacky way to remove IPv6: http://stackoverflow.com/questions/2014534/force-python-mechanize-urllib2-to-only-use-a-requests/6319043
+ # better way: disable IPv6, if your isp does not support it
+
+ # import pudb; pudb.set_trace()
+ app = QApplication(sys.argv)
+ screen = CaptchaGUI()
+ screen.show()
+ sys.exit(app.exec_())
+
+if __name__ == '__main__':
+ main()