GongT / AgentNEO.V2Ray.Export

// ==UserScript==
// @name         AgentNEO.V2Ray.Export
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  AgentNEO生成V2Ray配置
// @author       GongT
// @updateURL https://openuserjs.org/meta/GongT/AgentNEO.V2Ray.Export.meta.js
// @downloadURL https://openuserjs.org/install/GongT/AgentNEO.V2Ray.Export.user.js
// @copyright 2020, GongT (https://openuserjs.org/users/GongT)
// @license MIT
// @match        https://neoproxy.org/services/*/nodes
// @match        https://neoproxy.org/services/*/settings
// @match        https://ageneo.co/services/*/nodes
// @match        https://ageneo.co/services/*/settings
// @match        https://neoladder.com/services/*/nodes
// @match        https://neoladder.com/services/*/settings
// @match        https://neoladder.org/services/*/nodes
// @match        https://neoladder.org/services/*/settings
// @grant        none
// ==/UserScript==

(function () {
  'use strict';
  let uuid = $('#service_v2ray_uuid').val();
  if (uuid) {
    console.log('[v2rayex] remember your uuid.');
    localStorage.my_uuid = uuid;
    return;
  }

  const map = new Map();
  $('#v2ray tbody >tr').map(function () {
    return $('>td', this).map(function () {
      return $(this).text().trim();
    });
  }).toArray().map($arr => $arr.toArray()).map((
    [_qr, title, rate, host, port, alterID, encrypt, transfer, tls, ws]
  ) => {
    const key = `proxy_${encrypt}_${transfer}_${tls}${ws.replace(/\//, '_')}`;
    if (!map.has(key)) {
      map.set(key, []);
    }
    map.get(key).push({
      title,
      rate,
      host,
      port,
      alterID,
      encrypt,
      transfer,
      tls,
      ws
    });
  });

  const outbounds = [...map.entries()].map(([key, list]) => createOutbound(key, list)).reverse();

  const v2ray = {
    inbounds: [{
      tag: "socks-listen",
      listen: "127.0.0.1",
      port: 23270,
      protocol: "socks",
      settings: {
        auth: "noauth",
        udp: true,
        ip: "127.0.0.1"
      }
    }],
    routing: {
      domainStrategy: "AsIs",
      rules: [{
        type: "field",
        inboundTag: "socks-listen",
        balancerTag: "balancer"
      }],
      balancers: [{
        tag: "balancer",
        selector: ["proxy"]
      }]
    },
    outbounds,
  };

  createV2rayTab(v2ray);
})();

function createOutbound(key, list) {
  const uuid = localStorage.my_uuid || 'UUID_FILL_HERE';

  const {
    transfer,
    tls,
    ws
  } = list[0];

  const outbound = {
    protocol: "vmess",
    tag: key,
    settings: {
      vnext: list.map(({
        host,
        port,
        alterID
      }) => {
        return {
          address: host,
          port: parseInt(port),
          users: [{
            id: uuid,
            alterId: parseInt(alterID)
          }]
        };
      })
    },
    streamSettings: {
      network: transfer,
    }
  };

  if (tls === 'tls') {
    outbound.streamSettings.security = 'tls';
  }
  if (ws) {
    outbound.streamSettings.wsSettings = {
      path: ws
    };
  }

  return outbound;
}

function createV2rayTab(v2ray) {
  $('#myTab').append(
    $('<li class="nav-item" />').append(
      $('<a/>').attr({
        'class': "nav-link",
        id: "shadowsocks-tab",
        'data-toggle': 'tab',
        href: '#v2ray-export',
        role: 'tabpanel',
        'aria-labelledby': 'v2ray-export',
      }).text('V2Ray JSON')
    )
  );
  $('#myTabContent').append(
    $('<div class="tab-pane fade" id="v2ray-export" role="tabpanel" aria-labelledby="v2ray-export">').append(
      $('<textarea />').css({
        width: '100%',
        minHeight: '100em'
      }).val(JSON.stringify(v2ray, null, 2))
    )
  );
}