2018-09-06 13:48:01 +00:00
/*
This file is part of Telegram Desktop ,
the official desktop application for the Telegram messaging service .
For license and copyright information please follow this link :
https : //github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
# include "settings/settings_codes.h"
# include "ui/toast/toast.h"
# include "mainwidget.h"
2020-03-26 10:29:27 +00:00
# include "mainwindow.h"
2018-09-06 13:48:01 +00:00
# include "data/data_session.h"
2021-09-10 19:29:30 +00:00
# include "data/data_cloud_themes.h"
2020-06-09 16:57:05 +00:00
# include "main/main_session.h"
2020-06-17 09:36:25 +00:00
# include "main/main_account.h"
2020-06-18 18:04:16 +00:00
# include "main/main_domain.h"
2021-10-18 21:36:55 +00:00
# include "ui/boxes/confirm_box.h"
2018-09-06 13:48:01 +00:00
# include "lang/lang_cloud_manager.h"
2018-11-13 09:14:22 +00:00
# include "lang/lang_instance.h"
2019-01-21 13:42:21 +00:00
# include "core/application.h"
2018-09-06 13:48:01 +00:00
# include "mtproto/mtp_instance.h"
2020-06-17 09:36:25 +00:00
# include "mtproto/mtproto_dc_options.h"
2018-09-06 13:48:01 +00:00
# include "core/file_utilities.h"
# include "core/update_checker.h"
# include "window/themes/window_theme.h"
# include "window/themes/window_theme_editor.h"
2020-03-26 10:29:27 +00:00
# include "window/window_session_controller.h"
2019-02-13 12:36:59 +00:00
# include "media/audio/media_audio_track.h"
2020-03-26 10:29:27 +00:00
# include "settings/settings_common.h"
2022-04-01 11:53:23 +00:00
# include "settings/settings_folders.h"
2020-06-11 09:41:03 +00:00
# include "api/api_updates.h"
2022-01-24 16:33:30 +00:00
# include "base/qt/qt_common_adapters.h"
2022-02-07 21:23:26 +00:00
# include "base/custom_app_icon.h"
2022-02-28 03:59:36 +00:00
# include "boxes/abstract_box.h" // Ui::show().
2018-09-06 13:48:01 +00:00
2022-06-05 09:31:55 +00:00
# include <zlib.h>
2021-08-23 09:17:40 +00:00
2018-09-06 13:48:01 +00:00
namespace Settings {
2020-03-26 10:29:27 +00:00
namespace {
using SessionController = Window : : SessionController ;
2018-09-06 13:48:01 +00:00
2021-08-23 09:17:40 +00:00
[[nodiscard]] QByteArray UnpackRawGzip ( const QByteArray & bytes ) {
z_stream stream ;
stream . zalloc = nullptr ;
stream . zfree = nullptr ;
stream . opaque = nullptr ;
stream . avail_in = 0 ;
stream . next_in = nullptr ;
int res = inflateInit2 ( & stream , - MAX_WBITS ) ;
if ( res ! = Z_OK ) {
return QByteArray ( ) ;
}
const auto guard = gsl : : finally ( [ & ] { inflateEnd ( & stream ) ; } ) ;
auto result = QByteArray ( 1024 * 1024 , char ( 0 ) ) ;
stream . avail_in = bytes . size ( ) ;
stream . next_in = reinterpret_cast < Bytef * > ( const_cast < char * > ( bytes . data ( ) ) ) ;
stream . avail_out = 0 ;
while ( ! stream . avail_out ) {
stream . avail_out = result . size ( ) ;
stream . next_out = reinterpret_cast < Bytef * > ( result . data ( ) ) ;
int res = inflate ( & stream , Z_NO_FLUSH ) ;
if ( res ! = Z_OK & & res ! = Z_STREAM_END ) {
return QByteArray ( ) ;
} else if ( ! stream . avail_out ) {
return QByteArray ( ) ;
}
}
result . resize ( result . size ( ) - stream . avail_out ) ;
return result ;
}
2018-09-06 13:48:01 +00:00
auto GenerateCodes ( ) {
2020-03-26 10:29:27 +00:00
auto codes = std : : map < QString , Fn < void ( SessionController * ) > > ( ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " debugmode " _q , [ ] ( SessionController * window ) {
2018-09-06 13:48:01 +00:00
QString text = Logs : : DebugEnabled ( )
2022-11-29 21:46:36 +00:00
? u " Do you want to disable DEBUG logs? " _q
: u " Do you want to enable DEBUG logs? \n \n All network events will be logged. " _q ;
2022-02-27 08:23:20 +00:00
Ui : : show ( Ui : : MakeConfirmBox ( { text , [ ] {
2019-01-21 13:42:21 +00:00
Core : : App ( ) . switchDebugMode ( ) ;
2022-02-27 08:23:20 +00:00
} } ) ) ;
2018-09-06 13:48:01 +00:00
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " viewlogs " _q , [ ] ( SessionController * window ) {
2018-09-06 13:48:01 +00:00
File : : ShowInFolder ( cWorkingDir ( ) + " log.txt " ) ;
} ) ;
if ( ! Core : : UpdaterDisabled ( ) ) {
2022-11-29 21:46:36 +00:00
codes . emplace ( u " testupdate " _q , [ ] ( SessionController * window ) {
2018-09-06 13:48:01 +00:00
Core : : UpdateChecker ( ) . test ( ) ;
} ) ;
}
2022-11-29 21:46:36 +00:00
codes . emplace ( u " loadlang " _q , [ ] ( SessionController * window ) {
Lang : : CurrentCloudManager ( ) . switchToLanguage ( { u " #custom " _q } ) ;
2018-09-06 13:48:01 +00:00
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " crashplease " _q , [ ] ( SessionController * window ) {
2018-09-06 13:48:01 +00:00
Unexpected ( " Crashed in Settings! " ) ;
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " moderate " _q , [ ] ( SessionController * window ) {
auto text = Core : : App ( ) . settings ( ) . moderateModeEnabled ( ) ? u " Disable moderate mode? " _q : u " Enable moderate mode? " _q ;
2022-02-27 08:23:20 +00:00
Ui : : show ( Ui : : MakeConfirmBox ( { text , [ = ] {
2020-06-18 18:04:16 +00:00
Core : : App ( ) . settings ( ) . setModerateModeEnabled ( ! Core : : App ( ) . settings ( ) . moderateModeEnabled ( ) ) ;
Core : : App ( ) . saveSettingsDelayed ( ) ;
2018-09-06 13:48:01 +00:00
Ui : : hideLayer ( ) ;
2022-02-27 08:23:20 +00:00
} } ) ) ;
2018-09-06 13:48:01 +00:00
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " getdifference " _q , [ ] ( SessionController * window ) {
2020-06-11 09:41:03 +00:00
if ( window ) {
window - > session ( ) . updates ( ) . getDifference ( ) ;
2018-09-06 13:48:01 +00:00
}
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " loadcolors " _q , [ ] ( SessionController * window ) {
2019-01-21 13:42:21 +00:00
FileDialog : : GetOpenPath ( Core : : App ( ) . getFileDialogParent ( ) , " Open palette file " , " Palette (*.tdesktop-palette) " , [ ] ( const FileDialog : : OpenResult & result ) {
2018-09-06 13:48:01 +00:00
if ( ! result . paths . isEmpty ( ) ) {
Window : : Theme : : Apply ( result . paths . front ( ) ) ;
}
} ) ;
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " endpoints " _q , [ ] ( SessionController * window ) {
2020-06-18 18:04:16 +00:00
if ( ! Core : : App ( ) . domain ( ) . started ( ) ) {
2020-06-17 09:36:25 +00:00
return ;
}
const auto weak = window
? base : : make_weak ( & window - > session ( ) . account ( ) )
: nullptr ;
FileDialog : : GetOpenPath ( Core : : App ( ) . getFileDialogParent ( ) , " Open DC endpoints " , " DC Endpoints (*.tdesktop-endpoints) " , [ weak ] ( const FileDialog : : OpenResult & result ) {
2018-09-06 13:48:01 +00:00
if ( ! result . paths . isEmpty ( ) ) {
2020-06-17 09:36:25 +00:00
const auto loadFor = [ & ] ( not_null < Main : : Account * > account ) {
if ( ! account - > mtp ( ) . dcOptions ( ) . loadFromFile ( result . paths . front ( ) ) ) {
2022-02-27 08:23:20 +00:00
Ui : : show ( Ui : : MakeInformBox ( " Could not load endpoints "
2021-10-18 22:28:08 +00:00
" :( Errors in 'log.txt'. " ) ) ;
2020-06-17 09:36:25 +00:00
}
} ;
if ( const auto strong = weak . get ( ) ) {
loadFor ( strong ) ;
} else {
2020-12-09 09:08:36 +00:00
for ( const auto & pair : Core : : App ( ) . domain ( ) . accounts ( ) ) {
loadFor ( pair . account . get ( ) ) ;
2020-06-17 09:36:25 +00:00
}
2018-09-06 13:48:01 +00:00
}
}
} ) ;
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " testmode " _q , [ ] ( SessionController * window ) {
2020-08-26 13:50:28 +00:00
auto & domain = Core : : App ( ) . domain ( ) ;
if ( domain . started ( )
& & ( domain . accounts ( ) . size ( ) = = 1 )
& & ! domain . active ( ) . sessionExists ( ) ) {
const auto environment = domain . active ( ) . mtp ( ) . environment ( ) ;
domain . addActivated ( [ & ] {
return ( environment = = MTP : : Environment : : Production )
? MTP : : Environment : : Test
: MTP : : Environment : : Production ;
} ( ) ) ;
Ui : : Toast : : Show ( ( environment = = MTP : : Environment : : Production )
? " Switched to the test environment. "
: " Switched to the production environment. " ) ;
}
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " folders " _q , [ ] ( SessionController * window ) {
2020-03-26 10:29:27 +00:00
if ( window ) {
2022-04-01 11:53:23 +00:00
window - > showSettings ( Settings : : Folders : : Id ( ) ) ;
2020-03-26 10:29:27 +00:00
}
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " registertg " _q , [ ] ( SessionController * window ) {
2021-07-18 03:25:01 +00:00
Core : : Application : : RegisterUrlScheme ( ) ;
2018-09-06 13:48:01 +00:00
Ui : : Toast : : Show ( " Forced custom scheme register. " ) ;
} ) ;
2020-06-25 07:14:05 +00:00
2022-11-29 21:46:36 +00:00
auto audioFilters = u " Audio files (*.wav *.mp3);; " _q + FileDialog : : AllFilesFilter ( ) ;
2018-09-06 13:48:01 +00:00
auto audioKeys = {
2022-11-29 21:46:36 +00:00
u " msg_incoming " _q ,
u " call_incoming " _q ,
u " call_outgoing " _q ,
u " call_busy " _q ,
u " call_connect " _q ,
u " call_end " _q ,
2018-09-06 13:48:01 +00:00
} ;
for ( auto & key : audioKeys ) {
2020-03-26 10:29:27 +00:00
codes . emplace ( key , [ = ] ( SessionController * window ) {
2020-06-18 18:04:16 +00:00
FileDialog : : GetOpenPath ( Core : : App ( ) . getFileDialogParent ( ) , " Open audio file " , audioFilters , [ = ] ( const FileDialog : : OpenResult & result ) {
if ( ! result . paths . isEmpty ( ) ) {
2018-09-06 13:48:01 +00:00
auto track = Media : : Audio : : Current ( ) . createTrack ( ) ;
track - > fillFromFile ( result . paths . front ( ) ) ;
if ( track - > failed ( ) ) {
2022-02-27 08:23:20 +00:00
Ui : : show ( Ui : : MakeInformBox (
2020-03-26 10:29:27 +00:00
" Could not audio :( Errors in 'log.txt'. " ) ) ;
2018-09-06 13:48:01 +00:00
} else {
2020-06-18 18:04:16 +00:00
Core : : App ( ) . settings ( ) . setSoundOverride (
2020-03-26 10:29:27 +00:00
key ,
result . paths . front ( ) ) ;
2020-06-18 18:04:16 +00:00
Core : : App ( ) . saveSettingsDelayed ( ) ;
2018-09-06 13:48:01 +00:00
}
}
2020-06-18 18:04:16 +00:00
} ) ;
2018-09-06 13:48:01 +00:00
} ) ;
}
2022-11-29 21:46:36 +00:00
codes . emplace ( u " sounds_reset " _q , [ ] ( SessionController * window ) {
2020-06-18 18:04:16 +00:00
Core : : App ( ) . settings ( ) . clearSoundOverrides ( ) ;
Core : : App ( ) . saveSettingsDelayed ( ) ;
2022-02-27 08:23:20 +00:00
Ui : : show ( Ui : : MakeInformBox ( " All sound overrides were reset. " ) ) ;
2018-09-06 13:48:01 +00:00
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " unpacklog " _q , [ ] ( SessionController * window ) {
2021-08-23 09:17:40 +00:00
FileDialog : : GetOpenPath ( Core : : App ( ) . getFileDialogParent ( ) , " Open crash log file " , " Crash dump (*.txt) " , [ = ] ( const FileDialog : : OpenResult & result ) {
if ( result . paths . isEmpty ( ) ) {
return ;
}
auto f = QFile ( result . paths . front ( ) ) ;
if ( ! f . open ( QIODevice : : ReadOnly ) ) {
Ui : : Toast : : Show ( " Could not open log :( " ) ;
return ;
}
const auto all = f . readAll ( ) ;
const auto log = all . indexOf ( " Log: " ) ;
if ( log < 0 ) {
Ui : : Toast : : Show ( " Could not find log :( " ) ;
return ;
}
const auto base = all . mid ( log + 5 ) ;
const auto end = base . indexOf ( ' \n ' ) ;
if ( end < = 0 ) {
Ui : : Toast : : Show ( " Could not find log end :( " ) ;
return ;
}
const auto based = QByteArray : : fromBase64 ( base . mid ( 0 , end ) ) ;
const auto uncompressed = UnpackRawGzip ( based ) ;
if ( uncompressed . isEmpty ( ) ) {
Ui : : Toast : : Show ( " Could not unpack log :( " ) ;
return ;
}
FileDialog : : GetWritePath ( Core : : App ( ) . getFileDialogParent ( ) , " Save detailed log " , " Crash dump (*.txt) " , QString ( ) , [ = ] ( QString & & result ) {
if ( result . isEmpty ( ) ) {
return ;
}
auto f = QFile ( result ) ;
if ( ! f . open ( QIODevice : : WriteOnly ) ) {
Ui : : Toast : : Show ( " Could not open details :( " ) ;
} else if ( f . write ( uncompressed ) ! = uncompressed . size ( ) ) {
Ui : : Toast : : Show ( " Could not write details :( " ) ;
} else {
f . close ( ) ;
Ui : : Toast : : Show ( " Done! " ) ;
}
} ) ;
} ) ;
} ) ;
2022-11-29 21:46:36 +00:00
codes . emplace ( u " testchatcolors " _q , [ ] ( SessionController * window ) {
2021-09-10 19:29:30 +00:00
const auto now = ! Data : : CloudThemes : : TestingColors ( ) ;
Data : : CloudThemes : : SetTestingColors ( now ) ;
Ui : : Toast : : Show ( now ? " Testing chat theme colors! " : " Not testing.. " ) ;
} ) ;
2019-09-26 14:26:36 +00:00
2022-02-07 21:23:26 +00:00
# ifdef Q_OS_MAC
2022-11-29 21:46:36 +00:00
codes . emplace ( u " customicon " _q , [ ] ( SessionController * window ) {
const auto iconFilters = u " Icon files (*.icns *.png);; " _q + FileDialog : : AllFilesFilter ( ) ;
2022-02-07 21:23:26 +00:00
const auto change = [ ] ( const QString & path ) {
const auto success = path . isEmpty ( )
? base : : ClearCustomAppIcon ( )
: base : : SetCustomAppIcon ( path ) ;
Ui : : Toast : : Show ( success
? ( path . isEmpty ( )
? " Icon cleared. Restarting the Dock. "
: " Icon updated. Restarting the Dock. " )
: ( path . isEmpty ( )
? " Icon clear failed. See log.txt for details. "
: " Icon update failed. See log.txt for details. " ) ) ;
} ;
FileDialog : : GetOpenPath ( Core : : App ( ) . getFileDialogParent ( ) , " Choose custom icon " , iconFilters , [ = ] ( const FileDialog : : OpenResult & result ) {
change ( result . paths . isEmpty ( ) ? QString ( ) : result . paths . front ( ) ) ;
} , [ = ] {
change ( QString ( ) ) ;
} ) ;
} ) ;
# endif // Q_OS_MAC
2018-09-06 13:48:01 +00:00
return codes ;
}
2020-03-26 10:29:27 +00:00
} // namespace
void CodesFeedString ( SessionController * window , const QString & text ) {
2018-09-06 13:48:01 +00:00
static const auto codes = GenerateCodes ( ) ;
static auto secret = QString ( ) ;
secret + = text . toLower ( ) ;
int size = secret . size ( ) , from = 0 ;
while ( size > from ) {
2021-10-19 13:00:21 +00:00
auto piece = base : : StringViewMid ( secret , from ) ;
2018-09-06 13:48:01 +00:00
auto found = false ;
for ( const auto & [ key , method ] : codes ) {
if ( piece = = key ) {
2020-03-26 10:29:27 +00:00
method ( window ) ;
2018-09-06 13:48:01 +00:00
from = size ;
found = true ;
break ;
}
}
if ( found ) break ;
2020-05-18 19:33:14 +00:00
found = ranges : : any_of ( codes , [ & ] ( const auto & pair ) {
2018-09-06 13:48:01 +00:00
return pair . first . startsWith ( piece ) ;
2020-05-18 19:33:14 +00:00
} ) ;
2018-09-06 13:48:01 +00:00
if ( found ) break ;
+ + from ;
}
secret = ( size > from ) ? secret . mid ( from ) : QString ( ) ;
}
} // namespace Settings