GS-zerotier



  const token = 'xxxxxxxxxxxxxxx' //token zerotier
  const NETWORK_ID = 'yyyyyyyyyyyyyy';       // isi ID jaringan


function getZeroTierNetworks() {
  if (!token) {
    throw new Error('Token tidak ditemukan. Jalankan setZeroTierTokenOnce() atau simpan token di Script Properties.');
  }

  var url = 'https://api.zerotier.com/api/v1/network';
  var options = {
    method: 'get',
    headers: {
      Authorization: 'token ' + token
    },
    muteHttpExceptions: true,
    contentType: 'application/json'
  };

  var resp = UrlFetchApp.fetch(url, options);
  var code = resp.getResponseCode();
  var text = resp.getContentText();

  if (code >= 200 && code < 300) {
    var data = JSON.parse(text);
    Logger.log('Berhasil ambil networks. Count: ' + (data.length || 0));
    // contoh: log beberapa fields
    data.forEach(function(n, i){
      Logger.log('%s: id=%s name=%s', i+1, n.id, n.config && n.config.name);
    });

    // contoh: tulis ringkasan ke sheet aktif (optional)
    //writeNetworksToSheet(data);
    return data;
  } else {
    Logger.log('Error: HTTP ' + code);
    Logger.log(text);
    throw new Error('Request gagal. HTTP ' + code);
  }
}


/**
 * Contoh: GET network by id
 */
function getZeroTierNetworkById() {
  var networkId = "d5e5fb65378fe004"
  if (!token) throw new Error('Token tidak ditemukan.');

  var url = 'https://api.zerotier.com/api/v1/network/' + encodeURIComponent(networkId);
  var options = {
    method: 'get',
    headers: { Authorization: 'token ' + token },
    muteHttpExceptions: true
  };
  var resp = UrlFetchApp.fetch(url, options);
  if (resp.getResponseCode() === 200) {
    var obj = JSON.parse(resp.getContentText());
    Logger.log(obj);
    return obj;
  } else {
    Logger.log('HTTP ' + resp.getResponseCode() + ' -- ' + resp.getContentText());
    throw new Error('Gagal ambil network by id');
  }
}



function listPendingMembers() {

  const url = `https://api.zerotier.com/api/v1/network/${NETWORK_ID}/member`;

  const options = {
    method: 'get',
    headers: { Authorization: 'token ' + token },
    muteHttpExceptions: true
  };

  const resp = UrlFetchApp.fetch(url, options);
  const data = JSON.parse(resp.getContentText());

  const pending = data.filter(m => !m.config?.authorized);
  if (pending.length === 0) {
    Logger.log('Tidak ada member pending.');
  } else {
    pending.forEach(m => {
      Logger.log(`Pending: ${m.nodeId} - IP: ${m.config?.ipAssignments}`);
    });
  }
}

function autoAuthorizeMembers() {

  //var memberId = "61D3159610"
  //const token = PropertiesService.getScriptProperties().getProperty('ZEROTIER_TOKEN');
  //const NETWORK_ID = 'xxxxxxxxxx';
  const url = `https://api.zerotier.com/api/v1/network/${NETWORK_ID}/member`;

  const resp = UrlFetchApp.fetch(url, { method: 'get', headers: { Authorization: 'token ' + token } });
  const members = JSON.parse(resp.getContentText());

  members.forEach(m => {
    if (!m.config?.authorized) {
      // contoh: hanya authorize jika hostname mengandung "remote"
      //if (m.name && m.name.toLowerCase().includes('remote')) {
        const memberId = m.nodeId;
        const postUrl = `https://api.zerotier.com/api/v1/network/${NETWORK_ID}/member/${memberId}`;
        const payload = { config: { authorized: true } };
        UrlFetchApp.fetch(postUrl, {
          method: 'post',
          headers: {
            'Authorization': 'token ' + token,
            'Content-Type': 'application/json'
          },
          payload: JSON.stringify(payload)
        });
        Logger.log(`✔ Authorized ${memberId}`);
      //}
    }
  });
}


function listAllZeroTierMembers() {

  const url = `https://api.zerotier.com/api/v1/network/${NETWORK_ID}/member`;

  const options = {
    method: 'get',
    headers: {
      Authorization: 'token ' + token
    },
    muteHttpExceptions: true
  };

  const response = UrlFetchApp.fetch(url, options);
  const code = response.getResponseCode();
  const text = response.getContentText();

  if (code >= 200 && code < 300) {
    const members = JSON.parse(text);
    Logger.log(`Total member: ${members.length}`);

    members.forEach((m, i) => {
      Logger.log(
        `#${i + 1} NodeID: ${m.nodeId}\n` +
        `  Name: ${m.name || '(no name)'}\n` +
        `  Authorized: ${m.config?.authorized}\n` +
        `  IP: ${m.config?.ipAssignments?.join(', ') || '-'}\n` +
        `  Online: ${m.online}\n`
      );
    });


    return members;
  } else {
    Logger.log(`Error HTTP ${code}: ${text}`);
    throw new Error('Gagal memuat daftar member');
  }
}





function setMemberAuthorization(memberId, authorized) {

  const url = `https://api.zerotier.com/api/v1/network/${NETWORK_ID}/member/${memberId}`;
  const payload = { config: { authorized: authorized } };
  const options = {
    method: 'post',
    headers: {
      'Authorization': 'token ' + token,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };

  const resp = UrlFetchApp.fetch(url, options);
  const code = resp.getResponseCode();
  const text = resp.getContentText();

  if (code >= 200 && code < 300) {
    Logger.log(`✅ Member ${memberId} sekarang authorized=${authorized}`);
    return JSON.parse(text);
  } else {
    Logger.log(`❌ Gagal ubah status member. HTTP ${code}: ${text}`);
    throw new Error('Gagal ubah status member');
  }
}

function demo(){

setMemberAuthorization("61D3159610",false)
//setMemberAuthorization("61D3159610",true)

}