# -*- coding: utf-8 -*-
import rfiles
from PyQt4 import QtCore, QtGui
from PyQt4.QtWebKit import QWebView, QWebPage
import http.client as http_c
import sys, os, datetime, webbrowser, re, urllib.request, sqlite3
import lxml.html
from lxml import etree
class BaseWindow(QtGui.QMainWindow):
VERSION = 'v0.1'
themesNotif = True
smsNotif = True
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.centralWidget = QtGui.QWidget()
self.resize(800, 500)
self.setMinimumSize(500, 400)
self.setWindowTitle('PHPForum.ru ' + self.VERSION)
self.sb = self.statusBar()
self.path = os.getcwd()
self.rpath = os.path.normpath(self.path + '/resources/').replace('\\', '/')
self.setWindowIcon(QtGui.QIcon(':/resources/images/favicon.ico'))
self.tabs = QtGui.QTabWidget()
self.dbGetSettings()
exitMenu = QtGui.QAction(QtGui.QIcon('icons/exit.png'), 'Выход', self)
exitMenu.setShortcut('Ctrl+Q')
self.connect(exitMenu, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
menubar = self.menuBar()
file = menubar.addMenu('Файл')
file.addAction(exitMenu)
self.msgThemes = msgThemes = QtGui.QAction(QtGui.QIcon(), 'О темах', self, checkable = True)
msgThemes.setChecked(self.themesNotif)
self.msgSms = msgSms = QtGui.QAction(QtGui.QIcon(), 'О SMS', self, checkable = True)
msgSms.setChecked(self.smsNotif)
self.connect(msgThemes, QtCore.SIGNAL('toggled(bool)'), lambda: self.notifMessages('themes'))
self.connect(msgSms, QtCore.SIGNAL('toggled(bool)'), lambda: self.notifMessages('sms'))
messages = menubar.addMenu('Уведомления')
messages.addAction(msgThemes)
messages.addAction(msgSms)
def notifMessages(self, type):
sql = """
UPDATE `config`
SET `value` = ?
WHERE `name` = ?
"""
if type == 'themes':
conf = 'themes_notif'
val = self.msgThemes.isChecked()
self.themesNotif = val
val = int(val)
elif type == 'sms':
conf = 'sms_notif'
val = self.msgSms.isChecked()
self.smsNotif = val
val = int(val)
self.dbConnect()
try:
self.cur.execute(sql, (val, conf,))
except:
pass
else:
self.db.commit()
self.dbClose()
@QtCore.pyqtSlot(QtGui.QSystemTrayIcon.ActivationReason)
def onTrayIconActivated(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.showNormal()
def createTrayIcon(self):
self.quitAction = QtGui.QAction("&Выход", self, triggered=QtGui.qApp.quit)
self.trayIconMenu = QtGui.QMenu(self)
self.trayIconMenu.addAction(self.quitAction)
self.trayIcon = QtGui.QSystemTrayIcon(self)
self.trayIcon.activated.connect(self.onTrayIconActivated)
self.trayIcon.setContextMenu(self.trayIconMenu)
self.trayIcon.setIcon(QtGui.QIcon(':/resources/images/favicon.ico'))
self.trayIcon.show()
def changeEvent(self, event):
if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
self.hide()
elif event.oldState() & QtCore.Qt.WindowMinimized:
self.showNormal()
super(BaseWindow, self).changeEvent(event)
def dbConnect(self):
self.db = sqlite3.connect('maindb.sqlite')
self.cur = self.db.cursor()
def dbClose(self):
self.cur.close()
self.db.close()
def dbGetSettings(self):
self.dbConnect()
res = None
sql = """
SELECT `name`, `value` FROM `config`
WHERE `name` IN('themes_notif', 'sms_notif')
"""
try:
self.cur.execute(sql)
except:
pass
else:
res = self.cur.fetchmany(2)
if len(res) == 2:
for el in res:
if el[0] == 'sms_notif':
self.smsNotif = bool(int(el[1]))
continue
elif el[0] == 'themes_notif':
self.themesNotif = bool(int(el[1]))
continue
self.dbClose()
class Loader(BaseWindow):
FORUM_URL = 'phpforum.ru'
connection = False
def __init__(self, parent = None):
BaseWindow.__init__(self, parent)
self.createTrayIcon()
self.setStatusIco()
self.checkConnection()
self.curThemeTime = None
self.lastSmsId = None
self.pb = QtGui.QProgressBar(self.sb)
self.pb.setTextVisible(True)
self.pb.setMaximumWidth(200)
self.pb.hide()
self.sb.addPermanentWidget(self.pb)
self.pb2 = QtGui.QProgressBar(self.sb)
self.pb2.setTextVisible(True)
self.pb2.setMaximumWidth(200)
self.pb2.hide()
self.sb.addPermanentWidget(self.pb2, 1)
self.webview = QWebView(loadProgress = self.pb.setValue, loadFinished = self.pb.hide, loadStarted = self.pb.show)
self.webviewSMS = QWebView(loadProgress = self.pb2.setValue, loadFinished = self.pb2.hide, loadStarted = self.pb2.show)
self.webview.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
self.webview.connect(self.webview.page(), QtCore.SIGNAL("linkClicked(const QUrl&)"), self.linkClicked)
self.webviewSMS.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
self.webviewSMS.connect(self.webviewSMS.page(), QtCore.SIGNAL("linkClicked(const QUrl&)"), self.linkClicked)
self.connect(self.webview, QtCore.SIGNAL("loadProgress(int)"), self.loadProgress)
if self.connection:
QtCore.QTimer.singleShot(500, self.onLoadSms)
QtCore.QTimer.singleShot(500, self.onLoadThemes)
centralLayout = QtGui.QVBoxLayout()
centralLayout.addWidget(self.tabs, 1)
self.tabs.addTab(self.webview, "Темы");
self.tabs.addTab(self.webviewSMS,"SMS");
self.centralWidget.setLayout(centralLayout)
self.setCentralWidget(self.centralWidget)
if self.connection:
self.timers()
else:
self.timerConn()
def timers(self, start = True):
if start:
self.timerSms = QtCore.QTimer()
self.timerSms.timeout.connect(self.onLoadSms)
self.timerSms.start(1000*60)
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.onLoadThemes)
self.timer.start(1000*60)
else:
self.timer.stop()
self.timerSms.stop()
def timerConn(self, start = True):
if start:
self.timerCon = QtCore.QTimer()
self.timerCon.timeout.connect(self.checkConnection)
self.timerCon.start(1000*10)
else:
if hasattr(self, 'timerCon') and self.timerCon.isActive():
self.timerCon.stop()
self.timers()
self.onLoadThemes()
self.onLoadSms()
def loadProgress(self, load):
if load == 100:
self.pb.hide()
else:
self.pb.show()
self.pb.setRange(0, 100)
self.pb.setValue(load)
def onLoadThemes(self):
if not self.checkConnection():
self.timers(False)
self.timerConn()
return False
self.loadThemes()
self.webview.setHtml(self.themesStr)
def onLoadSms(self):
if not self.connection:
return False
self.loadSms()
self.webviewSMS.setHtml(self.smsStr)
def themesTrayMessage(self, themeName):
icon = QtGui.QSystemTrayIcon.MessageIcon(QtGui.QSystemTrayIcon.Information)
self.trayIcon.showMessage(
'Появились новые сообщения',
'В теме: "' + themeName + '"',
icon,
3000
)
def smsTrayMessage(self, author):
icon = QtGui.QSystemTrayIcon.MessageIcon(QtGui.QSystemTrayIcon.Information)
self.trayIcon.showMessage(
'Появилось новое SMS',
'От пользователя: ' + author,
icon,
3000
)
def loadThemes(self):
con = http_c.HTTPConnection(self.FORUM_URL)
con.request('GET', 'url')
res = con.getresponse()
themesCode = res.read().decode('cp1251')
doc = lxml.html.document_fromstring(themesCode)
topics = doc.xpath('/html/body/table[@class="topic"]')
data = []
i = 0
for topic in topics:
i += 1
tStr = lxml.html.document_fromstring(etree.tostring(topic))
authorName = tStr.xpath('//a[@class="author"]/text()')
authorLink = tStr.xpath('//a[@class="author"]/@href')
lastPost = tStr.xpath('//span[@class="post_date"]/text()[1]')
lastPostTmp = re.search(r'(\d?\d\.\d\d\.\d{4})\s+-\s+(\d\d:\d\d)', str(lastPost))
lastPost = "{0} - {1}".format(str(lastPostTmp.group(2)), str(lastPostTmp.group(1)))
title = tStr.xpath('//span[@class="topic_title"]/text()')
topicLink = tStr.xpath('//a[@class="topic_link"]/@href')
topicText = tStr.xpath('//table[1]//tr[3]/td/text()')
topicId = re.search('t=(\d+)$', topicLink[0]).group(1)
try:
authorName = authorName[0]
except IndexError:
authorName = 'Guest'
authorLink = '#'
else:
authorLink = authorLink[0]
try:
topicText = topicText[0]
except IndexError:
topicText = None
data.append({
'title': title[0],
'authorName': authorName,
'authorLink': authorLink,
'lastPost': lastPost,
'topicLink': topicLink[0],
'topicText': topicText,
'topicId': topicId,
})
if len(data) > 0:
if self.curThemeTime is None:
self.curThemeTime = data[0]['lastPost']
elif self.curThemeTime != data[0]['lastPost']:
if self.themesNotif:
self.themesTrayMessage(data[0]['title'])
self.curThemeTime = data[0]['lastPost']
themesStr = """
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="qrc:/resources/css/style.css">
</head>
<body>
<a href="http://phpforum.ru/">На главную</a> |
<a href="http://phpforum.ru/index.php?act=Search&CODE=getnew">Новые сообщения</a>
<div><hr></div>
"""
for info in data:
if info['authorName'] == 'Guest':
author = 'Guest'
else:
author = '<a href="{authorLink}" title="ТС">{authorName}</a>'.format(**info)
themesStr += """
<div class="topic">
<span class="title"><a href="{topicLink}">{title}</a></span>
<span class="author">{author}</span>
<span class="time">{lastPost}</span>
</div>
<br>
""".format(author = author, **info)
themesStr += """
</body>
</html>
"""
self.themesStr = themesStr
def loadSms(self):
con = http_c.HTTPConnection(self.FORUM_URL)
con.request('GET', 'url')
res = con.getresponse()
smsCode = res.read().decode('cp1251')
data = []
smsCode = smsCode.replace(" encoding='windows-1251'", '')
root = etree.XML(smsCode)
for mes in root.xpath('//message'):
authorName = mes.xpath('author/text()')[0]
authorId = mes.xpath('author/@id')[0]
messageText = mes.xpath('messageText/text()')[0]
messageId = mes.xpath('messageText/@id')[0]
messageColor = mes.xpath('messageText/@color')[0]
messageTime = mes.xpath('time/text()')[0]
messageTime = datetime.datetime.fromtimestamp(int(messageTime))
messageTime = messageTime.strftime('%H:%M %d/%m')
data.append({
'authorName': authorName,
'authorId': authorId,
'messageText': messageText,
'messageId': messageId,
'messageColor': messageColor,
'messageTime': messageTime,
})
data = sorted(data, key=lambda k: k['messageId'])
if len(data) > 0:
lastIndex = len(data) - 1
if self.lastSmsId is None:
self.lastSmsId= data[lastIndex]['messageId']
elif self.lastSmsId != data[lastIndex]['messageId'] or (self.lastSmsId is None and int(data[lastIndex]['messageId']) > 0):
if self.smsNotif:
self.smsTrayMessage(data[lastIndex]['authorName'])
self.lastSmsId = data[lastIndex]['messageId']
smsStr = """
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="qrc:/resources/css/style.css">
</head>
<body>
<a href="http://phpforum.ru/index.php?&act=Shoutbox">Написать сообщение</a>
<div><hr></div>
"""
for info in data:
smsStr += """
<div class="sms">
<span class="author"><a href="http://phpforum.ru/index.php?&showuser={authorId}">{authorName}</a></span>
<span class="time">{messageTime}</span>
<span class="sms_link"><a href="http://phpforum.ru/index.php?act=Shoutbox&shout={messageId}">#{messageId}</a></span>
<div><hr></div>
<div class="message" style="color:{messageColor}">{messageText}</div>
</div>
<br>
""".format(**info)
smsStr += """
</body>
</html>
"""
self.smsStr = smsStr
def checkConnection(self):
try:
urllib.request.urlopen('http://' + self.FORUM_URL, timeout = 30)
self.connection = True
self.timerConn(False)
self.changeStatusIco()
return True
except urllib.request.URLError:
self.connection = False
self.changeStatusIco(False)
return False
def setStatusIco(self):
self.statusIco = QtGui.QLabel()
self.statusIco.setFrameStyle(QtGui.QFrame.NoFrame)
self.statusIco.setPixmap(QtGui.QPixmap(':/resources/images/not_con.png'))
self.sb.addWidget(self.statusIco)
def changeStatusIco(self, isConn = True):
if isConn:
self.statusIco.setPixmap(QtGui.QPixmap(':/resources/images/is_con.png'))
else:
self.statusIco.setPixmap(QtGui.QPixmap(':/resources/images/not_con.png'))
def linkClicked(self, url):
webbrowser.open(str(url.toString()))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Loader()
window.show()
sys.exit(app.exec_())