Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F62856
ltchat.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Subscribers
None
ltchat.py
View Options
#!/usr/bin/python2
"""
Qt GUI front-end to the Lightron chat.
Copyright (C) 2016-2017 Glen Harpring
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import
sys
,
os
,
httplib
,
urllib
,
urllib2
,
math
,
time
,
json
,
traceback
print
len
(
sys
.
argv
)
if
len
(
sys
.
argv
)
<
2
:
gui
=
"-qt5"
else
:
gui
=
sys
.
argv
[
1
]
try
:
if
gui
==
"-qt4"
or
gui
==
"-qt3"
:
raise
ImportError
from
PyQt5
import
QtCore
,
QtGui
,
QtWidgets
guiused
=
"Qt5"
except
ImportError
:
#Fallback to PyQt4
print
(
"Warning: Attempting to use Qt4"
)
try
:
if
gui
==
"-qt3"
:
raise
ImportError
from
PyQt4
import
QtCore
,
QtGui
from
PyQt4
import
QtGui
as
QtWidgets
guiused
=
"Qt4"
except
ImportError
:
#Fallback to PySide is basically PyQt4 and is still included in the latest Ubuntu releases.
try
:
if
gui
==
"-qt3"
:
raise
ImportError
from
PySide
import
QtCore
,
QtGui
from
PySide
import
QtGui
as
QtWidgets
guiused
=
"Qt4"
except
ImportError
:
print
(
"Warning: Attempting to use Qt3"
)
try
:
from
qt
import
QtCore
,
QtGui
guiused
=
"Qt3"
except
:
print
(
"PyQt4 or PyQt5 must be installed for this to work (properly)"
);
#from HTMLParser import HTMLParser
global
getChat
,
useragent
getChat
=
httplib
.
HTTPSConnection
(
'lightron.org'
)
class
ChatBrowser
(
QtWidgets
.
QTextBrowser
):
def
loadResource
(
self
,
type
,
name
):
if
type
==
1
:
return
urllib2
.
urlopen
(
str
(
name
.
toString
()))
.
read
()
if
type
==
2
or
type
==
3
:
if
not
str
(
name
.
toString
())
in
self
.
cache
:
try
:
flag
=
name
.
toString
()
.
split
(
"https://lightron.org/inc/images/flags/"
)[
1
]
.
split
(
"."
)[
0
];
except
:
flag
=
"tftde"
;
if
'https://lightron.org/inc/images/flags/'
in
name
.
toString
()
and
flag
is
not
"tftde"
and
os
.
path
.
isfile
(
"/usr/share/locale/l10n/"
+
flag
+
"/flag.png"
):
self
.
cache
[
str
(
name
.
toString
())]
=
QtGui
.
QImage
(
"/usr/share/locale/l10n/"
+
flag
+
"/flag.png"
)
else
:
print
"Downloading "
+
name
.
toString
()
+
" of type "
+
str
(
type
)
+
" into memory..."
try
:
self
.
cache
[
str
(
name
.
toString
())]
=
QtGui
.
QImage
.
fromData
(
urllib2
.
urlopen
(
str
(
name
.
toString
()))
.
read
(),
os
.
path
.
splitext
(
name
.
toString
())[
1
]
.
upper
())
print
"[DONE]"
except
:
print
"[FAIL]"
return
False
return
self
.
cache
[
str
(
name
.
toString
())]
useragent
=
"Mozilla/5.0 QTextBrowser/"
+
guiused
+
" LTChatGUI/3.0r12"
;
class
main
(
object
):
def
setup
(
self
,
MainWindow
):
global
USERNAME
,
WHOSONLINE
,
curronline
,
PING
,
CHATS
,
wait
,
COOKIE
,
mself
,
FIRST
mself
=
self
COOKIE
=
""
;
USERNAME
=
"Guest"
;
WHOSONLINE
=
curronline
=
""
;
CHATS
=
"Loading..."
;
PING
=
'?'
;
wait
=
3
;
self
.
prevCHATS
=
""
;
FIRST
=
True
;
self
.
thread
=
QtCore
.
QThread
()
#Create a generic thread for now
self
.
chatstyle
=
"""
html
{
width: 293px;
font-size: 11px;
font-family: verdana, sans-serif;
line-height: 18px;
}
.send
{
width: 60px;
padding: 0px;
margin-top: 2px;
}
.message
{
position: relative;
right: 3px;
border-bottom: 1px solid #CCC;
}
.user
{
font-size: 12px;
font-weight: bold;
font-family: Arial;
padding-right:3px;
}
.timestamp
{
color: #555;
font-size: 10px;
margin-left: 30px;
}
.delete
{
float: right;
margin-right: 10px;
}"""
MainWindow
.
setObjectName
(
"MainWindow"
)
MainWindow
.
resize
(
335
,
400
)
MainWindow
.
setWindowTitle
(
"Lightron Chat GUI"
)
self
.
centralwidget
=
QtWidgets
.
QWidget
(
MainWindow
)
self
.
centralwidget
.
setObjectName
(
"centralwidget"
)
self
.
gridLayout
=
QtWidgets
.
QGridLayout
(
self
.
centralwidget
)
self
.
gridLayout
.
setObjectName
(
"gridLayout"
)
self
.
label
=
QtWidgets
.
QLabel
(
self
.
centralwidget
)
self
.
label
.
setObjectName
(
"label"
)
self
.
gridLayout
.
addWidget
(
self
.
label
,
1
,
0
,
1
,
1
)
self
.
label_3
=
QtWidgets
.
QLabel
(
self
.
centralwidget
)
self
.
label_3
.
setObjectName
(
"label_3"
)
self
.
gridLayout
.
addWidget
(
self
.
label_3
,
1
,
1
,
1
,
2
)
self
.
pushButton_2
=
QtWidgets
.
QPushButton
(
self
.
centralwidget
)
self
.
pushButton_2
.
setObjectName
(
"pushButton_2"
)
self
.
pushButton_2
.
setText
(
"Options"
)
self
.
pushButton_2
.
clicked
.
connect
(
self
.
showOptions
)
self
.
gridLayout
.
addWidget
(
self
.
pushButton_2
,
1
,
3
,
1
,
1
)
self
.
textBrowser
=
ChatBrowser
(
self
.
centralwidget
)
self
.
textBrowser
.
setObjectName
(
"textBrowser"
)
self
.
textBrowser
.
cache
=
{}
self
.
textBrowser
.
setOpenExternalLinks
(
True
)
self
.
gridLayout
.
addWidget
(
self
.
textBrowser
,
2
,
0
,
1
,
4
)
self
.
pushButton
=
QtWidgets
.
QPushButton
(
self
.
centralwidget
)
self
.
pushButton
.
setObjectName
(
"pushButton"
)
self
.
pushButton
.
setText
(
"Send"
)
self
.
pushButton
.
clicked
.
connect
(
self
.
send
)
self
.
gridLayout
.
addWidget
(
self
.
pushButton
,
3
,
3
,
1
,
1
)
self
.
lineEdit
=
QtWidgets
.
QLineEdit
(
self
.
centralwidget
)
self
.
lineEdit
.
setObjectName
(
"lineEdit"
)
self
.
gridLayout
.
addWidget
(
self
.
lineEdit
,
3
,
0
,
1
,
3
)
self
.
label_2
=
QtWidgets
.
QLabel
(
self
.
centralwidget
)
self
.
label_2
.
setObjectName
(
"label_2"
)
self
.
label_2
.
setOpenExternalLinks
(
True
)
self
.
gridLayout
.
addWidget
(
self
.
label_2
,
5
,
0
,
1
,
4
)
MainWindow
.
setCentralWidget
(
self
.
centralwidget
)
self
.
updateTimer
=
QtCore
.
QTimer
(
MainWindow
)
self
.
updateTimer
.
timeout
.
connect
(
self
.
update
)
self
.
updateTimer
.
start
(
4000
)
self
.
updated
();
self
.
update
()
QtCore
.
QMetaObject
.
connectSlotsByName
(
MainWindow
)
def
update
(
self
):
if
not
self
.
thread
.
isRunning
():
self
.
prevCHATS
=
CHATS
self
.
thread
=
UpdatingChat
()
self
.
thread
.
finished
.
connect
(
self
.
updated
)
self
.
thread
.
start
()
def
send
(
self
):
global
COOKIE
postdata
=
urllib
.
urlencode
({
'action'
:
'submit'
,
'message'
:
str
(
self
.
lineEdit
.
text
())})
try
:
con
=
httplib
.
HTTPSConnection
(
"lightron.org"
)
con
.
request
(
"POST"
,
"/Ajax/Chat"
,
postdata
,{
"User-Agent"
:
useragent
,
"Cookie"
:
COOKIE
,
"Content-Type"
:
"application/x-www-form-urlencoded; charset=UTF-8"
})
ChatsResponse
=
con
.
getresponse
()
except
:
pass
;
self
.
lineEdit
.
setText
(
""
)
self
.
updated
();
self
.
update
()
def
showOptions
(
self
):
self
.
options
=
QtWidgets
.
QMenu
()
if
USERNAME
==
"Guest"
:
self
.
optionsLogin
=
self
.
options
.
addAction
(
"Login"
)
self
.
optionsLogin
.
triggered
.
connect
(
self
.
login
)
else
:
self
.
optionsProfile
=
self
.
options
.
addAction
(
"Profile"
)
self
.
optionsProfile
.
triggered
.
connect
(
self
.
profile
)
self
.
optionsLogout
=
self
.
options
.
addAction
(
"Logout"
)
self
.
optionsLogout
.
triggered
.
connect
(
self
.
logout
)
self
.
options
.
addSeparator
()
self
.
optionsStats
=
self
.
options
.
addAction
(
"Statitics"
)
self
.
optionsStats
.
triggered
.
connect
(
self
.
stats
)
self
.
optionsAbout
=
self
.
options
.
addAction
(
"About"
)
self
.
optionsStats
.
triggered
.
connect
(
self
.
about
)
#self.optionsToC = self.options.addAction("License Agreement")
#self.optionsToC.triggered.connect(self.gpl)
self
.
options
.
exec_
(
QtGui
.
QCursor
()
.
pos
())
def
updated
(
self
):
global
USERNAME
,
COOKIE
if
USERNAME
==
"Guest"
:
self
.
label
.
setText
(
"Please sign in to chat."
)
out
=
True
else
:
self
.
label
.
setText
(
"Hello, "
+
USERNAME
+
"!"
)
out
=
False
self
.
pushButton
.
setHidden
(
out
)
self
.
lineEdit
.
setHidden
(
out
)
self
.
label_3
.
setText
(
str
(
PING
)
+
"ms"
)
self
.
label_2
.
setText
(
WHOSONLINE
)
self
.
label_2
.
setToolTip
(
curronline
)
if
CHATS
==
""
:
print
"Returned chat appears to be blank."
elif
not
self
.
prevCHATS
==
CHATS
:
self
.
textBrowser
.
setHtml
(
'<style type="text/css">'
+
self
.
chatstyle
+
'</style>
\n
<div class="chat"><div class="chat-output">'
+
str
(
CHATS
)
+
"</div></div>"
)
def
login
(
self
):
login
()
def
completeLogin
(
self
):
global
USERNAME
,
COOKIE
postdata
=
urllib
.
urlencode
({
'username'
:
loginDia
.
lineEdit
.
text
(),
'password'
:
loginDia
.
lineEdit_2
.
text
()})
try
:
con
=
httplib
.
HTTPSConnection
(
"lightron.org"
)
con
.
request
(
"POST"
,
"/Authentication"
,
postdata
,{
"User-Agent"
:
useragent
,
"Cookie"
:
COOKIE
,
"Content-Type"
:
"application/x-www-form-urlencoded; charset=UTF-8"
})
except
:
QtWidgets
.
QMessageBox
.
critical
(
MainWindow
,
'LTChat'
,
'Unable to login. Are you connected to the internet?'
,
QtWidgets
.
QMessageBox
.
Ok
)
return
;
data
=
con
.
getresponse
()
datar
=
str
(
data
.
read
())
datars
=
data
.
getheader
(
'Location'
)
if
datars
==
"/?invalid"
:
QtWidgets
.
QMessageBox
.
warning
(
MainWindow
,
'LTChat'
,
'Username and/or password invalid.'
,
QtWidgets
.
QMessageBox
.
Ok
)
loginDia
.
lineEdit_2
.
selectAll
()
elif
datars
!=
"/"
:
QtWidgets
.
QMessageBox
.
critical
(
MainWindow
,
'LTChat'
,
'Returned "'
+
datar
.
rstrip
(
'
\n
'
)
+
'"'
,
QtWidgets
.
QMessageBox
.
Ok
)
else
:
#self.lineEdit.setText(str(data))
#COOKIE = data.getheader('Cookie')
USERNAME
=
loginDia
.
lineEdit
.
text
()
loginDia
.
hide
()
self
.
update
()
def
logout
(
self
):
global
USERNAME
,
COOKIE
USERNAME
=
"Guest"
;
COOKIE
=
""
;
self
.
updated
()
def
profile
(
self
):
profile
()
def
stats
(
self
):
return
;
def
about
(
self
):
return
;
def
changepass
(
self
):
return
;
class
LoginDialog
(
QtWidgets
.
QDialog
):
def
__init__
(
self
):
super
(
LoginDialog
,
self
)
.
__init__
()
self
.
setup
()
def
setup
(
self
):
self
.
setWindowTitle
(
"Login to LTChat"
)
self
.
resize
(
335
,
80
)
self
.
gridLayout
=
QtWidgets
.
QGridLayout
(
self
)
self
.
gridLayout
.
setObjectName
(
"gridLayout"
)
spacerItem
=
QtWidgets
.
QSpacerItem
(
260
,
20
,
QtWidgets
.
QSizePolicy
.
Expanding
,
QtWidgets
.
QSizePolicy
.
Minimum
)
self
.
gridLayout
.
addItem
(
spacerItem
,
2
,
0
,
1
,
1
)
self
.
pushButton
=
QtWidgets
.
QPushButton
(
self
)
self
.
pushButton
.
setObjectName
(
"pushButton"
)
self
.
pushButton
.
setText
(
"Login!"
)
self
.
pushButton
.
setShortcut
(
"Enter, Return"
)
self
.
pushButton
.
clicked
.
connect
(
mself
.
completeLogin
)
self
.
gridLayout
.
addWidget
(
self
.
pushButton
,
2
,
1
,
1
,
1
)
self
.
lineEdit
=
QtWidgets
.
QLineEdit
(
self
)
self
.
lineEdit
.
setObjectName
(
"lineEdit"
)
self
.
lineEdit
.
setPlaceholderText
(
"Username"
)
self
.
gridLayout
.
addWidget
(
self
.
lineEdit
,
0
,
0
,
1
,
2
)
self
.
lineEdit_2
=
QtWidgets
.
QLineEdit
(
self
)
self
.
lineEdit_2
.
setEchoMode
(
QtWidgets
.
QLineEdit
.
Password
)
self
.
lineEdit_2
.
setObjectName
(
"lineEdit_2"
)
self
.
lineEdit_2
.
setPlaceholderText
(
"Password"
)
self
.
gridLayout
.
addWidget
(
self
.
lineEdit_2
,
1
,
0
,
1
,
2
)
QtCore
.
QMetaObject
.
connectSlotsByName
(
self
)
class
profileDialog
(
QtWidgets
.
QDialog
):
def
__init__
(
self
):
super
(
profileDialog
,
self
)
.
__init__
()
self
.
setup
()
def
setup
(
self
):
self
.
setWindowTitle
(
"My Profile - LTChat"
)
self
.
resize
(
335
,
80
)
try
:
con
=
httplib
.
HTTPSConnection
(
"lightron.org"
)
con
.
request
(
"POST"
,
"/Authentication"
,
urllib
.
urlencode
({
'action'
:
'userControlPanel'
}),{
"User-Agent"
:
useragent
,
"Cookie"
:
COOKIE
,
"Content-Type"
:
"application/x-www-form-urlencoded; charset=UTF-8"
})
except
:
QtWidgets
.
QMessageBox
.
critical
(
MainWindow
,
'LTChat'
,
'Unable to login. Are you connected to the internet?'
,
QtWidgets
.
QMessageBox
.
Ok
)
return
;
self
.
gridLayout
=
QtWidgets
.
QGridLayout
(
self
)
self
.
gridLayout
.
setObjectName
(
"gridLayout"
)
spacerItem
=
QtWidgets
.
QSpacerItem
(
260
,
20
,
QtWidgets
.
QSizePolicy
.
Expanding
,
QtWidgets
.
QSizePolicy
.
Minimum
)
self
.
gridLayout
.
addItem
(
spacerItem
,
2
,
0
,
1
,
1
)
self
.
pushButton
=
QtWidgets
.
QPushButton
(
self
)
self
.
pushButton
.
setObjectName
(
"pushButton"
)
self
.
pushButton
.
setText
(
"Close"
)
self
.
pushButton
.
setShortcut
(
"Enter, Return"
)
self
.
pushButton
.
clicked
.
connect
(
self
.
close
)
self
.
gridLayout
.
addWidget
(
self
.
pushButton
,
2
,
1
,
1
,
1
)
self
.
profileImage
=
QtWidgets
.
QLabel
()
image
=
"https://lightron.org/inc/images/avatar/101.png"
self
.
proImage
=
QtGui
.
QPixmap
.
fromImage
(
mself
.
textBrowser
.
loadResource
(
2
,
QtCore
.
QUrl
(
image
)))
self
.
profileImage
.
setPixmap
(
self
.
proImage
)
self
.
gridLayout
.
addWidget
(
self
.
profileImage
,
0
,
0
,
1
,
2
)
QtCore
.
QMetaObject
.
connectSlotsByName
(
self
)
class
UpdatingChat
(
QtCore
.
QThread
):
def
run
(
self
):
global
USERNAME
,
WHOSONLINE
,
curronline
,
PING
,
CHATS
,
wait
,
getChat
,
FIRST
,
COOKIE
if
FIRST
:
try
:
con
=
httplib
.
HTTPSConnection
(
"lightron.org"
)
con
.
request
(
"GET"
,
"/"
,
""
,{
"User-Agent"
:
useragent
})
data
=
con
.
getresponse
()
except
httplib
.
ssl
.
SSLError
:
ex_type
,
ex
,
tb
=
sys
.
exc_info
()
CHATS
=
"<body><p><strong>Error:</strong> SSL Certificate Error!</p> <p>"
+
traceback
.
format_exc
(
tb
)
+
"</p></body>"
PING
=
"inf"
;
WHOSONLINE
=
""
;
curronline
=
"can't tell"
del
tb
;
return
;
except
:
CHATS
=
"<p><strong>Error:</strong> Loading failed, is your internet connected?</p>"
PING
=
"inf"
;
WHOSONLINE
=
""
;
curronline
=
"can't tell"
return
;
FIRST
=
False
;
cookieheader
=
data
.
getheader
(
'Set-Cookie'
);
if
cookieheader
is
None
:
cookieheader
=
""
;
COOKIE
=
cookieheader
.
split
(
" "
)[
0
]
wait
=
wait
+
1
defheader
=
{
"User-Agent"
:
useragent
,
"Cookie"
:
COOKIE
,
"Content-Type"
:
"application/x-www-form-urlencoded; charset=UTF-8"
,
"X-Requested-With"
:
"XMLHttpRequest"
}
getChat
=
httplib
.
HTTPSConnection
(
'lightron.org'
)
pullr
=
urllib
.
urlencode
({
"action"
:
"pull"
,
"max-id"
:
"0"
})
try
:
timebefore
=
time
.
time
();
getChat
.
request
(
"POST"
,
"/Ajax/Chat"
,
pullr
,
defheader
);
timeafter
=
time
.
time
()
PING
=
int
((
float
(
timeafter
)
-
float
(
timebefore
))
*
1000
)
except
:
return
;
try
:
ChatsRespons
=
getChat
.
getresponse
()
.
read
()
#print ChatsRespons;
except
:
if
CHATS
is
""
:
CHATS
=
"<p><strong>Error:</strong> Unable to receive chats. Is your internet connection working?</p>"
PING
=
"inf"
;
WHOSONLINE
=
""
;
curronline
=
"can't tell"
try
:
ChatsResponse
=
json
.
loads
(
ChatsRespons
)
#print ChatsResponse;
except
:
return
thechatshtm
=
ChatsResponse
[
"output"
]
.
replace
(
"margin: 0px 4px -1px 0px;"
,
"margin-right:4px;margin-bottom:-1px;"
)
#WHOSONLINE = ChatsResponse["chatters"].replace("padding: 0px 4px;\">","\"> ")
WHOSONLINE
=
ChatsResponse
[
"online"
]
if
len
(
ChatsResponse
[
"online"
]
.
split
(
":"
))
>
1
:
curronline
=
ChatsResponse
[
"online"
]
.
split
(
":"
)[
1
]
.
replace
(
"padding: 0px 4px;
\"
>"
,
"
\"
> "
)
else
:
curronline
=
"nobody"
CHATS
=
str
(
thechatshtm
.
replace
(
"<a href=
\"
/"
,
"<a href=
\"
https://lightron.org/"
)
.
replace
(
"<img src=
\"
/"
,
"<img src=
\"
https://lightron.org/"
)
.
replace
(
'class=
\"
avatar
\"
'
,
'" width="12" height="12"'
)
.
replace
(
'style=
\"
height: 10px; margin: 0px 4px -1px 0px;
\"
'
,
'"width="21" height="14"'
))
#self.updated()
#print "Updated!"
def
login
():
global
loginDia
loginDia
=
LoginDialog
()
loginDia
.
setWindowModality
(
QtCore
.
Qt
.
ApplicationModal
)
loginDia
.
show
()
def
profile
():
global
profileDia
profileDia
=
profileDialog
()
profileDia
.
setWindowModality
(
QtCore
.
Qt
.
ApplicationModal
)
profileDia
.
show
()
app
=
QtWidgets
.
QApplication
(
sys
.
argv
)
MainWindow
=
QtWidgets
.
QMainWindow
()
ui
=
main
()
ui
.
setup
(
MainWindow
)
MainWindow
.
show
()
sys
.
exit
(
app
.
exec_
())
File Metadata
Details
Attached
Mime Type
text/x-python
Expires
Wed, Sep 3, 7:54 AM (6 d, 7 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13727
Attached To
rLTCHAT ltchat
Event Timeline
Log In to Comment