Skip to content

Instantly share code, notes, and snippets.

@chan-mai
Last active November 5, 2024 17:51
Show Gist options
  • Select an option

  • Save chan-mai/5bab0cc3655151b57bab3cb6363f9871 to your computer and use it in GitHub Desktop.

Select an option

Save chan-mai/5bab0cc3655151b57bab3cb6363f9871 to your computer and use it in GitHub Desktop.
問題のあるインスタンスをよしなにブロックしてくれるGASsc

スプレッドシートとにらめっこして手動で追加していくのに疲れたので作りました。 GASで動くのでタイムスケジュールを組んであげると幸せになれるかもしれません。

// CHANGE HERE
HOST = "" // サーバーのホスト部を指定  ex) shahu.ski
TOKEN = "" // 権限のあるトークンを指定
DISCORD_WEBHOOK_URL = "" // 通知送信先のwebhookURL (空欄の場合webhook通知はなし)

// スプシから問題のあるインスタンスのリストを取得
function getData(sheetId, sheetName) {
  var sheet = SpreadsheetApp.openById(sheetId).getSheetByName(sheetName);
  var rows = sheet.getDataRange().getValues();
  return rows;
}

// ホストのインスタンスブロックリストを取得
function getBlockLists(host, token) {
  // https://{host}/api/admin/meta から既存のブロックリストを取得
  return JSON.parse(UrlFetchApp.fetch(
    `https://${host}/api/admin/meta`, 
    {
      'method': 'POST',
      'headers' : {'Content-Type': 'application/json'},
      'payload':JSON.stringify({i : token})
    }
  ).getContentText())["blockedHosts"];
}

// ホストのインスタンスブロックリストに追加
function addBlockLists(host, token, blockHosts) {
  return UrlFetchApp.fetch(
    `https://${host}/api/admin/update-meta`, 
    {
      'method': 'POST',
      'headers' : {'Content-Type': 'application/json'},
      'payload':JSON.stringify({i : token, "blockedHosts" : blockHosts})
    }
  );
}

// discord送信
function sendToDiscordWebhook(unblockedInstanceList, newlyBlockedInstanceList) {
  if ( DISCORD_WEBHOOK_URL.length === 0 ) return;

  const embed = {
    "content": "",
    "tts": false,
    "embeds": [
      {
        "title": HOST + "の連合状態が更新されました", 
        "url": HOST.startsWith("https://") ? HOST : "https://" + HOST,
        "thumbnail": { "url": HOST.startsWith("https://") ? HOST + "/favicon.ico" : "https://" + HOST + "/favicon.ico" },
        "color": parseInt("ff6fac", 16),
        // 簡単なタイトルと文章を表のように並べることができます(1行:3つまで, サムネイルが入ると2つまで表示)
        "fields": [
          {
            "name": ":white_check_mark: ブロック解除されたインスタンス (" + unblockedInstanceList.length + "件)",
            "value": unblockedInstanceList.length===0 ? "なし" : unblockedInstanceList.join("\n"),
            "inline": true
          },
          {
            "name": ":negative_squared_cross_mark: ブロックされたインスタンス (" + newlyBlockedInstanceList.length + "件)",
            "value": newlyBlockedInstanceList.length===0 ? "なし" : newlyBlockedInstanceList.join("\n"),
            "inline": true
          }
        ],
      }
    ]
  }
  const param = {
    "method": "POST",
    "headers": { 'Content-type': "application/json" },
    "payload": JSON.stringify(embed)
  }

  UrlFetchApp.fetch(DISCORD_WEBHOOK_URL, param);
}

function main() {
  // https://docs.google.com/spreadsheets/d/1ifqjnJWikLkpVERjvNQ7-_Rbi8l-d6EtUBu0AopvHe0/edit?pli=1&gid=891834841#gid=891834841
  var data = getData('1ifqjnJWikLkpVERjvNQ7-_Rbi8l-d6EtUBu0AopvHe0', 'サーバー一覧');
  
  // スプレッドシートの中から問題のあるインスタンスと問題の解決したインスタンスを抽出
  let currentProblemInstanceList = [];
  let resolvedProblemInstanceList = [];
  data.filter(function( value, index, array ) {
    if ( value[3] === '問題発生中' && value[1] === false ) currentProblemInstanceList.push(value[2]);
    if ( value[3] === '対処済み' && value[1] === false ) resolvedProblemInstanceList.push(value[2]);
  });

  // 既存のブロックリストを取得
  const blockedHosts = getBlockLists(HOST, TOKEN);
  // 既存のブロックリストに問題のあるインスタンスを結合させた配列を生成
  const blockHosts = Array.from(new Set([...blockedHosts, ...currentProblemInstanceList]));

  // 問題の解決したインスタンスがあればピックアップして削除
  const duplicatedArr = [...blockHosts, ...resolvedProblemInstanceList].filter(item => blockHosts.includes(item) && resolvedProblemInstanceList.includes(item));
  duplicatedArr.forEach((value, index, array) => blockHosts.splice(blockHosts.indexOf(value), 1));

  let unblockedInstanceList = []
  let newlyBlockedInstanceList = []
  // 解除されたインスタンスのリストを作成
  unblockedInstanceList = blockedHosts.filter(host => resolvedProblemInstanceList.includes(host));
  // 新たにブロックされたインスタンスのリストを作成(現在の問題インスタンスのうち、まだブロックされていなかったもの)
  newlyBlockedInstanceList = currentProblemInstanceList.filter(host => !blockedHosts.includes(host));

  Logger.log(unblockedInstanceList);
  Logger.log(newlyBlockedInstanceList);

  if( newlyBlockedInstanceList.length > 0 || unblockedInstanceList > 0 ) {
    // 指定したホストに対してblock_hostsを追加
    addBlockLists(HOST, TOKEN, blockHosts);
    // 通知
    sendToDiscordWebhook(unblockedInstanceList, newlyBlockedInstanceList);
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment