Giter Club home page Giter Club logo

Comments (7)

DM164 avatar DM164 commented on July 16, 2024 4

Can anyone respond to this? Would be really helpful...

from hazel.

jes-wd avatar jes-wd commented on July 16, 2024 2

Thanks. I ended up doing similar. I copied your code and modified it. I thought I'd leave it here in case anyone else needs it in the future. It's a bit rough right now but it works on Windows. Haven't developed for Mac at this stage.

In renderer process:

const https = require("https");
const { execFile } = require("child_process");

// check for updates and install if there is one
function checkForUpdates() {
  // document.getElementById('update-status').innerText = 'Checking for updates...'
  console.log("Checking for updates...");

  const platform = remote.process.platform;

  https.get(
    `https://my-app-name.jes-wd.vercel.app/update/${platform}/${remote.app.getVersion()}/`,
    (response) => {
      let data = "";

      //another chunk of data has been received, so append it to `str`
      response.on("data", function (chunk) {
        data += chunk;
      });

      response.on("error", function (err) {
        console.log(err);
      });

      //the whole response has been received
      response.on("end", function () {
        data = JSON.parse(data);
        console.log(data);
        const cachedVersion = data.name.substring(1);

        console.log("current app version: ", remote.app.getVersion());
        console.log("latest app version: ", cachedVersion);

        if (cachedVersion > remote.app.getVersion()) {
          console.log("Update required!");
          // document.getElementById('update-status').innerText = 'Update available!'
          ipcRenderer.send("download-update", cachedVersion);
        } else {
          // document.getElementById('update-status').innerText = 'No update available.'
          console.log("No update required");
        }
      });
    }
  );

  ipcRenderer.on("download-successful", (event, filePath) => {
    setTimeout(() => {
      installUpdate(filePath);
    }, 4000);
  });
}

function installUpdate(filePath) {

  console.log("install update..");

  const executablePath = filePath;

  execFile(executablePath, ['--version'], {maxBuffer: 1024 * 102400 }, function (err, data) {
    if (err) {
      console.error(err);
      return;
    }
    console.log(data.toString());
  });
}

checkForUpdates();

and in my main process, I added the following:

const ensureDirExists = require("./ensureDirExists");
const request = require("request");
const progress = require('request-progress');
const fs = require("fs");
const path = require('path');

ipcMain.on("download-update", function () {

    console.log("download-update ipcMain event ran");
    console.log("app path", path.dirname(process.execPath));

    const fileName = `my-app-name-Setup-${cachedVersion}.exe`;
    const dir = path.join(path.dirname(process.execPath), "/updates/");

    console.log("update file name: ", fileName);
    console.log('dir: ', dir);
    
    ensureDirExists(dir, 0744, function (err) {
      if (err) {
        console.log(err);
      } else {
        // The options argument is optional so you can omit it
        progress(request("https://my-app-name.jes-wd.vercel.app/download/win32?update=true"), {
          // throttle: 2000,                    // Throttle the progress event to 2000ms, defaults to 1000ms
          // delay: 1000,                       // Only start to emit after 1000ms delay, defaults to 0ms
          // lengthHeader: 'x-transfer-length'  // Length header to use, defaults to content-length
        })
          .on("progress", function (state) {
            console.log("progress", state);
          })
          .on("error", function (err) {
            console.log(err);
          })
          .on("end", function () {
            console.log("download successful");
            mainWindow.webContents.send("download-successful", dir + fileName);
          })
          .pipe(fs.createWriteStream(dir + fileName));
      } 
    });
  });

The ensureDirExists() function required in the main process looks like this:

const fs = require("fs");

function ensureDirExists(path, mask, cb) {
  if (typeof mask == 'function') { // allow the `mask` parameter to be optional
      cb = mask;
      mask = 0777;
  }
  fs.mkdir(path, mask, function(err) {
      if (err) {
          if (err.code == 'EEXIST') cb(null); // ignore the error if the folder already exists
          else cb(err); // something else went wrong
      } else cb(null); // successfully created folder
  });
}

module.exports = ensureDirExists;

from hazel.

jes-wd avatar jes-wd commented on July 16, 2024

I have the same issue. @DM164 did you ever figure it out?

from hazel.

DM164 avatar DM164 commented on July 16, 2024

I changed the cacheReleaseList function to this:

async cacheReleaseList(url) {
const { token } = this.config;
const headers = { Accept: "application/vnd.github.preview" };

if (token && typeof token === "string" && token.length > 0) {
  headers.Authorization = `token ${token}`;
}

const res = await retry(
  async () => {
    const response = await fetch(url, { headers });
    let buffer = await response.buffer();

    if (response.status !== 200) {
      throw new Error(
        `Tried to cache RELEASES, but failed fetching ${url}, status ${status}`
      );
    }

    return await buffer.toString("utf-8");
  },
  { retries: 3 }
);

const content = res;
const matches = content.match(/[^ ]*\.nupkg/gim);

if (matches.length === 0) {
  throw new Error(
    `Tried to cache RELEASES, but failed. RELEASES content doesn't contain nupkg`
  );
}

const nuPKG = url.replace("RELEASES", matches[0]);
return content.replace(matches[0], nuPKG);
}

and then I coded my electron app so that it downloads the .exe file and executes and installs it without using any package or library.

from hazel.

jes-wd avatar jes-wd commented on July 16, 2024

Thanks for the response.

I had already updated the cacheReleaseList function to that but sadly I still don't get a RELEASES file at /update/win32/:version/RELEASES

from hazel.

DM164 avatar DM164 commented on July 16, 2024

I know, for me it's the same so I gave up trying to fix it and solved it by adding this to my code:

let cachedVersion = ''
function checkForUpdates() {
    document.getElementById('update-status').innerText = 'Checking for updates...'

    const Http = new XMLHttpRequest();
    let platform = remote.process.platform
    if (platform === 'linux'){ platform = 'debian' }
    const url = `https://forget-me-not-update-server.vercel.app/update/${platform}/1.0.0/`;
    Http.open("GET", url);
    Http.send();

    Http.onloadend = (e) => {
        let response = JSON.parse(Http.responseText)
        cachedVersion = response.name
        if (response.name.length > 7) {
            cachedVersion = cachedVersion.slice(0, cachedVersion.length - 5)
        }
        if (cachedVersion > remote.app.getVersion()) {
            console.log('Update required!')
            document.getElementById('update-status').innerText = 'Update available!'
            ipcRenderer.send('download-update')
        } else {
            document.getElementById('update-status').innerText = 'No update available.'
            console.log('No update required')
        }
    }
}
function installUpdate() {
    const child = require('child_process').execFile;
    let executablePath = null

    if (remote.process.platform === 'win32'){
        executablePath = path.join(__dirname, `../updates/files/forget_me_not-${cachedVersion}-setup.exe`)
    }else if (remote.process.platform === 'linux'){
        executablePath = path.join(__dirname, `../updates/files/forget-me-not_${cachedVersion}_amd64.deb`)
    }

    child(executablePath, function (err, data) {
        if (err) {
            console.error(err);
            return;
        }
        console.log(data.toString());
    });
}
ipcRenderer.on('download-successfull', () => {
    setTimeout(() => {
        installUpdate()
    }, 4000);
})

It doesn't really fix the issue, it's a work around but at least I can update my app now and it works reliably.

from hazel.

wobedi avatar wobedi commented on July 16, 2024

Sharing what worked for me:
#79 (comment)

from hazel.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.