2024-08-14 13:48:27 -04:00
# include "mainwindow.h"
# include <QApplication>
2024-08-15 12:23:36 -04:00
# include <QFile>
2024-08-14 14:54:24 -04:00
# include <QHBoxLayout>
2024-08-15 12:23:36 -04:00
# include <QJsonDocument>
# include <QJsonObject>
# include <QNetworkAccessManager>
# include <QNetworkRequest>
# include <QRegularExpression>
# include <QSettings>
2024-08-14 13:48:27 -04:00
# include <QVBoxLayout>
2024-08-15 12:23:36 -04:00
# include <utils/discordrequests.h>
2024-08-14 16:15:26 -04:00
void MainWindow : : handleOutput ( ) {
QString content = m_box - > text ( ) ;
m_box - > setText ( " " ) ;
switch ( state ) {
2024-08-15 12:23:36 -04:00
case Unauthed : {
2024-08-14 16:15:26 -04:00
if ( ! content . startsWith ( " /login " ) ) {
addMessage ( " You are currently unauthenticated, you can't send messages or use commands! " , Error ) ;
return ;
}
m_box - > setEchoMode ( QLineEdit : : NoEcho ) ;
m_box - > setPlaceholderText ( " Enter your password " ) ;
state = PendingPassword ;
2024-08-15 12:23:36 -04:00
m_pendingAuthObject . setEmail ( content . replace ( " /login " , " " ) ) ;
2024-08-14 16:15:26 -04:00
addMessage ( QString ( " Logging in as <b>%1</b>. Enter your password then press Enter. (you won't be able to see any characters) " ) . arg ( content . replace ( " /login " , " " ) ) , System ) ;
2024-08-15 12:23:36 -04:00
addMessage ( " If you'd like to cancel at any time, type 'cancel'. " , System ) ;
2024-08-14 16:15:26 -04:00
break ;
2024-08-15 12:23:36 -04:00
}
case PendingPassword : {
m_box - > setEchoMode ( QLineEdit : : Normal ) ;
m_box - > setPlaceholderText ( " Message (or /command) " ) ;
state = Unauthed ;
if ( content = = " cancel " ) {
addMessage ( " Cancelled. " , System ) ;
break ;
2024-08-14 16:15:26 -04:00
}
2024-08-15 12:23:36 -04:00
addMessage ( " Logging in, please be patient... " , System ) ;
QNetworkRequest request = DiscordRequests : : buildRequest ( " auth/login " , false , true ) ;
QJsonObject data ;
data [ " undelete " ] = true ;
data [ " email " ] = m_pendingAuthObject . getEmail ( ) ;
data [ " password " ] = content ;
m_netmgr - > post ( request , QJsonDocument ( data ) . toJson ( ) ) ;
break ;
}
case PendingOTP : {
if ( content = = " cancel " ) {
addMessage ( " Cancelled. " , System ) ;
break ;
}
static QRegularExpression re ( " \\ d* " ) ;
if ( ! re . match ( content ) . hasMatch ( ) | | content . length ( ) > 8 | | content . length ( ) < 6 | | content . length ( ) = = 7 ) {
addMessage ( " A valid TOTP or backup code is required. Else, enter 'sms' to use SMS auth. " , Error ) ;
break ;
}
if ( content . length ( ) = = 6 ) {
QNetworkRequest request = DiscordRequests : : buildRequest ( " auth/mfa/totp " , false , true ) ;
QJsonObject data ;
data [ " ticket " ] = m_pendingAuthObject . get2faToken ( ) ;
data [ " code " ] = content ;
m_netmgr - > post ( request , QJsonDocument ( data ) . toJson ( ) ) ;
}
if ( content . length ( ) = = 8 ) {
QNetworkRequest request = DiscordRequests : : buildRequest ( " auth/mfa/backup " , false , true ) ;
QJsonObject data ;
data [ " ticket " ] = m_pendingAuthObject . get2faToken ( ) ;
data [ " code " ] = content ;
m_netmgr - > post ( request , QJsonDocument ( data ) . toJson ( ) ) ;
}
break ;
}
}
2024-08-14 16:15:26 -04:00
}
2024-08-14 15:23:01 -04:00
void MainWindow : : addMessage ( QString content , MainWindow : : MessageType type ) {
if ( type = = Normal ) {
m_chatlog - > append ( content ) ;
}
if ( type = = System ) {
m_chatlog - > append ( QString ( " <span style= \" color:#00FFE5; \" >[Sys] %1</p> " ) . arg ( content ) ) ;
}
if ( type = = Error ) {
2024-08-14 16:15:26 -04:00
m_chatlog - > append ( QString ( " <span style= \" color:#ff2222; \" >Error: %1</p> " ) . arg ( content ) ) ;
2024-08-14 15:23:01 -04:00
}
}
2024-08-15 12:23:36 -04:00
void MainWindow : : handleHttpReply ( QNetworkReply * reply ) {
QJsonDocument data = QJsonDocument : : fromJson ( reply - > readAll ( ) ) ;
if ( reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) ! = 200 ) {
addMessage ( " Something happened " , Error ) ;
return ;
}
// == AUTH == //
if ( data [ " mfa " ] . toBool ( ) & & reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) = = 200 ) {
m_pendingAuthObject . set2faToken ( data [ " ticket " ] . toString ( ) ) ;
m_box - > setPlaceholderText ( " Enter your code (or sms) " ) ;
state = PendingOTP ;
if ( data [ " sms " ] . toBool ( ) ) {
addMessage ( " 2FA is required to login to this account. Available options: authenticator app, backup codes, SMS auth " , System ) ;
addMessage ( " To use TOTP/backup auth, simply enter your 6-8 digit code. For SMS auth, type 'sms'. " , System ) ;
}
else {
addMessage ( " 2FA is required to login to this account. Available options: authenticator app, backup codes " , System ) ;
addMessage ( " Enter your 6-8 digit code. " , System ) ;
}
}
if ( data [ " token " ] . toString ( ) ! = " " ) {
QSettings settings ;
settings . setValue ( " token " , data [ " token " ] . toString ( ) ) ;
addMessage ( " Auth done! " , System ) ;
}
// == END AUTH == //
}
2024-08-14 13:48:27 -04:00
MainWindow : : MainWindow ( QWidget * parent )
: QMainWindow ( parent )
{
2024-08-15 12:23:36 -04:00
QCoreApplication : : setOrganizationName ( " nin0dev " ) ;
QCoreApplication : : setApplicationName ( " txtcord " ) ;
QSettings settings ;
2024-08-14 13:48:27 -04:00
QWidget * centralWidget = new QWidget ( this ) ;
m_layout = new QVBoxLayout ( centralWidget ) ;
setCentralWidget ( centralWidget ) ;
2024-08-15 12:23:36 -04:00
// init network manager
m_pendingAuthObject = PendingAuthObject ( ) ;
m_netmgr = new QNetworkAccessManager ( this ) ;
connect ( m_netmgr , SIGNAL ( finished ( QNetworkReply * ) ) , this , SLOT ( handleHttpReply ( QNetworkReply * ) ) ) ;
2024-08-14 14:54:24 -04:00
// init chatlog
m_chatlog = new QTextEdit ( ) ;
m_chatlog - > setReadOnly ( true ) ;
2024-08-14 15:23:01 -04:00
m_chatlog - > append ( " <b style= \" color:#00FFE5; \" >Welcome to txtcord, the minimal Discord client.</b> " ) ;
2024-08-15 12:23:36 -04:00
if ( settings . value ( " token " ) . isNull ( ) ) {
addMessage ( " No accounts are saved. Use the /login [email/phone] command to sign in to your Discord account. " , System ) ;
}
else {
addMessage ( " You are logged in, connecting to the Gateway... (soon) " , System ) ;
state = NonConnected ;
}
2024-08-14 14:54:24 -04:00
m_layout - > addWidget ( m_chatlog ) ;
// init chatbox
QWidget * chatboxWidget = new QWidget ( ) ;
QHBoxLayout * chatboxLayout = new QHBoxLayout ( ) ;
m_box = new QLineEdit ( ) ;
m_box - > setPlaceholderText ( " Message (or /command) " ) ;
chatboxLayout - > addWidget ( m_box ) ;
m_send = new QPushButton ( ) ;
m_send - > setText ( " Send " ) ;
chatboxLayout - > addWidget ( m_send ) ;
chatboxWidget - > setLayout ( chatboxLayout ) ;
m_layout - > addWidget ( chatboxWidget ) ;
2024-08-14 16:15:26 -04:00
connect ( m_box , SIGNAL ( returnPressed ( ) ) , this , SLOT ( handleOutput ( ) ) ) ;
2024-08-14 13:48:27 -04:00
}
MainWindow : : ~ MainWindow ( ) {
}