<commit_before>'use strict'
const crypto = require('crypto')
const querystring = require('querystring')
require('isomorphic-fetch')
const winston = require('winston')

const log = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)({
      colorize: true,
      timestamp: true,
    }),
  ],
})

let accessToken
;(() => {
  if (accessToken) {
    log.info(' we have an access token ')
    log.info('getting user\'s saved tracks')
    collectTracks().then(organizeTracks).then(createPlaylists)
  }
})()

// returns a Promise
function getTracks(offset) {
  const getTracksURL = 'https://api.spotify.com/v1/me/tracks'
  const headers = new Headers()
  headers.set('Authorization', `Bearer ${accessToken}`)
  const qs = querystring.stringify({ limit: 50, offset })
  return fetch(`${getTracksURL}?${qs}`, { headers }).then(r => r.json())
}

let tracksArr = []
// takes an HTTP response, returns total number of tracks
function storeTracks(response) {
  tracksArr = tracksArr.concat(response.items)
  return response.total
}

function collectTracks() {
  return getTracks(0).then(r => {
    const totalTracks = storeTracks(r)
    const promises = []
    for (let offset = 50; offset < totalTracks; offset += 50) {
      promises.push(getTracks(offset))
    }
    return Promise.all(promises).then(responses => {
      responses.forEach(curr => {
        storeTracks(curr)
      })
      return Promise.resolve()
    })
  }).catch(e => {
    // TODO: handle error gracefully
    throw e
  })
}

/**
 * returns a promise with artistMap parameter
 *  tracks
 *  genres
 */
function organizeTracks() {
  const artistIDs = new Set()
  const artistMap = new Map()
  tracksArr.forEach(c => {
    artistIDs.add(c.track.artists[0].id)
    if (artistMap.has(c.track.artists[0].id)) {
      artistMap.get(c.track.artists[0].id).tracks.push(c.track.id)
    } else {
      artistMap.set(c.track.artists[0].id, { tracks: [c.track.id], genres: [] })
    }
  })
  const promises = []
  promises.push(getGenres(artistIDs).then(responses => {
    let populated = 0
    responses.forEach(r => {
      r.artists.forEach(c => {
        // NOTE: c.genres is empty on all entries!!!
        if (c.genres.length) populated++
        artistMap.get(c.id).genres = c.genres
      })
    })
    log.debug(populated, '/', artistIDs.size)
    return Promise.resolve(artistMap)
  }))
  promises.push(getTerms(artistIDs).then(rArr => {
    let populated = 0
    rArr.forEach(r => {
      populated++
      log.debug(r.id())
      artistMap.get(r.id()).terms = r.response.terms
    })
    log.debug(populated, '/', artistIDs.size)
    return Promise.resolve(artistMap)
  }))
  return Promise.all(promises)
}

function getGenres(artists) {
  const artistsURL = 'https://api.spotify.com/v1/artists'
  const artistsArr = Array.from(artists)
  const promises = []

  const headers = new Headers()
  headers.set('Authorization', `Bearer ${accessToken}`)

  for (let i = 0; i < artistsArr.length; i += 50) {
    const qs = querystring.stringify({ ids: artistsArr.slice(i, i + 50).join() })
    promises.push(fetch(`${artistsURL}?${qs}`, { headers }).then(r => r.json()))
  }
  return Promise.all(promises)
}

function getTerms(artists) {
  const termsURL = 'http://developer.echonest.com/api/v4/artist/terms'
  const ECHONEST_API_KEY = process.env.ECHONEST_API_KEY
  const artistsArr = Array.from(artists).splice(0, 5)
  const promises = []

  artistsArr.forEach(a => {
    const qs = querystring.stringify({
      api_key: ECHONEST_API_KEY,
      id: `spotify:artist:${a}`,
    })
    promises.push(fetch(`${termsURL}?${qs}`).then(r => r.json()).then(r => {
      const r2 = r
      // enclose a
      r2.id = (retVal => () => retVal)(a)
      return Promise.resolve(r2)
    }))
  })
  return Promise.all(promises)
}

const playlists = new Map()
function createPlaylists(map) {
  log.debug(map)
  map[0].forEach(v => {
    try {
      // organize by genre
      v.genres.forEach(g => {
        v.tracks.forEach(t => {
          if (playlists.has(g)) {
            playlists.get(g).push(t)
          } else {
            playlists.set(g, [t])
          }
        })
      })
      // organize by terms
      if (v.terms && v.terms.length) {
        const term = v.terms[0].name
        v.tracks.forEach(t => {
          if (playlists.has(term)) {
            playlists.get(term).push(t)
          } else {
            playlists.set(term, [t])
          }
        })
        log.debug(term)
      }
    } catch (e) {
      log.error(e)
      log.error('failed on', v)
    }
  })
  log.info(playlists)
}

const authURL = 'https://accounts.spotify.com/authorize'
const stateString = crypto.randomBytes(64).toString('hex')
const authParams = {
  client_id: process.env.SPOTIFY_CLIENT_ID,
  response_type: 'token',
  redirect_uri: 'http://localhost:8080',
  state: stateString,
  scope: 'playlist-modify-public user-library-read',
  // show_dialog
}

//got(authURL, {query: authParams}).then(response => {
//  console.log(response.body)
//}).catch(e => {
//  console.error(e)
//})
<commit_msg>First step of Authorization Code Flow: get authorization code.<commit_after>'use strict'
const http = require('http')
const url = require('url')
const crypto = require('crypto')
const querystring = require('querystring')
require('isomorphic-fetch')
const winston = require('winston')

const log = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)({
      colorize: true,
      timestamp: true,
    }),
  ],
})

let accessToken
;(() => {
  if (accessToken) {
    log.info(' we have an access token ')
    log.info('getting user\'s saved tracks')
    collectTracks().then(organizeTracks).then(createPlaylists)
  }
})()

function getAuthURL() {
  const authURL = 'https://accounts.spotify.com/authorize'
  // const stateString = crypto.randomBytes(64).toString('hex')
  const authParams = {
    client_id: process.env.SPOTIFY_CLIENT_ID,
    response_type: 'code',
    redirect_uri: 'http://localhost:8080',
    // state: stateString,
    scope: 'playlist-modify-public user-library-read',
  }
  return `${authURL}?${querystring.stringify(authParams)}`
}

function server() {
  http.createServer((req, res) => {
    const urlObj = url.parse(req.url, true)
    log.info(urlObj)
    if (urlObj.query) {
      res.end()
      urlObj.query.code

    } else {
      const html = `<!DOCTYPE html>
        <button onclick="document.location.assign('${getAuthURL()}')">
          Click to Authorize
        </button>`
      res.end(html)
    }
  }).listen(8080)
}
server()

// returns a Promise
function getTracks(offset) {
  const getTracksURL = 'https://api.spotify.com/v1/me/tracks'
  const headers = new Headers()
  headers.set('Authorization', `Bearer ${accessToken}`)
  const qs = querystring.stringify({ limit: 50, offset })
  return fetch(`${getTracksURL}?${qs}`, { headers }).then(r => r.json())
}

let tracksArr = []
// takes an HTTP response, returns total number of tracks
function storeTracks(response) {
  tracksArr = tracksArr.concat(response.items)
  return response.total
}

function collectTracks() {
  return getTracks(0).then(r => {
    const totalTracks = storeTracks(r)
    const promises = []
    for (let offset = 50; offset < totalTracks; offset += 50) {
      promises.push(getTracks(offset))
    }
    return Promise.all(promises).then(responses => {
      responses.forEach(curr => {
        storeTracks(curr)
      })
      return Promise.resolve()
    })
  }).catch(e => {
    // TODO: handle error gracefully
    throw e
  })
}

/**
 * returns a promise with artistMap parameter
 *  tracks
 *  genres
 */
function organizeTracks() {
  const artistIDs = new Set()
  const artistMap = new Map()
  tracksArr.forEach(c => {
    artistIDs.add(c.track.artists[0].id)
    if (artistMap.has(c.track.artists[0].id)) {
      artistMap.get(c.track.artists[0].id).tracks.push(c.track.id)
    } else {
      artistMap.set(c.track.artists[0].id, { tracks: [c.track.id], genres: [] })
    }
  })
  const promises = []
  promises.push(getGenres(artistIDs).then(responses => {
    let populated = 0
    responses.forEach(r => {
      r.artists.forEach(c => {
        // NOTE: c.genres is empty on all entries!!!
        if (c.genres.length) populated++
        artistMap.get(c.id).genres = c.genres
      })
    })
    log.debug(populated, '/', artistIDs.size)
    return Promise.resolve(artistMap)
  }))
  promises.push(getTerms(artistIDs).then(rArr => {
    let populated = 0
    rArr.forEach(r => {
      populated++
      log.debug(r.id())
      artistMap.get(r.id()).terms = r.response.terms
    })
    log.debug(populated, '/', artistIDs.size)
    return Promise.resolve(artistMap)
  }))
  return Promise.all(promises)
}

function getGenres(artists) {
  const artistsURL = 'https://api.spotify.com/v1/artists'
  const artistsArr = Array.from(artists)
  const promises = []

  const headers = new Headers()
  headers.set('Authorization', `Bearer ${accessToken}`)

  for (let i = 0; i < artistsArr.length; i += 50) {
    const qs = querystring.stringify({ ids: artistsArr.slice(i, i + 50).join() })
    promises.push(fetch(`${artistsURL}?${qs}`, { headers }).then(r => r.json()))
  }
  return Promise.all(promises)
}

function getTerms(artists) {
  const termsURL = 'http://developer.echonest.com/api/v4/artist/terms'
  const ECHONEST_API_KEY = process.env.ECHONEST_API_KEY
  const artistsArr = Array.from(artists).splice(0, 5)
  const promises = []

  artistsArr.forEach(a => {
    const qs = querystring.stringify({
      api_key: ECHONEST_API_KEY,
      id: `spotify:artist:${a}`,
    })
    promises.push(fetch(`${termsURL}?${qs}`).then(r => r.json()).then(r => {
      const r2 = r
      // enclose a
      r2.id = (retVal => () => retVal)(a)
      return Promise.resolve(r2)
    }))
  })
  return Promise.all(promises)
}

const playlists = new Map()
function createPlaylists(map) {
  log.debug(map)
  map[0].forEach(v => {
    try {
      // organize by genre
      v.genres.forEach(g => {
        v.tracks.forEach(t => {
          if (playlists.has(g)) {
            playlists.get(g).push(t)
          } else {
            playlists.set(g, [t])
          }
        })
      })
      // organize by terms
      if (v.terms && v.terms.length) {
        const term = v.terms[0].name
        v.tracks.forEach(t => {
          if (playlists.has(term)) {
            playlists.get(term).push(t)
          } else {
            playlists.set(term, [t])
          }
        })
        log.debug(term)
      }
    } catch (e) {
      log.error(e)
      log.error('failed on', v)
    }
  })
  log.info(playlists)
}
<|endoftext|>


<commit_before>const electron = require('electron')
// Module to control application life.
const {app, globalShortcut} = require('electron')

const {ipcMain} = require('electron')

// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow

var path = require('path')
var iconPath = path.join(__dirname, '/listen1_chrome_extension/images/logo.png');

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
let willQuitApp = false;
var windowState = { maximized: false }

const globalShortcutMapping = {
  'CmdOrCtrl+Alt+Left':'left',
  'CmdOrCtrl+Alt+Right':'right',
  'CmdOrCtrl+Alt+Space':'space',
};

function initialTray(mainWindow) {
  const {app, Menu, Tray} = require('electron');

  let appIcon = null;

  var trayIconPath = path.join(__dirname, '/resources/logo_16.png');
  appTray = new Tray(trayIconPath);

  function toggleVisiable() {
    var isVisible = mainWindow.isVisible();
    if (isVisible) {
      mainWindow.hide();
    } else {
      mainWindow.show();
    }
  }
  const contextMenu = Menu.buildFromTemplate([
    {label: '显示/隐藏窗口',  click(){
      toggleVisiable();
    }},
    {label: '退出',  click() {
      app.quit();
    }},
  ]);
  //appTray.setToolTip('This is my application.');
  appTray.setContextMenu(contextMenu);
  appTray.on('click', function handleClicked () {
    toggleVisiable();
  });
}

function setKeyMapping(key, message) {
    const ret = globalShortcut.register(key, () => {
      mainWindow.webContents.send('globalShortcut', message);
    });
}

function enableGlobalShortcuts() {
  // initial global shortcuts
  for (let key in globalShortcutMapping){
    setKeyMapping(key, globalShortcutMapping[key]);
  }
}

function disableGlobalShortcuts() {
  for (let key in globalShortcutMapping){
    globalShortcut.unregister(key);
  }

  globalShortcut.unregisterAll()
}

let floatingWindow;
const createFloatingWindow = function () {
  const electron = require('electron');
  const BrowserWindow = electron.BrowserWindow;
  const display = electron.screen.getPrimaryDisplay();
  if (!floatingWindow) {
    floatingWindow = new BrowserWindow({
      width: 1000,
      height: 80,
      titleBarStyle: 'hide',
      transparent: true,
      frame: false,
      resizable: false,
      hasShadow: false,
      alwaysOnTop:true,
      visibleOnAllWorkspaces: true,
      webPreferences: {
        nodeIntegration: true
      }
    });
    floatingWindow.setPosition(floatingWindow.getPosition()[0], display.bounds.height - 150);
    floatingWindow.setSkipTaskbar(true);
    floatingWindow.loadURL(`file://${__dirname}/floatingWindow.html`);
    floatingWindow.setAlwaysOnTop(true, 'floating');
    floatingWindow.on('closed', function () { floatingWindow = null })
  }
  floatingWindow.showInactive();
};

function createWindow() {

  const session = require('electron').session;

  const filter = {
    urls: ["*://music.163.com/*", "*://*.xiami.com/*", "*://i.y.qq.com/*", "*://c.y.qq.com/*", "*://*.kugou.com/*", "*://*.kuwo.cn/*", "*://*.bilibili.com/*", "*://*.migu.cn/*", "*://*.githubusercontent.com/*",
      "https://listen1.github.io/listen1/callback.html?code=*"]
  };

  session.defaultSession.webRequest.onBeforeSendHeaders(filter, function(details, callback) {
    if(details.url.startsWith("https://listen1.github.io/listen1/callback.html?code=")){
      const url = details.url;
      const code = url.split('=')[1];
      mainWindow.webContents.executeJavaScript('Github.handleCallback("'+code+'");');
    }
    else {
      hack_referer_header(details);
    }
    callback({cancel: false, requestHeaders: details.requestHeaders});
  });

  var transparent = false;
  if (process.platform == 'darwin') {
    transparent = true;
  }
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1000,
    height: 670,
    webPreferences: {'nodeIntegration': true},
    icon: iconPath,
    titleBarStyle: 'hiddenInset',
    transparent: transparent,
    vibrancy: 'light',
    frame: false,
    hasShadow: true
  });

  // mainWindow.webContents.openDevTools();

  mainWindow.on('close', (e) => {
    if (willQuitApp) {
      /* the user tried to quit the app */
      mainWindow = null;
    } else {
      /* the user only tried to close the window */
      //if (process.platform != 'linux') {
        e.preventDefault();
        mainWindow.hide();
        //mainWindow.minimize();
      //}

    }
  });

  // and load the index.html of the app.
  var ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36';
  mainWindow.loadURL(`file://${__dirname}/listen1_chrome_extension/listen1.html`, {userAgent: ua})

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
  })

  // define global menu content, also add support for cmd+c and cmd+v shortcuts
  var template = [{
      label: "Application",
      submenu: [
          { label: "About Application", selector: "orderFrontStandardAboutPanel:" },
          { type: "separator" },
          { label: "Quit", accelerator: "Command+Q", click: function() { app.quit(); }}
      ]}, {
      label: "Edit",
      submenu: [
          { label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" },
          { label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
          { type: "separator" },
          { label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
          { label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
          { label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" },
          { label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
      ]}
  ];

  mainWindow.setMenu(null);

  electron.Menu.setApplicationMenu(electron.Menu.buildFromTemplate(template));

  initialTray(mainWindow);
}

function hack_referer_header(details) {
    let replace_referer = true;
    let replace_origin = true;
    let add_referer = true;
    let add_origin = true;
    var referer_value = '';

    if (details.url.indexOf("://music.163.com/") != -1) {
        referer_value = "http://music.163.com/";
    }
    if (details.url.indexOf("://gist.githubusercontent.com/") != -1) {
        referer_value = "https://gist.githubusercontent.com/";
    }

    if (details.url.indexOf("api.xiami.com/") != -1 || details.url.indexOf('.xiami.com/song/playlist/id/') != -1) {
        referer_value = "https://www.xiami.com/";
    }

    if ((details.url.indexOf("y.qq.com/") != -1) ||
        (details.url.indexOf("qqmusic.qq.com/") != -1) ||
        (details.url.indexOf("music.qq.com/") != -1) ||
        (details.url.indexOf("imgcache.qq.com/") != -1)) {
        referer_value = "http://y.qq.com/";
    }
    if (details.url.indexOf(".kugou.com/") != -1) {
        referer_value = "http://www.kugou.com/";
    }
    if (details.url.indexOf(".kuwo.cn/") != -1) {
        referer_value = "http://www.kuwo.cn/";
    }
    if (details.url.indexOf(".bilibili.com/") != -1) {
        referer_value = "http://www.bilibili.com/";
        replace_origin = false;
        add_origin = false;
    }
    if (details.url.indexOf('.migu.cn') !== -1) {
        referer_value = 'http://music.migu.cn/v3/music/player/audio?from=migu';
    }

    var isRefererSet = false;
    var isOriginSet = false;
    var headers = details.requestHeaders,
        blockingResponse = {};

    for (var i = 0, l = headers.length; i < l; ++i) {
        if (replace_referer && (headers[i].name == 'Referer') && (referer_value != '')) {
            headers[i].value = referer_value;
            isRefererSet = true;
        }
        if (replace_origin && (headers[i].name == 'Origin') && (referer_value != '')) {
            headers[i].value = referer_value;
            isOriginSet = true;
        }
    }

    if (add_referer && (!isRefererSet) && (referer_value != '')) {
        headers["Referer"] = referer_value;
    }

    if (add_origin && (!isOriginSet) && (referer_value != '')) {
        headers["Origin"] = referer_value;
    }

    details.requestHeaders = headers;
};

ipcMain.on('currentLyric', (event, arg) => {
  if (floatingWindow && floatingWindow !== null) {
    if(typeof arg === 'string') {
      floatingWindow.webContents.send('currentLyric', arg);
      floatingWindow.webContents.send('currentLyricTrans', '');
    } else {
      floatingWindow.webContents.send('currentLyric', arg.lyric);
      floatingWindow.webContents.send('currentLyricTrans', arg.tlyric);
    }
  }
})

ipcMain.on('control', (event, arg) => {
  // console.log(arg);
  if(arg == 'enable_global_shortcut') {
    enableGlobalShortcuts();
  }
  else if(arg == 'disable_global_shortcut') {
    disableGlobalShortcuts();
  }
  else if (arg == 'enable_lyric_floating_window') {
    createFloatingWindow();
  }
  else if (arg == 'disable_lyric_floating_window') {
    if (floatingWindow) {
      floatingWindow.hide();
    }
  }
  else if(arg == 'window_min') {
    mainWindow.minimize();
  }
  else if(arg == 'window_max') {
    if(windowState.maximized == true) {
        windowState.maximized = false;
        mainWindow.unmaximize();
      } else {
        windowState.maximized = true;
        mainWindow.maximize();
      }
  }
  else if(arg == 'window_close') {
    mainWindow.close();
  }
  // event.sender.send('asynchronous-reply', 'pong')
})

const gotTheLock = app.requestSingleInstanceLock()

if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore()
      mainWindow.focus()
    }
  })

  // Create myWindow, load the rest of the app, etc...
  app.on('ready', () => {
    createWindow()
  })
}

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

/* 'activate' is emitted when the user clicks the Dock icon (OS X) */
app.on('activate', () => mainWindow.show());

/* 'before-quit' is emitted when Electron receives
 * the signal to exit and wants to start closing windows */
app.on('before-quit', () => willQuitApp = true);

app.on('will-quit', () => {
 disableGlobalShortcuts();
})

<commit_msg>fix bilibili music play fail bug<commit_after>const electron = require('electron')
// Module to control application life.
const {app, globalShortcut} = require('electron')

const {ipcMain} = require('electron')

// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow

var path = require('path')
var iconPath = path.join(__dirname, '/listen1_chrome_extension/images/logo.png');

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
let willQuitApp = false;
var windowState = { maximized: false }

const globalShortcutMapping = {
  'CmdOrCtrl+Alt+Left':'left',
  'CmdOrCtrl+Alt+Right':'right',
  'CmdOrCtrl+Alt+Space':'space',
};

function initialTray(mainWindow) {
  const {app, Menu, Tray} = require('electron');

  let appIcon = null;

  var trayIconPath = path.join(__dirname, '/resources/logo_16.png');
  appTray = new Tray(trayIconPath);

  function toggleVisiable() {
    var isVisible = mainWindow.isVisible();
    if (isVisible) {
      mainWindow.hide();
    } else {
      mainWindow.show();
    }
  }
  const contextMenu = Menu.buildFromTemplate([
    {label: '显示/隐藏窗口',  click(){
      toggleVisiable();
    }},
    {label: '退出',  click() {
      app.quit();
    }},
  ]);
  //appTray.setToolTip('This is my application.');
  appTray.setContextMenu(contextMenu);
  appTray.on('click', function handleClicked () {
    toggleVisiable();
  });
}

function setKeyMapping(key, message) {
    const ret = globalShortcut.register(key, () => {
      mainWindow.webContents.send('globalShortcut', message);
    });
}

function enableGlobalShortcuts() {
  // initial global shortcuts
  for (let key in globalShortcutMapping){
    setKeyMapping(key, globalShortcutMapping[key]);
  }
}

function disableGlobalShortcuts() {
  for (let key in globalShortcutMapping){
    globalShortcut.unregister(key);
  }

  globalShortcut.unregisterAll()
}

let floatingWindow;
const createFloatingWindow = function () {
  const electron = require('electron');
  const BrowserWindow = electron.BrowserWindow;
  const display = electron.screen.getPrimaryDisplay();
  if (!floatingWindow) {
    floatingWindow = new BrowserWindow({
      width: 1000,
      height: 80,
      titleBarStyle: 'hide',
      transparent: true,
      frame: false,
      resizable: false,
      hasShadow: false,
      alwaysOnTop:true,
      visibleOnAllWorkspaces: true,
      webPreferences: {
        nodeIntegration: true
      }
    });
    floatingWindow.setPosition(floatingWindow.getPosition()[0], display.bounds.height - 150);
    floatingWindow.setSkipTaskbar(true);
    floatingWindow.loadURL(`file://${__dirname}/floatingWindow.html`);
    floatingWindow.setAlwaysOnTop(true, 'floating');
    floatingWindow.on('closed', function () { floatingWindow = null })
  }
  floatingWindow.showInactive();
};

function createWindow() {

  const session = require('electron').session;

  const filter = {
    urls: ["*://music.163.com/*", "*://*.xiami.com/*", "*://i.y.qq.com/*", "*://c.y.qq.com/*", "*://*.kugou.com/*", "*://*.kuwo.cn/*", "*://*.bilibili.com/*", "*://*.bilivideo.com/*", "*://*.migu.cn/*", "*://*.githubusercontent.com/*",
      "https://listen1.github.io/listen1/callback.html?code=*"]
  };

  session.defaultSession.webRequest.onBeforeSendHeaders(filter, function(details, callback) {
    if(details.url.startsWith("https://listen1.github.io/listen1/callback.html?code=")){
      const url = details.url;
      const code = url.split('=')[1];
      mainWindow.webContents.executeJavaScript('Github.handleCallback("'+code+'");');
    }
    else {
      hack_referer_header(details);
    }
    callback({cancel: false, requestHeaders: details.requestHeaders});
  });

  var transparent = false;
  if (process.platform == 'darwin') {
    transparent = true;
  }
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1000,
    height: 670,
    webPreferences: {'nodeIntegration': true},
    icon: iconPath,
    titleBarStyle: 'hiddenInset',
    transparent: transparent,
    vibrancy: 'light',
    frame: false,
    hasShadow: true
  });

  // mainWindow.webContents.openDevTools();

  mainWindow.on('close', (e) => {
    if (willQuitApp) {
      /* the user tried to quit the app */
      mainWindow = null;
    } else {
      /* the user only tried to close the window */
      //if (process.platform != 'linux') {
        e.preventDefault();
        mainWindow.hide();
        //mainWindow.minimize();
      //}

    }
  });

  // and load the index.html of the app.
  var ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36';
  mainWindow.loadURL(`file://${__dirname}/listen1_chrome_extension/listen1.html`, {userAgent: ua})

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
  })

  // define global menu content, also add support for cmd+c and cmd+v shortcuts
  var template = [{
      label: "Application",
      submenu: [
          { label: "About Application", selector: "orderFrontStandardAboutPanel:" },
          { type: "separator" },
          { label: "Quit", accelerator: "Command+Q", click: function() { app.quit(); }}
      ]}, {
      label: "Edit",
      submenu: [
          { label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" },
          { label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
          { type: "separator" },
          { label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
          { label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
          { label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" },
          { label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
      ]}
  ];

  mainWindow.setMenu(null);

  electron.Menu.setApplicationMenu(electron.Menu.buildFromTemplate(template));

  initialTray(mainWindow);
}

function hack_referer_header(details) {
    let replace_referer = true;
    let replace_origin = true;
    let add_referer = true;
    let add_origin = true;
    var referer_value = '';

    if (details.url.indexOf("://music.163.com/") != -1) {
        referer_value = "http://music.163.com/";
    }
    if (details.url.indexOf("://gist.githubusercontent.com/") != -1) {
        referer_value = "https://gist.githubusercontent.com/";
    }

    if (details.url.indexOf("api.xiami.com/") != -1 || details.url.indexOf('.xiami.com/song/playlist/id/') != -1) {
        referer_value = "https://www.xiami.com/";
    }

    if ((details.url.indexOf("y.qq.com/") != -1) ||
        (details.url.indexOf("qqmusic.qq.com/") != -1) ||
        (details.url.indexOf("music.qq.com/") != -1) ||
        (details.url.indexOf("imgcache.qq.com/") != -1)) {
        referer_value = "http://y.qq.com/";
    }
    if (details.url.indexOf(".kugou.com/") != -1) {
        referer_value = "http://www.kugou.com/";
    }
    if (details.url.indexOf(".kuwo.cn/") != -1) {
        referer_value = "http://www.kuwo.cn/";
    }
    if (details.url.indexOf(".bilibili.com/") != -1 || details.url.indexOf(".bilivideo.com/") != -1) {
        referer_value = "https://www.bilibili.com/";
        replace_origin = false;
        add_origin = false;
    }
    if (details.url.indexOf('.migu.cn') !== -1) {
        referer_value = 'http://music.migu.cn/v3/music/player/audio?from=migu';
    }

    var isRefererSet = false;
    var isOriginSet = false;
    var headers = details.requestHeaders,
        blockingResponse = {};

    for (var i = 0, l = headers.length; i < l; ++i) {
        if (replace_referer && (headers[i].name == 'Referer') && (referer_value != '')) {
            headers[i].value = referer_value;
            isRefererSet = true;
        }
        if (replace_origin && (headers[i].name == 'Origin') && (referer_value != '')) {
            headers[i].value = referer_value;
            isOriginSet = true;
        }
    }

    if (add_referer && (!isRefererSet) && (referer_value != '')) {
        headers["Referer"] = referer_value;
    }

    if (add_origin && (!isOriginSet) && (referer_value != '')) {
        headers["Origin"] = referer_value;
    }

    details.requestHeaders = headers;
};

ipcMain.on('currentLyric', (event, arg) => {
  if (floatingWindow && floatingWindow !== null) {
    if(typeof arg === 'string') {
      floatingWindow.webContents.send('currentLyric', arg);
      floatingWindow.webContents.send('currentLyricTrans', '');
    } else {
      floatingWindow.webContents.send('currentLyric', arg.lyric);
      floatingWindow.webContents.send('currentLyricTrans', arg.tlyric);
    }
  }
})

ipcMain.on('control', (event, arg) => {
  // console.log(arg);
  if(arg == 'enable_global_shortcut') {
    enableGlobalShortcuts();
  }
  else if(arg == 'disable_global_shortcut') {
    disableGlobalShortcuts();
  }
  else if (arg == 'enable_lyric_floating_window') {
    createFloatingWindow();
  }
  else if (arg == 'disable_lyric_floating_window') {
    if (floatingWindow) {
      floatingWindow.hide();
    }
  }
  else if(arg == 'window_min') {
    mainWindow.minimize();
  }
  else if(arg == 'window_max') {
    if(windowState.maximized == true) {
        windowState.maximized = false;
        mainWindow.unmaximize();
      } else {
        windowState.maximized = true;
        mainWindow.maximize();
      }
  }
  else if(arg == 'window_close') {
    mainWindow.close();
  }
  // event.sender.send('asynchronous-reply', 'pong')
})

const gotTheLock = app.requestSingleInstanceLock()

if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore()
      mainWindow.focus()
    }
  })

  // Create myWindow, load the rest of the app, etc...
  app.on('ready', () => {
    createWindow()
  })
}

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

/* 'activate' is emitted when the user clicks the Dock icon (OS X) */
app.on('activate', () => mainWindow.show());

/* 'before-quit' is emitted when Electron receives
 * the signal to exit and wants to start closing windows */
app.on('before-quit', () => willQuitApp = true);

app.on('will-quit', () => {
 disableGlobalShortcuts();
})

<|endoftext|>


<commit_before>//Initialize twitter and appbase modules.
//request module is required for the twitter api

var Twit = require('twit');
var request = require("request");
var fs = require("fs");

var producer = require('../bin/producer.js');

var content = fs.readFileSync("config.json");
var jsonContent = JSON.parse(content);

//Required authetication of twitter api
var T = new Twit({
    consumer_key: jsonContent.twitter.consumer_key,
    consumer_secret: jsonContent.twitter.consumer_secret,
    access_token: jsonContent.twitter.access_token,
    access_token_secret: jsonContent.twitter.access_token_secret
});

//Filter tweets related to swarmapp
var stream = T.stream('statuses/filter', { track: 'swarmapp', language: 'en' });
var streamStatus = producer().run();

//Streaming of twitter tweets
stream.on('tweet', function(tweet) {

  if (verifyTweets(tweet)){

    var swarmappUrl = tweet.entities.urls[0].display_url;
    //extracting id from that url
    var FSid = swarmappUrl.split("/")[2];
    //created url to get data of that checkin from swarmapp
    var FSurl = "https://api.foursquare.com/v2/checkins/resolve?shortId="+FSid+"&oauth_token="+jsonContent.foursquare.oauth_token+"&v=20150919";
    //Getting data from foursquare

    request(FSurl, function(error, response, body) {
        if(verifyFoursquare(body,error)){
            var parsedbody = JSON.parse(body);

            if(parsedbody.meta.code==200){
                var data = {
                  shout: parsedbody.response.checkin.shout,
                  city: parsedbody.response.checkin.venue.location.city,
                  category: parsedbody.response.checkin.venue.categories[0].shortName,
                  venue: parsedbody.response.checkin.venue.name,
                  url: swarmappUrl,
                  username: parsedbody.response.checkin.user.firstName,
                  state: parsedbody.response.checkin.venue.location.state,
                  country: parsedbody.response.checkin.venue.location.country
                };
                if (streamStatus){
                  producer().sendData(data);
                }
            }
        }
    });
  }
});

function verifyTweets(tweet) {

    if (tweet) {
        if (tweet.entities) {
            if (tweet.entities.urls[0]) {
                if (tweet.entities.urls[0].display_url) {
                    return true;
                }
            }
        }
    }

    return false;
}

function verifyFoursquare(fsdata,error){
  if(fsdata && !error){
      var parsedbody = JSON.parse(fsdata);
      if(parsedbody.response){
        if(parsedbody.response.checkin){
          if(parsedbody.response.checkin.venue && parsedbody.response.checkin.user){
            if(parsedbody.response.checkin.venue.location.city && parsedbody.response.checkin.user.firstName && parsedbody.response.checkin.venue.location.state && parsedbody.response.checkin.venue.location.country){
              if(parsedbody.response.checkin.venue.categories[0]){
                if(parsedbody.response.checkin.venue.categories[0].shortName){
                  if(parsedbody.response.checkin.venue.name){
                    if(parsedbody.response.checkin.shout){
                      return true;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  return false;
}
<commit_msg>Add id field<commit_after>//Initialize twitter and appbase modules.
//request module is required for the twitter api

var Twit = require('twit');
var request = require("request");
var fs = require("fs");

var producer = require('../bin/producer.js');

var content = fs.readFileSync("config.json");
var jsonContent = JSON.parse(content);

//Required authetication of twitter api
var T = new Twit({
    consumer_key: jsonContent.twitter.consumer_key,
    consumer_secret: jsonContent.twitter.consumer_secret,
    access_token: jsonContent.twitter.access_token,
    access_token_secret: jsonContent.twitter.access_token_secret
});

//Filter tweets related to swarmapp
var stream = T.stream('statuses/filter', { track: 'swarmapp', language: 'en' });
var streamStatus = producer().run();

//Streaming of twitter tweets
stream.on('tweet', function(tweet) {

  if (verifyTweets(tweet)){

    var swarmappUrl = tweet.entities.urls[0].display_url;
    //extracting id from that url
    var FSid = swarmappUrl.split("/")[2];
    //created url to get data of that checkin from swarmapp
    var FSurl = "https://api.foursquare.com/v2/checkins/resolve?shortId="+FSid+"&oauth_token="+jsonContent.foursquare.oauth_token+"&v=20150919";
    //Getting data from foursquare

    request(FSurl, function(error, response, body) {
        if(verifyFoursquare(body,error)){
            var parsedbody = JSON.parse(body);

            if(parsedbody.meta.code==200){
                var data = {
                  id: parsedbody.response.checkin.id
                  shout: parsedbody.response.checkin.shout,
                  city: parsedbody.response.checkin.venue.location.city,
                  category: parsedbody.response.checkin.venue.categories[0].shortName,
                  venue: parsedbody.response.checkin.venue.name,
                  url: swarmappUrl,
                  username: parsedbody.response.checkin.user.firstName,
                  state: parsedbody.response.checkin.venue.location.state,
                  country: parsedbody.response.checkin.venue.location.country
                };
                if (streamStatus){
                  producer().sendData(data);
                }
            }
        }
    });
  }
});

function verifyTweets(tweet) {

    if (tweet) {
        if (tweet.entities) {
            if (tweet.entities.urls[0]) {
                if (tweet.entities.urls[0].display_url) {
                    return true;
                }
            }
        }
    }

    return false;
}

function verifyFoursquare(fsdata,error){
  if(fsdata && !error){
      var parsedbody = JSON.parse(fsdata);
      if(parsedbody.response){
        if(parsedbody.response.checkin){
          if(parsedbody.response.checkin.venue && parsedbody.response.checkin.user){
            if(parsedbody.response.checkin.venue.location.city && parsedbody.response.checkin.user.firstName && parsedbody.response.checkin.venue.location.state && parsedbody.response.checkin.venue.location.country){
              if(parsedbody.response.checkin.venue.categories[0]){
                if(parsedbody.response.checkin.venue.categories[0].shortName){
                  if(parsedbody.response.checkin.venue.name){
                    if(parsedbody.response.checkin.shout){
                      return true;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  return false;
}
<|endoftext|>


<commit_before>'use strict';

(() => {
  const electron = require('electron');
  const app = electron.app;
  const BrowserWindow = electron.BrowserWindow;
  let win = null;

  app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
      app.quit();
    }
  });

  // Avoid the slow performance issue when renderer window is hidden
  app.commandLine.appendSwitch('disable-renderer-backgrounding');

  app.on('ready', () => {
    win = new BrowserWindow({
      width: 850,
      height: 600
    });

    win.loadURL(`file://${__dirname}/index.html`);

    win.on('closed', () => {
      win = null;
    });
  });
})();

<commit_msg>Quit app when the window is closed<commit_after>'use strict';

(() => {
  const electron = require('electron');
  const app = electron.app;
  const BrowserWindow = electron.BrowserWindow;
  let win = null;

  app.on('window-all-closed', () => {
    app.quit();
  });

  // Avoid the slow performance issue when renderer window is hidden
  app.commandLine.appendSwitch('disable-renderer-backgrounding');

  app.on('ready', () => {
    win = new BrowserWindow({
      width: 850,
      height: 600
    });

    win.loadURL(`file://${__dirname}/index.html`);

    win.on('closed', () => {
      win = null;
    });
  });
})();

<|endoftext|>


<commit_before>//Simple promises code

let promise1 = fetch("https://jsonplaceholder.typicode.com/posts/1");

promise1
.then((response) => response.json())
.then((json) => {
    let {userId, id} = json;
    return userId;
})
.then((userId) => {
    let promise2 = fetch(`https://jsonplaceholder.typicode.com/posts/${userId}/comments`);
    return promise2;
})
.then((response) => response.json())
.then((commentsJson) => {
    return commentsJson.map(elem => elem.email);
})
.then(console.log)
.catch(error => {
    console.log('ERROR OCCURRED')
    return console.log(error);
});
<commit_msg>typo fix<commit_after>//Simple promises code

let promise1 = fetch("https://jsonplaceholder.typicode.com/posts/1");

promise1
.then((response) => response.json())
.then((json) => {
    let {userId, id} = json;
    return userId;
})
.then((userId) => {
    let promise2 = fetch(`https://jsonplaceholder.typicode.com/posts/${userId}/comments`);
    return promise2;
})
.then((response) => response.json())
.then((commentsJson) => {
    return commentsJson.map(elem => elem.email);
})
.then(console.log)
.catch(error => {
    console.log('ERROR OCCURRED');
    return console.log(error);
});
<|endoftext|>


<commit_before>var app = require('app');
var BrowserWindow = require('browser-window');

require('crash-reporter').start();

var mainWindow = null;

app.on('window-all-closed', function() {

	if (process.platform != 'darwin') {
		app.quit();
	}

});

app.on('ready', function() {

	mainWindow = new BrowserWindow({width: 800, height: 600});

	mainWindow.loadUrl('file://' + __dirname + '/index.html');

	mainWindow.openDevTools();

	mainWindow.on('closed', function() {

		mainWindow = null;
	});
});<commit_msg>Fix deprecated function<commit_after>var app = require('app');
var BrowserWindow = require('browser-window');

require('crash-reporter').start();

var mainWindow = null;

app.on('window-all-closed', function() {

	if (process.platform != 'darwin') {
		app.quit();
	}

});

app.on('ready', function() {

	mainWindow = new BrowserWindow({width: 800, height: 600});

	mainWindow.loadURL('file://' + __dirname + '/index.html');

	// mainWindow.openDevTools();

	mainWindow.on('closed', function() {

		mainWindow = null;
	});
});<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import GraphiQL from 'graphiql';
import fetch from 'isomorphic-fetch';

function graphQLFetcher(graphQLParams) {
  return fetch("http://localhost:8080", {
    method: 'post',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(graphQLParams),
  }).then(response => response.json());
}

ReactDOM.render(<GraphiQL fetcher={graphQLFetcher} />, document.body);
<commit_msg>Wipe the slate<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import GraphiQL from 'graphiql';
import fetch from 'isomorphic-fetch';

function graphQLFetcher(graphQLParams) {
  return fetch("http://localhost:8080", {
    method: 'post',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(graphQLParams),
  }).then(response => response.json());
}

ReactDOM.render(<GraphiQL query='' fetcher={graphQLFetcher} />, document.body);
<|endoftext|>


<commit_before>require([
  // Application.
  "app",

  // Main Router.
  "router"
],

function(app, Router) {

  // Define your master router on the application namespace and trigger all
  // navigation from this instance.
  app.router = new Router();

  // Trigger the initial route and enable HTML5 History API support, set the
  // root folder to '/' by default.  Change in app.js.
  Backbone.history.start({ pushState: true, root: app.root });

  // All navigation that is relative should be passed through the navigate
  // method, to be processed by the router. If the link has a `data-bypass`
  // attribute, bypass the delegation completely.
  $(document).on("click", "a:not([data-bypass])", function(evt) {
    // Get the absolute anchor href.
    var href = $(this).prop("href");
    // Get the absolute root.
    var root = location.protocol + "//" + location.host + app.root;

    // Ensure the protocol is not part of URL, meaning it's relative.
    if (href && href.indexOf(location.protocol)) {
      // Stop the default event to ensure the link will not cause a page
      // refresh.
      evt.preventDefault();

      // `Backbone.history.navigate` is sufficient for all Routers and will
      // trigger the correct events. The Router's internal `navigate` method
      // calls this anyways.  The fragment is sliced from the root.
      Backbone.history.navigate(href.slice(root.length), true);
    }
  });

});
<commit_msg>fixed the better relative determination<commit_after>require([
  // Application.
  "app",

  // Main Router.
  "router"
],

function(app, Router) {

  // Define your master router on the application namespace and trigger all
  // navigation from this instance.
  app.router = new Router();

  // Trigger the initial route and enable HTML5 History API support, set the
  // root folder to '/' by default.  Change in app.js.
  Backbone.history.start({ pushState: true, root: app.root });

  // All navigation that is relative should be passed through the navigate
  // method, to be processed by the router. If the link has a `data-bypass`
  // attribute, bypass the delegation completely.
  $(document).on("click", "a:not([data-bypass])", function(evt) {
    // Get the absolute anchor href.
    var href = $(this).prop("href");
    // Get the absolute root.
    var root = location.protocol + "//" + location.host + app.root;

    // Ensure the root is part of the anchor href, meaning it's relative.
    if (href && href.slice(root.length) === root) {
      // Stop the default event to ensure the link will not cause a page
      // refresh.
      evt.preventDefault();

      // `Backbone.history.navigate` is sufficient for all Routers and will
      // trigger the correct events. The Router's internal `navigate` method
      // calls this anyways.  The fragment is sliced from the root.
      Backbone.history.navigate(href.slice(root.length), true);
    }
  });

});
<|endoftext|>


<commit_before>'use strict';

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const ipc = electron.ipcMain;
const fs = require('fs');
const path = require('path');
const childProcess = require('child_process');

const paths = {
	module: path.join(__dirname, '..', 'node_modules'),
	gulp: path.join(__dirname, '..', 'node_modules', 'gulp', 'bin', 'gulp.js'),
	icon: path.join(__dirname, '..', 'icon.png')
};
const workerEnv = {
	NODE_PATH: paths.module,
	ELECTRON_RUN_AS_NODE: true,
	ELECTRON_NO_ATTACH_CONSOLE: false,
	ELECTRON_HIDE_INTERNAL_MODULES: true
};
const production = __dirname.includes('Contents/Resources/app') || __dirname.includes('resources/app') || __dirname.includes('resources\\app');
const mainfile = path.basename(__filename);

let mainWindow = null;
let children = {};

app.on('window-all-closed', function (event) {
	for (let child in children) {
		if (children[child] && typeof children[child].kill === 'function') {
			children[child].kill();
		}
	}

	app.quit();
});

app.on('ready', function () {
	mainWindow = new BrowserWindow({
			useContentSize: true,
			width: 1000,
			height: 450,
			resizable: false,
			fullscreen: false,
			icon: paths.icon,
			title: 'Electron Gulp Runner ' + app.getVersion()
	});
	mainWindow.loadURL('file://' + __dirname + '/index.html');
	mainWindow.setMenuBarVisibility(false);
	mainWindow.on('closed', function () {
		mainWindow = null;
	});

	if (!production) {
		mainWindow.openDevTools();
		fs.watch(__dirname, {persistent: true, recursive: true}, (event, filename) => {
			if (filename !== mainfile) {
				console.log('\x1b[36m' + new Date().toLocaleTimeString() + ` [${event}]\x1b[0m : ${filename}`);
				mainWindow.reload();
			}
		});
	}
});

ipc.on('gulp:tasks', function (event, arg) {
	let child = childProcess.fork(paths.gulp, ['--tasks-simple', '--no-color'], {
		silent: true,
		env: workerEnv,
		cwd: arg.path
	});

	child.stdout.setEncoding('utf8');
	child.stdout.on('data', function (data) {
		event.sender.send('gulp:tasks', {path: arg.path, data: data});
	});

	child.stderr.setEncoding('utf8');
	child.stderr.on('data', function (data) {
		event.sender.send('gulp:error', {path: arg.path, data: data});
	});
});

ipc.on('gulp:start', function (event, arg) {
	if (!children[arg.path]) {
		let child = children[arg.path] = childProcess.fork(paths.gulp, [arg.task, '--no-color'], {
			silent: true,
			env: workerEnv,
			cwd: arg.path
		});

		child.stdout.setEncoding('utf8');
		child.stdout.on('data', function (data) {
			event.sender.send('gulp:console', {path: arg.path, data: data});
		});

		child.stderr.setEncoding('utf8');
		child.stderr.on('data', function (data) {
			event.sender.send('gulp:error', {path: arg.path, data: data});
		});

		child.on('exit', function (code) {
			if (code === 0) {
				event.sender.send('gulp:console', {path: arg.path, data: '\nFinished running tasks'});
			}
			else {
				event.sender.send('gulp:error', {path: arg.path, data: '\nExited with error code ' + code});
			}

			event.sender.send('gulp:terminated', {path: arg.path, data: code});
			delete children[arg.path];
		});
	}
});

ipc.on('gulp:stop', function (event, arg) {
	if (children[arg.path]) {
		if (typeof children[arg.path].kill === 'function') {
			children[arg.path].kill();
		}
		delete children[arg.path];
	}
});
<commit_msg>Update log template in development mode<commit_after>'use strict';

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const ipc = electron.ipcMain;
const fs = require('fs');
const path = require('path');
const childProcess = require('child_process');

const paths = {
	module: path.join(__dirname, '..', 'node_modules'),
	gulp: path.join(__dirname, '..', 'node_modules', 'gulp', 'bin', 'gulp.js'),
	icon: path.join(__dirname, '..', 'icon.png')
};
const workerEnv = {
	NODE_PATH: paths.module,
	ELECTRON_RUN_AS_NODE: true,
	ELECTRON_NO_ATTACH_CONSOLE: false,
	ELECTRON_HIDE_INTERNAL_MODULES: true
};
const production = __dirname.includes('Contents/Resources/app') || __dirname.includes('resources/app') || __dirname.includes('resources\\app');
const mainfile = path.basename(__filename);

let mainWindow = null;
let children = {};

app.on('window-all-closed', function (event) {
	for (let child in children) {
		if (children[child] && typeof children[child].kill === 'function') {
			children[child].kill();
		}
	}

	app.quit();
});

app.on('ready', function () {
	mainWindow = new BrowserWindow({
			useContentSize: true,
			width: 1000,
			height: 450,
			resizable: false,
			fullscreen: false,
			icon: paths.icon,
			title: 'Electron Gulp Runner ' + app.getVersion()
	});
	mainWindow.loadURL('file://' + __dirname + '/index.html');
	mainWindow.setMenuBarVisibility(false);
	mainWindow.on('closed', function () {
		mainWindow = null;
	});

	if (!production) {
		mainWindow.openDevTools();
		fs.watch(__dirname, {persistent: true, recursive: true}, (event, filename) => {
			if (filename !== mainfile) {
				console.log(`\x1b[36m${new Date().toLocaleTimeString()} [${event}]\x1b[0m ${filename}`);
				mainWindow.reload();
			}
		});
	}
});

ipc.on('gulp:tasks', function (event, arg) {
	let child = childProcess.fork(paths.gulp, ['--tasks-simple', '--no-color'], {
		silent: true,
		env: workerEnv,
		cwd: arg.path
	});

	child.stdout.setEncoding('utf8');
	child.stdout.on('data', function (data) {
		event.sender.send('gulp:tasks', {path: arg.path, data: data});
	});

	child.stderr.setEncoding('utf8');
	child.stderr.on('data', function (data) {
		event.sender.send('gulp:error', {path: arg.path, data: data});
	});
});

ipc.on('gulp:start', function (event, arg) {
	if (!children[arg.path]) {
		let child = children[arg.path] = childProcess.fork(paths.gulp, [arg.task, '--no-color'], {
			silent: true,
			env: workerEnv,
			cwd: arg.path
		});

		child.stdout.setEncoding('utf8');
		child.stdout.on('data', function (data) {
			event.sender.send('gulp:console', {path: arg.path, data: data});
		});

		child.stderr.setEncoding('utf8');
		child.stderr.on('data', function (data) {
			event.sender.send('gulp:error', {path: arg.path, data: data});
		});

		child.on('exit', function (code) {
			if (code === 0) {
				event.sender.send('gulp:console', {path: arg.path, data: '\nFinished running tasks'});
			}
			else {
				event.sender.send('gulp:error', {path: arg.path, data: '\nExited with error code ' + code});
			}

			event.sender.send('gulp:terminated', {path: arg.path, data: code});
			delete children[arg.path];
		});
	}
});

ipc.on('gulp:stop', function (event, arg) {
	if (children[arg.path]) {
		if (typeof children[arg.path].kill === 'function') {
			children[arg.path].kill();
		}
		delete children[arg.path];
	}
});
<|endoftext|>


<commit_before>/**
 * Created with IntelliJ IDEA.
 * User: koroandr
 * Date: 08.08.13
 * Time: 12:07
 */

function factorial(number) {
    if (typeof number != 'number') {
        console.error("Function factorial: argument must be number");
        return null;
    }
    if (number == 0) {
        return 1;
    } else {
        return number * factorial(number - 1);
    }
}

function getFactorialArray() {
    var arr = [];
    for (var i = 0; i < 10; i++) {
        arr.push(factorial(i));
    }
    return arr;
}

function getFactNumbers(start, end) {
    var facts = getFactorialArray();
    var result = [];
    for (var num = start; num < end; num++) {
        var prevNum = 0;
        var fact = 0;
        for (mask = 10; mask/10 < num; mask *= 10) {
            var digit = (num % mask - prevNum) / (mask / 10);
            fact += facts[digit];
            prevNum = num % mask;
//            console.log(num, mask, fact, digit, prevNum);
        }

        if (fact == num) {
            result.push(num);
        }
    }
    return result;
}
<commit_msg>task 13 finished<commit_after>/**
 * Created with IntelliJ IDEA.
 * User: koroandr
 * Date: 08.08.13
 * Time: 12:07
 */

(function () {
    /**
     * Расчет факториала числа
     *
     * @param number
     * @returns {number} - факториал аргумента
     */
    function factorial(number) {
        if (typeof number != 'number') {
            console.error("Function factorial: argument must be number");
            return null;
        }
        if (number == 0) {
            return 1;
        } else {
            return number * factorial(number - 1);
        }
    }

    /**
     * Функция для расчета факториала всех цифр.
     *
     * @returns {Array} - массив, в котором в i-м элементе находится значение i!
     */
    function getFactorialArray() {
        var arr = [];
        for (var i = 0; i < 10; i++) {
            arr.push(factorial(i));
        }
        return arr;
    }

    /**
     * Находит числа в заданном диапазоне, равные факториалу своих цифр.
     * @param start - начало диапазона
     * @param end - конец диапазона
     * @returns {Array} - массив чисел, равных факториалу своих цифр
     */
    function getFactNumbers(start, end) {
        var facts = getFactorialArray();
        var result = [];
        for (var num = start; num < end; num++) {
            var prevNum = 0;
            var fact = 0;
            for (mask = 10; mask/10 < num; mask *= 10) {
                var digit = (num % mask - prevNum) / (mask / 10);
                fact += facts[digit];
                prevNum = num % mask;
//            console.log(num, mask, fact, digit, prevNum);
            }

            if (fact == num) {
                result.push(num);
            }
        }
        return result;
    }

    /*
    Вообще значение числа растет быстрее, чем сумма факториалов его цифр, так как с добавлением разряда сумма факториалов
    увеличивается на константу (максимально допустимая сумма увеличивается на 9!), а само значения числа - на порядок.

    Далее наблюдение:
    Для семизначного числа максимальная сумма цифр 9!*7 = 2540160 (т. е. также является семизначным числом), следовательно
    для 8 и более цифр таких чисел просто не существует.
     */
    console.log(getFactNumbers(1,2540160))
})();
<|endoftext|>


<commit_before>(function() {
  const api = 'https://emojityper.appspot.com';

  function historicData() {
    let p = window.fetch('https://emojityper.com/res/js/emojimap.js').then(out => out.text());
    p = p.then(raw => {
      const first = raw.indexOf('{');
      if (first === -1) {
        throw new Error('invalid emojimap');
      }
      // FIXME: never do this :O
      eval('var emojimap = ' + raw.substr(first));
      return emojimap;
    })
    p = p.then(emojimap => {
      const out = {};
      Object.keys(emojimap).forEach(string => {
        const data = emojimap[string];
        string = string.replace(/\s+/g, '').replace(/[’’]/g, '');
        if (!(string in out)) {
          out[string] = [];
        }
        out[string].push(...data.map(details => details.emoji));
      });

      return out;
    });
    return p;
  }

  function futureData() {
    return window.fetch(api + '/popular').then(out => out.json());
  }

  // const data = historicData();
  const data = futureData();
  let indexed = data.then(emojimap => {
    const prefixLength = 3;   // generate prefixes up to this length
    const maxSuggestions = 10;  // only generate this many suggestions
    const prefixSuggest = {};

    for (let k in emojimap) {
      const prefix = k.substr(0, prefixLength);
      for (let i = 1; i <= prefix.length; ++i) {
        const part = prefix.substr(0, i);
        let opts = prefixSuggest[part];
        if (!opts) {
          opts = prefixSuggest[part] = [];
        }
        if (opts.length < maxSuggestions) {
          opts.push(k);
        }
      }
    }

    return function(typed) {
      typed = typed.toLowerCase();
      const rest = typed.substr(prefixLength);
      let all = prefixSuggest[typed.substr(0, prefixLength)] || [];

      if (rest) {
        all = all.filter(word => word.substr(prefixLength).startsWith(rest));
      }
      all = all.map(word => {
        return {'name': word, 'options': emojimap[word] || []};
      });

      return all.length ? all : null;
    }
  });

  let timeout;  // timeout handler for secondary query
  const performRequest = (text, prefix) => {
    window.clearTimeout(timeout);
    if (!text) {
      window.emojimanager.callback(null);
      return;
    }

    function send(out) {
      if (timeout === localTimeout) {
        window.emojimanager.callback(out);
      } else {
        console.debug('got results for old query');
      }
    }

    // TODO: only send extra query if there's not enough results, or the user hits 'more'
    localTimeout = window.setTimeout(_ => {
      const data = new FormData();
      data.append('q', text);
      data.append('prefix', prefix)
      window.fetch(api + '/query', {method: 'POST', data}).then(out => out.json()).then(send);
    }, 2000);
    timeout = localTimeout;

    indexed.then(suggest => {
      let results = suggest(text);
      if (!prefix) {
        results = results.filter(result => result['name'] === text);
      }
      send(results);
    });
  };

  window.emojimanager = {
    callback: function() {},
    request(text, prefix) {
      window.requestAnimationFrame(_ => {
        performRequest(text, prefix);
      });
    },
    submit(name, value) {
      // const data = `name=${name}&emoji=${value}`;
      // FIXME: we've disabled CORS for now; the response is actually useless anyway
      // FIXME: however, the client now thinks this succeeds even when it 400s
      const data = new FormData();
      data.append('name', name);
      data.append('emoji', value);
      return window.fetch(api + '/name', {method: 'POST', data, mode: 'no-cors'});
    },
  };

}())

<commit_msg>remove historic data<commit_after>(function() {
  const api = 'https://emojityper.appspot.com';

  const data = window.fetch(api + '/popular').then(out => out.json());
  let indexed = data.then(emojimap => {
    const prefixLength = 3;   // generate prefixes up to this length
    const maxSuggestions = 10;  // only generate this many suggestions
    const prefixSuggest = {};

    for (let k in emojimap) {
      const prefix = k.substr(0, prefixLength);
      for (let i = 1; i <= prefix.length; ++i) {
        const part = prefix.substr(0, i);
        let opts = prefixSuggest[part];
        if (!opts) {
          opts = prefixSuggest[part] = [];
        }
        if (opts.length < maxSuggestions) {
          opts.push(k);
        }
      }
    }

    return function(typed) {
      typed = typed.toLowerCase();
      const rest = typed.substr(prefixLength);
      let all = prefixSuggest[typed.substr(0, prefixLength)] || [];

      if (rest) {
        all = all.filter(word => word.substr(prefixLength).startsWith(rest));
      }
      all = all.map(word => {
        return {'name': word, 'options': emojimap[word] || []};
      });

      return all.length ? all : null;
    }
  });

  let timeout;  // timeout handler for secondary query
  const performRequest = (text, prefix) => {
    window.clearTimeout(timeout);
    if (!text) {
      window.emojimanager.callback(null);
      return;
    }

    function send(out) {
      if (timeout === localTimeout) {
        window.emojimanager.callback(out);
      } else {
        console.debug('got results for old query');
      }
    }

    // TODO: only send extra query if there's not enough results, or the user hits 'more'
    localTimeout = window.setTimeout(_ => {
      const data = new FormData();
      data.append('q', text);
      data.append('prefix', prefix)
      window.fetch(api + '/query', {method: 'POST', data}).then(out => out.json()).then(send);
    }, 2000);
    timeout = localTimeout;

    indexed.then(suggest => {
      let results = suggest(text);
      if (!prefix) {
        results = results.filter(result => result['name'] === text);
      }
      send(results);
    });
  };

  window.emojimanager = {
    callback: function() {},
    request(text, prefix) {
      window.requestAnimationFrame(_ => {
        performRequest(text, prefix);
      });
    },
    submit(name, value) {
      // const data = `name=${name}&emoji=${value}`;
      // FIXME: we've disabled CORS for now; the response is actually useless anyway
      // FIXME: however, the client now thinks this succeeds even when it 400s
      const data = new FormData();
      data.append('name', name);
      data.append('emoji', value);
      return window.fetch(api + '/name', {method: 'POST', data, mode: 'no-cors'});
    },
  };

}())

<|endoftext|>


<commit_before>"use strict";

function DiffBuilder(file, output)
{
    this.file = file;
    this.language = file.language;
    this.output = output;
    this.highlightData = null;
}

DiffBuilder.prototype.reset = function()
{
    this.language = this.file.language;
    this.highlightData = null;
};

DiffBuilder.prototype.emitDiff = function(diff)
{
    if (diff.isImage) {
        var image = document.createElement("cr-diff-image");
        image.file = this.file;
        this.output.appendChild(image);
        return;
    }
    if (diff.from)
        this.emitMoveHeader(diff.from);
    var groups = diff.groups;
    for (var i = 0; i < groups.length; ++i)
        this.emitGroup(groups[i]);
};

// Moves and copies need a header at the start of the file.
DiffBuilder.prototype.emitMoveHeader = function(text)
{
    var section = document.createElement("div");
    this.output.appendChild(section);
    this.emitLine(section, {
        type: "header",
        beforeNumber: 0,
        afterNumber: 0,
        contextLinesStart: 0,
        contextLinesEnd: 0,
        context: false,
        text: text,
    });
};

DiffBuilder.prototype.emitGroup = function(group)
{
    var section = document.createElement("div");
    for (var i = 0; i < group.length; ++i)
        this.emitLine(section, group[i]);
    this.output.appendChild(section);
};

DiffBuilder.prototype.emitLine = function(section, line)
{
    var file = this.file;

    this.resetLanguageIfNeeded(line);

    var row = document.createElement("div");
    row.className = "row " + line.type;

    row.appendChild(this.createLineNumber(line, line.beforeNumber, "remove"));
    row.appendChild(this.createLineNumber(line, line.afterNumber, "add"));
    row.appendChild(this.createText(line));

    var contextAction = this.createContextAction(section, line);
    if (contextAction)
        row.appendChild(contextAction);

    section.appendChild(row);

    var messages = this.createMessages(line);
    if (messages)
        section.appendChild(messages);

    this.selectEmbeddedLanguage(line);

    // FIXME: Editing a multi line comment can end up making an entire file
    // look like a comment. For now we reset the syntax highlighter between
    // sections to avoid this in the common case. This will break headers
    // in the middle of multi line comments, but that's very rare.
    if (line.type == "header")
        this.highlightData = null;
};

DiffBuilder.prototype.resetLanguageIfNeeded = function(line)
{
    if (this.language == this.file.language)
        return;
    if (!this.file.shouldResetEmbeddedLanguage(this.language, line.text))
        return;
    this.language = this.file.language;
    this.highlightData = null;
};

DiffBuilder.prototype.selectEmbeddedLanguage = function(line)
{
    if (this.language != this.file.language)
        return;
    this.language = this.file.selectEmbeddedLanguage(line.text);
    if (this.language != this.file.language)
        this.highlightData = null;
};

DiffBuilder.prototype.createContextAction = function(section, line)
{
    if (!line.context)
        return null;
    var self = this;
    var action = document.createElement("cr-action");
    action.textContent = "Show context";
    action.onclick = function() {
        self.file.loadContext(line.contextLinesStart, line.contextLinesEnd).then(function(lines) {
            self.reset();
            var newSection = document.createElement("div");
            lines.forEach(function(line) {
                self.emitLine(newSection, line);
            });
            self.output.insertBefore(newSection, section);
            section.remove();
        }).catch(function(e) {
            console.log(e);
        });
    };
    return action;
};

DiffBuilder.prototype.createLineNumber = function(line, number, type)
{
    var div = document.createElement("div");
    div.className = "line-number";
    if (line.type == "both" || line.type == type)
        div.setAttribute("value", number);
    else if (line.type == "header")
        div.setAttribute("value", "@@");
    return div;
};

DiffBuilder.prototype.createText = function(line)
{
    var text = document.createElement("div");
    text.className = "text";
    if (!this.language) {
        text.textContent = line.text;
        return text;
    }
    try {
        var code = hljs.highlight(this.language, line.text, true, this.highlightData);
        this.highlightData = code.top;
        text.innerHTML = code.value;
    } catch (e) {
        console.log("Syntax highlighter error", e);
        text.textContent = line.text;
    }
    return text;
};

DiffBuilder.prototype.messagesForLine = function(line, number, type)
{
    if (line.type == "both" || line.type == type)
        return this.file.messages[number];
    return null;
};

DiffBuilder.prototype.createMessages = function(line)
{
    var beforeMessages = this.messagesForLine(line, line.beforeNumber, "remove");
    var afterMessages = this.messagesForLine(line, line.afterNumber, "add");

    if (!beforeMessages && !afterMessages)
        return null;

    var messages = document.createElement("div");
    messages.className = "messages";

    if (beforeMessages) {
        beforeMessages.forEach(function(message) {
            if (!message.left)
                return;
            var fileMessage = document.createElement("cr-patch-file-message");
            fileMessage.message = message;
            messages.appendChild(fileMessage);
        });
    }

    if (afterMessages) {
        afterMessages.forEach(function(message) {
            if (message.left)
                return;
            var fileMessage = document.createElement("cr-patch-file-message");
            fileMessage.message = message;
            messages.appendChild(fileMessage);
        });
    }

    return messages;
};
<commit_msg>Reuse emitGroup in DiffBuilder for context lines.<commit_after>"use strict";

function DiffBuilder(file, output)
{
    this.file = file;
    this.language = file.language;
    this.output = output;
    this.highlightData = null;
}

DiffBuilder.prototype.reset = function()
{
    this.language = this.file.language;
    this.highlightData = null;
};

DiffBuilder.prototype.emitDiff = function(diff)
{
    if (diff.isImage) {
        var image = document.createElement("cr-diff-image");
        image.file = this.file;
        this.output.appendChild(image);
        return;
    }
    if (diff.from)
        this.emitMoveHeader(diff.from);
    var groups = diff.groups;
    for (var i = 0; i < groups.length; ++i)
        this.emitGroup(groups[i]);
};

// Moves and copies need a header at the start of the file.
DiffBuilder.prototype.emitMoveHeader = function(text)
{
    var section = document.createElement("div");
    this.output.appendChild(section);
    this.emitLine(section, {
        type: "header",
        beforeNumber: 0,
        afterNumber: 0,
        contextLinesStart: 0,
        contextLinesEnd: 0,
        context: false,
        text: text,
    });
};

DiffBuilder.prototype.emitGroup = function(group, beforeSection)
{
    var section = document.createElement("div");
    for (var i = 0; i < group.length; ++i)
        this.emitLine(section, group[i]);
    this.output.insertBefore(section, beforeSection);
};

DiffBuilder.prototype.emitLine = function(section, line)
{
    var file = this.file;

    this.resetLanguageIfNeeded(line);

    var row = document.createElement("div");
    row.className = "row " + line.type;

    row.appendChild(this.createLineNumber(line, line.beforeNumber, "remove"));
    row.appendChild(this.createLineNumber(line, line.afterNumber, "add"));
    row.appendChild(this.createText(line));

    var contextAction = this.createContextAction(section, line);
    if (contextAction)
        row.appendChild(contextAction);

    section.appendChild(row);

    var messages = this.createMessages(line);
    if (messages)
        section.appendChild(messages);

    this.selectEmbeddedLanguage(line);

    // FIXME: Editing a multi line comment can end up making an entire file
    // look like a comment. For now we reset the syntax highlighter between
    // sections to avoid this in the common case. This will break headers
    // in the middle of multi line comments, but that's very rare.
    if (line.type == "header")
        this.highlightData = null;
};

DiffBuilder.prototype.resetLanguageIfNeeded = function(line)
{
    if (this.language == this.file.language)
        return;
    if (!this.file.shouldResetEmbeddedLanguage(this.language, line.text))
        return;
    this.language = this.file.language;
    this.highlightData = null;
};

DiffBuilder.prototype.selectEmbeddedLanguage = function(line)
{
    if (this.language != this.file.language)
        return;
    this.language = this.file.selectEmbeddedLanguage(line.text);
    if (this.language != this.file.language)
        this.highlightData = null;
};

DiffBuilder.prototype.createContextAction = function(section, line)
{
    if (!line.context)
        return null;
    var self = this;
    var action = document.createElement("cr-action");
    action.textContent = "Show context";
    action.onclick = function() {
        self.file.loadContext(line.contextLinesStart, line.contextLinesEnd).then(function(lines) {
            self.reset();
            self.emitGroup(lines, section);
            section.remove();
        }).catch(function(e) {
            console.log(e);
        });
    };
    return action;
};

DiffBuilder.prototype.createLineNumber = function(line, number, type)
{
    var div = document.createElement("div");
    div.className = "line-number";
    if (line.type == "both" || line.type == type)
        div.setAttribute("value", number);
    else if (line.type == "header")
        div.setAttribute("value", "@@");
    return div;
};

DiffBuilder.prototype.createText = function(line)
{
    var text = document.createElement("div");
    text.className = "text";
    if (!this.language) {
        text.textContent = line.text;
        return text;
    }
    try {
        var code = hljs.highlight(this.language, line.text, true, this.highlightData);
        this.highlightData = code.top;
        text.innerHTML = code.value;
    } catch (e) {
        console.log("Syntax highlighter error", e);
        text.textContent = line.text;
    }
    return text;
};

DiffBuilder.prototype.messagesForLine = function(line, number, type)
{
    if (line.type == "both" || line.type == type)
        return this.file.messages[number];
    return null;
};

DiffBuilder.prototype.createMessages = function(line)
{
    var beforeMessages = this.messagesForLine(line, line.beforeNumber, "remove");
    var afterMessages = this.messagesForLine(line, line.afterNumber, "add");

    if (!beforeMessages && !afterMessages)
        return null;

    var messages = document.createElement("div");
    messages.className = "messages";

    if (beforeMessages) {
        beforeMessages.forEach(function(message) {
            if (!message.left)
                return;
            var fileMessage = document.createElement("cr-patch-file-message");
            fileMessage.message = message;
            messages.appendChild(fileMessage);
        });
    }

    if (afterMessages) {
        afterMessages.forEach(function(message) {
            if (message.left)
                return;
            var fileMessage = document.createElement("cr-patch-file-message");
            fileMessage.message = message;
            messages.appendChild(fileMessage);
        });
    }

    return messages;
};
<|endoftext|>


<commit_before>var crypto = require('crypto'),
    fs = require('fs'),
    Promise = require('core-js/library/es6/promise'),
    // change the algo to sha1, sha256 etc according to your requirements
    algo = 'md5';

module.exports = function fileHash(path) {
    var shasum = crypto.createHash(algo),
        stream = fs.ReadStream(path);
    return new Promise(function calcHash(reject, resolve) {
        stream.on('error', reject)
              .on('data', function(d) { shasum.update(d); })
              .on('end', function digest() {
            var d = shasum.digest('hex');
            resolve(d);
        });
    });
}
<commit_msg>fix(file-hash): swap reject and resolve in promise<commit_after>var crypto = require('crypto'),
    fs = require('fs'),
    Promise = require('core-js/library/es6/promise'),
    // change the algo to sha1, sha256 etc according to your requirements
    algo = 'md5';

module.exports = function fileHash(path) {
    var shasum = crypto.createHash(algo),
        stream = fs.ReadStream(path);
    return new Promise(function calcHash(resolve, reject) {
        stream.on('error', reject)
              .on('data', function(d) { shasum.update(d); })
              .on('end', function digest() {
            var d = shasum.digest('hex');
            resolve(d);
        });
    });
}
<|endoftext|>


<commit_before>var Menu = require('menu');
var MenuItem = require('menu-item');

module.exports = {
  setup: function (app, host) {
    var name = app.getName();

    var app_menu = {
      label: name,
      submenu: [
        {
          label: 'About ' + name,
          role: 'about'
        },
        {
          type: 'separator'
        },
        {
          label: 'Preferences…',
          accelerator: 'Cmd+,',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.executeJavaScript('SESSIONVIEW.openSettings()');
            }
          }
        },
        {
          type: 'separator'
        },
        {
          label: 'Services',
          role: 'services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          label: 'Hide ' + name,
          accelerator: 'Cmd+H',
          role: 'hide'
        },
        {
          label: 'Hide Others',
          accelerator: 'Cmd+Alt+H',
          role: 'hideothers'
        },
        {
          label: 'Show All',
          role: 'unhide'
        },
        {
          type: 'separator'
        },
        {
          label: 'Quit',
          accelerator: 'Cmd+Q',
          click: function(item, focusedWindow) {
            app.quit();
          }
        }
      ]
    };
    var file_menu = {
        label: 'File',
        submenu: [
            {
              label: 'Open in Browser',
              click: function(item, focusedWindow) {
                var url = focusedWindow ? focusedWindow.webContents.getURL() : host;
                require('electron').shell.openExternal(url);
              }
            },
            {
              type: 'separator'
            },
            {
              label: 'Add a Network…',
              click: function (item, focusedWindow) {
                if (focusedWindow) {
                  focusedWindow.webContents.executeJavaScript('SESSIONVIEW.addNetwork()');
                }
              }
            },
            {
              type: 'separator'
            },
            {
              label: 'Jump to…',
              accelerator: 'CmdOrCtrl+K'
            },
            {
              label: 'Select Next in List',
              accelerator: 'Alt+Down'
            },
            {
              label: 'Select Previous in List',
              accelerator: 'Alt+Up'
            },
            {
              label: 'Select Next Unread in List',
              accelerator: 'Alt+Shift+Down'
            },
            {
              label: 'Select Previous Unread in List',
              accelerator: 'Alt+Shift+Up'
            },
            {
              type: 'separator'
            },
            {
              label: 'Mark Current as Read',
              accelerator: 'Esc'
            },
            {
              label: 'Mark All as Read',
              accelerator: 'Shift+Esc'
            },
            {
              type: 'separator'
            },
            {
              label: 'Upload a File…',
              click: function (item, focusedWindow) {
                if (focusedWindow) {
                  focusedWindow.webContents.executeJavaScript('if (cb()) cb().trigger("uploadPrompt");');
                }
              }
            },
            {
              label: 'Start a Pastebin…',
              click: function (item, focusedWindow) {
                if (focusedWindow) {
                  focusedWindow.webContents.executeJavaScript('if (cb()) cb().trigger("pastePrompt");');
                }
              }
            },
            {
              type: 'separator'
            },
            {
              label: 'Close',
              accelerator: 'CmdOrCtrl+W',
              role: 'close'
            }
        ]
    };
    if (process.platform != 'darwin') {
      file_menu.submenu.push({
        label: 'Quit',
        accelerator: 'Alt+F4',
        click: function(item, focusedWindow) {
          app.quit();
        }
      });
    }

    var edit_menu = {
      label: 'Edit',
      submenu: [
        {
          label: 'Undo',
          accelerator: 'CmdOrCtrl+Z',
          role: 'undo'
        },
        {
          label: 'Redo',
          accelerator: 'Shift+CmdOrCtrl+Z',
          role: 'redo'
        },
        {
          type: 'separator'
        },
        {
          label: 'Cut',
          accelerator: 'CmdOrCtrl+X',
          role: 'cut'
        },
        {
          label: 'Copy',
          accelerator: 'CmdOrCtrl+C',
          role: 'copy'
        },
        {
          label: 'Paste',
          accelerator: 'CmdOrCtrl+V',
          role: 'paste'
        },
        {
          label: 'Select All',
          accelerator: 'CmdOrCtrl+A',
          role: 'selectall'
        },
      ]
    };

    var view_menu = {
      label: 'View',
      submenu: [
        {
          label: 'Reload',
          accelerator: 'CmdOrCtrl+R',
          click: function(item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.reloadIgnoringCache();
            }
          }
        },
        {
          label: 'Toggle Full Screen',
          accelerator: (function() {
            if (process.platform == 'darwin') {
              return 'Ctrl+Cmd+F';
            } else {
              return 'F11';
            }
          })(),
          click: function(item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          }
        },
        {
          label: 'Toggle Developer Tools',
          accelerator: (function() {
            if (process.platform == 'darwin') {
              return 'Cmd+Alt+I';
            } else {
              return 'Ctrl+Shift+I';
            }
          })(),
          click: function(item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.toggleDevTools();
            }
          }
        },
      ]
    };

    var go_menu = {
      label: 'Go',
      id: 'history',
      submenu: [
        {
          label: 'Back',
          accelerator: 'CmdOrCtrl+[',
          enabled: false,
          id: 'backMenu',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.goBack();
            }
          }
        },
        {
          label: 'Forward',
          accelerator: 'CmdOrCtrl+]',
          enabled: false,
          id: 'fwdMenu',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.goForward();
            }
          }
        },
        {
          type: 'separator'
        },
        {
          label: 'File Uploads',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.executeJavaScript('SESSIONVIEW.files.show();');
            }
          }
        },
        {
          label: 'Pastebins',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.executeJavaScript('SESSIONVIEW.pastebins.show();');
            }
          }
        }
      ]
    };

    var window_menu = {
      label: 'Window',
      role: 'window',
      submenu: [
        {
          label: 'Minimize',
          accelerator: 'CmdOrCtrl+M',
          role: 'minimize'
        },
        {
          type: 'separator'
        },
        {
          label: 'Bring All to Front',
          role: 'front'
        }
      ]
    };

    var help_menu = {
      label: 'Help',
      role: 'help',
      submenu: [
        {
          label: 'Keyboard Shortcuts',
          accelerator: 'CmdOrCtrl+/'
        },
        {
          type: 'separator'
        },
        {
          label: 'Known Issues',
          click: function(item, focusedWindow) {
            require('electron').shell.openExternal('https://github.com/irccloud/irccloud-desktop/issues');
          }
        },
      ]
    };

    var menu;
    if (process.platform == 'darwin') {
      menu = Menu.buildFromTemplate([app_menu, file_menu, edit_menu, view_menu, go_menu, window_menu, help_menu]);
    } else {
      menu = Menu.buildFromTemplate([file_menu, edit_menu, view_menu, go_menu, help_menu]);
    }
    Menu.setApplicationMenu(menu);
    return menu;
  }
};
<commit_msg>Remove close and add settings menu items on windows<commit_after>var Menu = require('menu');
var MenuItem = require('menu-item');

module.exports = {
  setup: function (app, host) {
    var name = app.getName();

    var app_menu = {
      label: name,
      submenu: [
        {
          label: 'About ' + name,
          role: 'about'
        },
        {
          type: 'separator'
        },
        {
          label: 'Preferences…',
          accelerator: 'Cmd+,',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.executeJavaScript('SESSIONVIEW.openSettings()');
            }
          }
        },
        {
          type: 'separator'
        },
        {
          label: 'Services',
          role: 'services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          label: 'Hide ' + name,
          accelerator: 'Cmd+H',
          role: 'hide'
        },
        {
          label: 'Hide Others',
          accelerator: 'Cmd+Alt+H',
          role: 'hideothers'
        },
        {
          label: 'Show All',
          role: 'unhide'
        },
        {
          type: 'separator'
        },
        {
          label: 'Quit',
          accelerator: 'Cmd+Q',
          click: function(item, focusedWindow) {
            app.quit();
          }
        }
      ]
    };
    var file_menu = {
        label: 'File',
        submenu: [
            {
              label: 'Open in Browser',
              click: function(item, focusedWindow) {
                var url = focusedWindow ? focusedWindow.webContents.getURL() : host;
                require('electron').shell.openExternal(url);
              }
            },
            {
              type: 'separator'
            },
            {
              label: 'Add a Network…',
              click: function (item, focusedWindow) {
                if (focusedWindow) {
                  focusedWindow.webContents.executeJavaScript('SESSIONVIEW.addNetwork()');
                }
              }
            },
            {
              type: 'separator'
            },
            {
              label: 'Jump to…',
              accelerator: 'CmdOrCtrl+K'
            },
            {
              label: 'Select Next in List',
              accelerator: 'Alt+Down'
            },
            {
              label: 'Select Previous in List',
              accelerator: 'Alt+Up'
            },
            {
              label: 'Select Next Unread in List',
              accelerator: 'Alt+Shift+Down'
            },
            {
              label: 'Select Previous Unread in List',
              accelerator: 'Alt+Shift+Up'
            },
            {
              type: 'separator'
            },
            {
              label: 'Mark Current as Read',
              accelerator: 'Esc'
            },
            {
              label: 'Mark All as Read',
              accelerator: 'Shift+Esc'
            },
            {
              type: 'separator'
            },
            {
              label: 'Upload a File…',
              click: function (item, focusedWindow) {
                if (focusedWindow) {
                  focusedWindow.webContents.executeJavaScript('if (cb()) cb().trigger("uploadPrompt");');
                }
              }
            },
            {
              label: 'Start a Pastebin…',
              click: function (item, focusedWindow) {
                if (focusedWindow) {
                  focusedWindow.webContents.executeJavaScript('if (cb()) cb().trigger("pastePrompt");');
                }
              }
            }
        ]
    };
    if (process.platform != 'darwin') {
      file_menu.submenu.push({
        type: 'separator'
      });
      file_menu.submenu.push({
        label: 'Preferences…',
        accelerator: 'Ctrl+,',
        click: function (item, focusedWindow) {
          if (focusedWindow) {
            focusedWindow.webContents.executeJavaScript('SESSIONVIEW.openSettings()');
          }
        }
      });
      file_menu.submenu.push({
        type: 'separator'
      });
      file_menu.submenu.push({
        label: 'Quit',
        accelerator: 'Alt+F4',
        click: function(item, focusedWindow) {
          app.quit();
        }
      });
    }

    var edit_menu = {
      label: 'Edit',
      submenu: [
        {
          label: 'Undo',
          accelerator: 'CmdOrCtrl+Z',
          role: 'undo'
        },
        {
          label: 'Redo',
          accelerator: 'Shift+CmdOrCtrl+Z',
          role: 'redo'
        },
        {
          type: 'separator'
        },
        {
          label: 'Cut',
          accelerator: 'CmdOrCtrl+X',
          role: 'cut'
        },
        {
          label: 'Copy',
          accelerator: 'CmdOrCtrl+C',
          role: 'copy'
        },
        {
          label: 'Paste',
          accelerator: 'CmdOrCtrl+V',
          role: 'paste'
        },
        {
          label: 'Select All',
          accelerator: 'CmdOrCtrl+A',
          role: 'selectall'
        },
      ]
    };

    var view_menu = {
      label: 'View',
      submenu: [
        {
          label: 'Reload',
          accelerator: 'CmdOrCtrl+R',
          click: function(item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.reloadIgnoringCache();
            }
          }
        },
        {
          label: 'Toggle Full Screen',
          accelerator: (function() {
            if (process.platform == 'darwin') {
              return 'Ctrl+Cmd+F';
            } else {
              return 'F11';
            }
          })(),
          click: function(item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          }
        },
        {
          label: 'Toggle Developer Tools',
          accelerator: (function() {
            if (process.platform == 'darwin') {
              return 'Cmd+Alt+I';
            } else {
              return 'Ctrl+Shift+I';
            }
          })(),
          click: function(item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.toggleDevTools();
            }
          }
        },
      ]
    };

    var go_menu = {
      label: 'Go',
      id: 'history',
      submenu: [
        {
          label: 'Back',
          accelerator: 'CmdOrCtrl+[',
          enabled: false,
          id: 'backMenu',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.goBack();
            }
          }
        },
        {
          label: 'Forward',
          accelerator: 'CmdOrCtrl+]',
          enabled: false,
          id: 'fwdMenu',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.goForward();
            }
          }
        },
        {
          type: 'separator'
        },
        {
          label: 'File Uploads',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.executeJavaScript('SESSIONVIEW.files.show();');
            }
          }
        },
        {
          label: 'Pastebins',
          click: function (item, focusedWindow) {
            if (focusedWindow) {
              focusedWindow.webContents.executeJavaScript('SESSIONVIEW.pastebins.show();');
            }
          }
        }
      ]
    };

    var window_menu = {
      label: 'Window',
      role: 'window',
      submenu: [
        {
          label: 'Minimize',
          accelerator: 'CmdOrCtrl+M',
          role: 'minimize'
        },
        {
          type: 'separator'
        },
        {
          label: 'Bring All to Front',
          role: 'front'
        }
      ]
    };

    var help_menu = {
      label: 'Help',
      role: 'help',
      submenu: [
        {
          label: 'Keyboard Shortcuts',
          accelerator: 'CmdOrCtrl+/'
        },
        {
          type: 'separator'
        },
        {
          label: 'Known Issues',
          click: function(item, focusedWindow) {
            require('electron').shell.openExternal('https://github.com/irccloud/irccloud-desktop/issues');
          }
        },
      ]
    };

    var menu;
    if (process.platform == 'darwin') {
      menu = Menu.buildFromTemplate([app_menu, file_menu, edit_menu, view_menu, go_menu, window_menu, help_menu]);
    } else {
      menu = Menu.buildFromTemplate([file_menu, edit_menu, view_menu, go_menu, help_menu]);
    }
    Menu.setApplicationMenu(menu);
    return menu;
  }
};
<|endoftext|>