update checker

This commit is contained in:
GenevensiS
2026-02-08 02:27:19 +01:00
parent 42b9c241f3
commit 46414307fd
36 changed files with 917 additions and 544 deletions
+317
View File
@@ -0,0 +1,317 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make card games |
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// ----------------------------------------------------------------------------- : Includes
#include <wx/wxprec.h>
#include <wx/webrequest.h>
#include <wx/process.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include <wx/filename.h>
#include <wx/stdpaths.h>
#include <unordered_map>
// ----------------------------------------------------------------------------- : Payload URL
static const wxString url = wxString("https://github.com/MagicSetEditorPacks/Installer-Pack/raw/refs/heads/main/magicseteditor.zip");
// ----------------------------------------------------------------------------- : Localized Text
const std::unordered_map<wxString, wxString> update_map = [] {
std::unordered_map<wxString, wxString> map = {
{ _("en"), _("Magic Set Editor will now update itself.") }
, { _("chs"), _("Magic Set Editor现在将自动更新。") }
, { _("cht"), _("Magic Set Editor現在將自動更新。") }
, { _("da"), _("Magic Set Editor opdaterer nu sig selv.") }
, { _("de"), _("Magic Set Editor wird nun aktualisiert.") }
, { _("es"), _("Magic Set Editor se actualizará automáticamente.") }
, { _("fr"), _("Magic Set Editor va maintenant se mettre à jour.") }
, { _("it"), _("Magic Set Editor si aggiornerà automaticamente.") }
, { _("jp"), _("Magic Set Editorが自動的に更新されます。") }
, { _("ko"), _("Magic Set Editor가 이제 자동으로 업데이트됩니다.") }
, { _("pl"), _("Magic Set Editor zaktualizuje się teraz samoczynnie.") }
, { _("ptbr"), _("Magic Set Editor será atualizado automaticamente.") }
, { _("ru"), _("Сейчас произойдет обновление Magic Set Editor ") }
};
return map;
}();
const std::unordered_map<wxString, wxString> close_map = [] {
std::unordered_map<wxString, wxString> map = {
{ _("en"), _("Please close all other Magic Set Editor windows, then click OK.") }
, { _("chs"), _("请关闭所有其他Magic Set Editor窗口,然后单击“OK”。") }
, { _("cht"), _("請關閉所有其他Magic Set Editor窗口,然後按一下“OK”。") }
, { _("da"), _("Luk alle andre Magic Set Editor-vinduer, og klik derefter på OK.") }
, { _("de"), _("Bitte schließen Sie alle anderen Fenster des Magic Set Editor und klicken Sie anschließend auf OK.") }
, { _("es"), _("Cierre todas las demás ventanas de Magic Set Editor y haga clic en OK.") }
, { _("fr"), _("Veuillez fermer toutes les autres fenêtres de Magic Set Editor, puis cliquez sur OK.") }
, { _("it"), _("Chiudere tutte le altre finestre di Magic Set Editor, quindi fare clic su OK.") }
, { _("jp"), _("他のMagic Set Editorウィンドウをすべて閉じて、「OK」をクリックしてください。") }
, { _("ko"), _("다른 Magic Set Editor 창을 모두 닫은 다음 OK을 클릭하십시오.") }
, { _("pl"), _("Zamknij wszystkie pozostałe okna Magic Set Editor, a następnie kliknij OK.") }
, { _("ptbr"), _("Feche todas as outras janelas do Magic Set Editor e clique em OK") }
, { _("ru"), _("Пожалуйста, закройте все остальные окна Magic Set Editor, затем нажмите ОК.") }
};
return map;
}();
// ----------------------------------------------------------------------------- : Events
wxDEFINE_EVENT(wxEVT_EXTRACTION, wxThreadEvent);
wxDEFINE_EVENT(wxEVT_FAIL, wxThreadEvent);
wxDEFINE_EVENT(wxEVT_SUCCESS, wxThreadEvent);
// ----------------------------------------------------------------------------- : Classes
class MSEUpdater : public wxApp {
public:
virtual bool OnInit();
};
IMPLEMENT_APP(MSEUpdater)
class Thread;
class Frame : public wxFrame {
public:
Frame(wxString locale);
void OnExtraction(wxThreadEvent& event);
void OnFail (wxThreadEvent& event);
void OnSuccess (wxThreadEvent& event);
void OnOK (wxCommandEvent& event);
void DoFail (const wxString& error);
wxStaticText* status;
wxStaticText* address;
wxButton* button;
Thread* thread;
bool OK = false;
};
class Thread : public wxThread {
public:
Thread(Frame* frame);
void NotifyExtraction(const wxString& file);
void NotifyFail (const wxString& error);
void NotifySuccess (const wxString& app_folder);
virtual wxThread::ExitCode Entry();
Frame* frame;
};
// ----------------------------------------------------------------------------- : Methods
bool MSEUpdater::OnInit() {
Appearance darkmode = Appearance::System;
wxString locale = wxString("en");
for (int i = 0; i < argc; ++i) {
wxString arg = wxString(argv[i]);
if (arg.StartsWith("darkmode") && arg.size() > 8) {
darkmode = arg.GetChar(8) == '1' ? Appearance::Dark : Appearance::Light;
}
else if (arg.StartsWith("locale") && arg.size() > 6) {
locale = arg.substr(6);
}
}
SetAppearance(darkmode);
Frame *frame = new Frame(locale);
SetTopWindow(frame);
frame->Show();
return true;
}
Frame::Frame(wxString locale) : wxFrame(nullptr, wxID_ANY, wxString("Magic Set Editor Updater")) {
// Set app icon
wxLogNull noLog;
#if defined(__WXMSW__) && !defined(__GNUC__)
SetIcon(wxIcon(_("updater")));
#else
SetIcon(wxIcon(wxStandardPaths::Get().GetDataDir() + _("/src_updater/updater.ico"), wxBITMAP_TYPE_ICO));
#endif
// Create controls
wxString update_text = update_map.find(locale) != update_map.end() ? update_map.at(locale) : update_map.at("en");
wxString close_text = close_map.find(locale) != close_map.end() ? close_map.at(locale) : close_map.at("en");
status = new wxStaticText(this, wxID_ANY, update_text, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL | wxALIGN_CENTRE_VERTICAL | wxST_NO_AUTORESIZE);
address = new wxStaticText(this, wxID_ANY, close_text, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL | wxALIGN_CENTRE_VERTICAL | wxST_NO_AUTORESIZE);
button = new wxButton (this, wxID_OK, wxString("OK"));
wxFont font = status->GetFont().Scale(1.2f);
status ->SetFont(font);
address->SetFont(font);
button ->SetFont(font);
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(status, 1, wxEXPAND | wxALL, 12);
sizer->Add(address, 1, wxEXPAND | (wxALL & ~wxTOP), 12);
sizer->Add(button, 1, wxEXPAND, 12);
sizer->SetMinSize(wxSize(800, -1));
SetSizerAndFit(sizer);
// Bind events
Bind(wxEVT_EXTRACTION, &Frame::OnExtraction, this);
Bind(wxEVT_SUCCESS, &Frame::OnSuccess, this);
Bind(wxEVT_FAIL, &Frame::OnFail, this);
Bind(wxEVT_BUTTON, &Frame::OnOK, this, wxID_OK);
// Run thread
thread = new Thread(this);
if (thread->Create() == wxTHREAD_NO_ERROR) {
thread->Run();
}
}
void Frame::OnExtraction(wxThreadEvent& event) {
status->SetLabelText(wxString("Extracting File To:"));
address->SetLabelText(event.GetString());
Update();
}
void Frame::OnFail(wxThreadEvent& event) {
DoFail(event.GetString());
}
void Frame::DoFail(const wxString& error) {
thread->Kill();
status->SetForegroundColour(wxColor(*wxRED));
status->SetLabelText(error);
address->SetLabelText(wxString(""));
Update();
wxMilliSleep(3000);
Destroy();
}
void Frame::OnSuccess(wxThreadEvent& event) {
wxString path = event.GetString() + wxString("magicseteditor");
path = path + wxString(".exe");
long processID = wxFileExists(path) ? wxExecute(path, wxEXEC_ASYNC) : 0L;
if (processID == 0L) {
DoFail(wxString("Could not launch Magic Set Editor."));
}
else {
status->SetLabelText(wxString("Launching Magic Set Editor."));
address->SetLabelText(wxString(""));
Update();
wxMilliSleep(800);
Destroy();
}
}
void Frame::OnOK(wxCommandEvent& event) {
if (!OK) {
button->Enable(false);
button->SetLabel(wxString("Cancel"));
status->SetLabelText(wxString("Downloading New Version From:"));
address->SetLabelText(url);
Update();
wxMilliSleep(200);
button->Enable(true);
wxMilliSleep(100);
OK = true;
}
else {
thread->Kill();
Destroy();
}
}
Thread::Thread(Frame* frame) : wxThread(wxTHREAD_DETACHED), frame(frame) {}
void Thread::NotifyExtraction(const wxString& file) {
wxThreadEvent* event = new wxThreadEvent(wxEVT_EXTRACTION);
event->SetString(file);
wxQueueEvent(frame, event);
}
void Thread::NotifyFail(const wxString& error) {
wxThreadEvent* event = new wxThreadEvent(wxEVT_FAIL);
event->SetString(error);
wxQueueEvent(frame, event);
}
void Thread::NotifySuccess(const wxString& app_folder) {
wxThreadEvent* event = new wxThreadEvent(wxEVT_SUCCESS);
event->SetString(app_folder);
wxQueueEvent(frame, event);
}
wxThread::ExitCode Thread::Entry() {
try {
// Get app folder
wxFileName updater_folder = wxFileName(wxStandardPaths::Get().GetExecutablePath());
updater_folder.RemoveLastDir();
if (!updater_folder.GetPath().EndsWith(wxString("data"))) {
NotifyFail("Updater package is not in the 'data' folder.");
return (ExitCode)-1;
}
updater_folder.RemoveLastDir();
wxString app_folder = updater_folder.GetPath() + wxFileName::GetPathSeparator();
// Fetch zip from url
wxWebRequestSync request = wxWebSessionSync::GetDefault().CreateRequest(url);
auto const result = request.Execute();
if (!result) {
NotifyFail("Download Failed.");
return (ExitCode)-1;
}
wxInputStream* is = request.GetResponse().GetStream();
if (!is->IsOk()) {
NotifyFail("Download Corrupted.");
return (ExitCode)-1;
}
// Stall until the user gives the go ahead
while (!frame->OK) {
wxMilliSleep(50);
wxYield();
}
// Extract files from zip
wxZipInputStream zis(is);
if (!zis.IsOk()) {
NotifyFail("Zip Archive Corrupted.");
return (ExitCode)-1;
}
std::unique_ptr<wxZipEntry> entry;
while (entry.reset(zis.GetNextEntry()), entry.get() != nullptr) {
wxString target_path = app_folder + entry->GetName();
int nPermBits = entry->GetMode();
if (entry->IsDir()) {
if (!wxDirExists(target_path)) wxFileName::Mkdir(target_path, nPermBits, wxPATH_MKDIR_FULL);
continue;
}
NotifyExtraction(target_path);
wxFileName fn;
fn.Assign(target_path);
if (!wxDirExists(fn.GetPath())) wxFileName::Mkdir(fn.GetPath(), nPermBits, wxPATH_MKDIR_FULL);
if (!zis.CanRead()) {
NotifyFail("Extraction Failed.");
return (ExitCode)-1;
}
wxFileOutputStream fos(target_path);
if (!fos.IsOk()) {
NotifyFail("Writing Failed. Magic Set Editor may still be open.");
return (ExitCode)-1;
}
zis.Read(fos);
fos.Close();
zis.CloseEntry();
}
NotifySuccess(app_folder);
wxMilliSleep(200);
return (ExitCode)0;
}
catch (...) {
NotifyFail("Something Went Wrong.");
return (ExitCode)-1;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

+9
View File
@@ -0,0 +1,9 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2017 Twan van Laarhoven and "coppro" |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// -------------------------------------------------------- : Icon
updater ICON "updater.ico"