WME Reverse Nodes

Serves to reverse the nodes A and B of a segment, in order to better manage restrictions on multiples segments.

目前為 2017-08-02 提交的版本,檢視 最新版本

// ==UserScript==
// @name             WME Reverse Nodes
// @name:fr          WME Reverse Nodes
// @description      Serves to reverse the nodes A and B of a segment, in order to better manage restrictions on multiples segments.
// @description:fr   Sert à inverser les nodes A et B d'un segment, dans le but de mieux gérer les restrictions sur segments multiples.
// @include          https://www.waze.com/editor/*
// @include          https://www.waze.com/*/editor/*
// @include	         https://beta.waze.com/editor/*
// @include 	       https://beta.waze.com/*/editor/*
// @exclude          https://www.waze.com/user/*
// @exclude          https://www.waze.com/*/user/*
// @namespace        WME_Reverse_Nodes
// @version          1.3
// @grant            none
// ==/UserScript==





function WRNAB_Injected(){

  var WRNAB_version = "1.3";
  var debug = false;
  var WRNAB_API = {};
  WRNAB_API.require = {};
  
  /* bootstrap */
  function WRNAB_bootstrap(){
	  if (typeof(unsafeWindow) === "undefined"){
		  unsafeWindow = ( function () {
			  var dummyElem = document.createElement('p');
			  dummyElem.setAttribute('onclick', 'return window;');
			  return dummyElem.onclick();
		  }) ();
	  }
    /* begin running the code! */
	  log("Start");
	  setTimeout(initialize, 1000);
    
  }

  //==========  Helper ==============================//



  function getElementsByClassName(classname, node) {
    if(!node) node = document.getElementsByTagName("body")[0];
    var a = [];
    var re = new RegExp('\\b' + classname + '\\b');
    var els = node.getElementsByTagName("*");
    for (var i=0,j=els.length; i<j; i++)
      if (re.test(els[i].className)) a.push(els[i]);
    return a;
  }

  function getId(node) {
	  return document.getElementById(node);
  }

  function log(msg, obj)
  {
    if (obj==null)
       console.log("WME Reverse Nodes AB v" + WRNAB_version + " - " + msg);
    else if(debug)
       console.debug("WME Reverse Nodes AB v" + WRNAB_version + " - " + msg + " " ,obj);
    
  }
      



  //==========  /Helper ==============================//

  function initialize()
  {
      initializeWazeObjects();   
  }

  function waitForObject(object)
  {
    var obj=null;
    if (object.r==true)
    {
        if (debug) log ("eval: " + (object.s!=null?object.s:'dummy') + "="+ ((typeof(window.require)=="function")?"require":"WRNAB_API.require") +"(\"" + object.o + "\")");
        eval ((object.s!=null?object.s:'dummy') + '=' + ((typeof(window.require)=="function")?'require':'WRNAB_API.require') +'("' + object.o + '")');  
        eval ("obj=" + (object.s!=null?object.s:'dummy'));
    		if (debug) log("obj", obj);
    }else{
    
        if (debug) log ("eval: " + "typeof(unsafeWindow." + object.o.replace(/\//g, '.') + ")");
        obj=eval("typeof(unsafeWindow." + object.o.replace(/\//g, '.') + ")");
    }
    if(obj === "undefined")
    {
        log(object.o + ' KO');
        window.setTimeout(waitForObject.caller, 500);
        return false;
    }
    if (debug) log(object.s + ' OK');

    if (object.s!=null && object.r==false)
        eval (object.s + "=" + object.o.replace(/\//g, '.'));
  
    return true;


  }


  function initializeWazeObjects()
  {
    var objectToCheck = [
    	{o: "Waze",																s: "waze",														r: false},
	    {o: "Waze.vent",													s: "wazeVent",												r: false},
	    {o: "Waze.controller",										s: "wazeController",									r: false},
	    {o: "Waze.model",													s: "wazeModel",												r: false},
	    {o: "Waze.map",														s: "wazeMap",													r: false},
	    {o: "Waze.loginManager",									s: "WazeLoginManager",								r: false},
	    {o: "Waze.selectionManager",							s: "WazeSelectionManager",						r: false},
	    {o: "Waze/Action/UpdateObject",						s: "WazeActionUpdateObject",					r: true},
	    {o: "Waze/Action/UpdateSegmentGeometry",  s: "WazeUpdateSegmentGeometry",       r: true},
		  {o: "Waze/Action/ConnectSegment",			    s: "WazeActionConnectSegment",        r: true},
	    {o: "Waze/Action/DisconnectSegment",			s: "WazeActionDisconnectSegment",     r: true},
	    {o: "Waze/Action/MultiAction",            s: "WazeActionMultiAction",           r: true},
	    {o: "Waze/Model/Graph/Actions/SetTurn",   s: "WazeModelGraphActionsSetTurn",    r: true},
	    {o: "Waze/Model/Graph/Turn",              s: "WazeModelGraphTurn",              r: true},
      {o: "Waze/Model/Graph/TurnData",          s: "WazeModelGraphTurnData",          r: true},
      {o: "Waze/Model/Graph/TurnGraph",         s: "WazeModelGraphTurnGraph",         r: true},
      {o: "Waze/Model/Graph/Vertex",            s: "WazeModelGraphVertex",            r: true},
	    {o: "Waze.loginManager.user",             s: "me",															r: false},
      {o: "me.rank",									          s: "ul",															r: false},
      {o: "me.isAreaManager",					          s: "uam",															r: false},
	    {o: "localStorage",												s: null,															r: false}
	    ];

	  for (var i=0; i<objectToCheck.length; i++)
	  {
			  if (!waitForObject(objectToCheck[i])) return;    
	  }
    
    
    initializeWazeUI();

  }

  function initializeWazeUI()
  {


      var userInfo = getId('user-info');
      if (userInfo==null)
      {
          window.setTimeout(initializeWazeUI, 500);
          return;
      }

      var navTabs=userInfo.getElementsByTagName('ul');
      if (navTabs.length==0)
      {
          window.setTimeout(initializeWazeUI, 500);
          return;
      }
      if (typeof(navTabs[0])==='undefined')
      {
          window.setTimeout(initializeWazeUI, 500);
          return;
      }
      
      var tabContents=userInfo.getElementsByTagName('div');
      if (tabContents.length==0)
      {
          window.setTimeout(initializeWazeUI, 500);
          return;
      }
      if (typeof(tabContents[0])==='undefined')
      {
          window.setTimeout(initializeWazeUI, 500);
          return;
      }
    
      WRNAB_Init();
  }



  function WRNAB_newSelectionAvailable()
  {
      //log('WazeSelectionManager',WazeSelectionManager);
      if (WazeSelectionManager.selectedItems.length!=1)
          return;
      var selectedObject = WazeSelectionManager.selectedItems[0].model;
      if (selectedObject.type!="segment")
          return;
      //log('uam', uam);
		  if (!uam) return;
      var attributes = selectedObject.attributes;
		  //log('attributes', attributes);
		
		  if (attributes.fwdRestrictions !== undefined && attributes.fwdRestrictions.length > 0){
		    var fwdRestrictions = attributes.fwdRestrictions;
		  }
		  if (attributes.revRestrictions !== undefined && attributes.revRestrictions.length > 0){
		    var revRestrictions = attributes.revRestrictions;
		  }
		
      var editPanel=getId('edit-panel');
      if (editPanel.firstElementChild.style.display=='none')
          window.setTimeout(WRNAB_newSelectionAvailable, 100);
      
      // ok: 1 selected item and pannel is shown
      
      
      
      if (selectedObject.type=="segment")
      {
          item=getId("segment-edit-general");
          
          var WRNAB_Controle=document.createElement('Div');
          WRNAB_Controle.id="WRNAB-Controle";

		      WRNAB_Controle.innerHTML='<input type="button" id="_btnInvertAB" value="Reverse Nodes A/B">';
				
		      item.appendChild(WRNAB_Controle);
          
          getId("_btnInvertAB").onclick=invertNodeAB;
          //log("wazeModel.actionManager",wazeModel.actionManager);
      }
      
  }

  function WRNAB_Init()
  {
		
      WazeSelectionManager.events.register("selectionchanged", null, WRNAB_newSelectionAvailable);

      log('init done.');

  }

  function onScreen(obj)
  {
      if (obj.geometry)
      {
          return(wazeMap.getExtent().intersectsBounds(obj.geometry.getBounds()));
      }
      return false;
  }

  function isSegmentEditable(seg)
  {
      var rep = true;
      if (seg==null) return false;
      //if (Waze.loginManager.user.isCountryManager() ) rep = true;
      if (!uam) rep = false;
      var ndA = wazeModel.nodes.get(seg.attributes.fromNodeID);
      var ndB = wazeModel.nodes.get(seg.attributes.toNodeID);
      
      if ((seg.attributes.permissions == 0) || (seg.attributes.hasClosures))
        rep = false;
      
      if ((ndA.attributes.permissions == 0) || (seg.attributes.hasClosures))
        rep = false;
      
      if ((ndB.attributes.permissions == 0) || (seg.attributes.hasClosures))
        rep = false;

      return rep;
  }

  function invertNodeAB()
  {
      if (WazeSelectionManager.selectedItems.length!=1)
          return;
      var seg =  wazeModel.segments.get(WazeSelectionManager.selectedItems[0].model.attributes.id);
      if (seg.type!="segment")
          return;
      
      var attr = seg.attributes;
      log("seg",seg);
		  log("attr",attr);
		
		
		  var sid = attr.id;
		
      // si non nomme, on touche pas:
      if (attr.primaryStreetID==null)
      {
          log("Unnamed segment. Do not put my name on it!");
          return;
      }
      
      // si locke: on edite pas
      /*if ((attr.lockRank==null && attr.rank>usrRank) ||
          (attr.lockRank!=null && attr.lockRank>usrRank)) 
      {
          log("locked: " + attr.rank + " " + attr.lockRank);
          continue;
      }
      */
      
      var ndA = wazeModel.nodes.get(attr.fromNodeID);
      var ndB = wazeModel.nodes.get(attr.toNodeID);
      log("ndA", ndA);
      log("ndB", ndB);
      // verification de pbs sur nodes (unterminated roads par ex)
      if (!ndA || !ndB) 
      {
          log("Bad nodes: A=" + ndA + " B=" + ndB);
          return;
      }        


      // On verifie que le segment est affiche a l'ecran
      if (onScreen(ndA) && onScreen(ndB))
      {
          log("IN Screen!");
      }
      else
      {
          log("OUT of Screen");
          return;
      }
      
      // On verifie que le segment est éditable
      if (!isSegmentEditable(seg))
      {
          log("Not editable!");
          return;
      }
          
      // Mémorisation des paramètre du segment pour les reporter après changement de sens
		  var newAttr={};
		  //var fromConnections = attr.toConnections.clone();
      //var toConnections = attr.fromConnections.clone();
		  newAttr.fwdDirection = attr.revDirection;
      newAttr.revDirection = attr.fwdDirection;
      newAttr.fwdTurnsLocked = attr.revTurnsLocked;
      newAttr.revTurnsLocked = attr.fwdTurnsLocked;
      newAttr.fwdMaxSpeed = attr.revMaxSpeed;
      newAttr.revMaxSpeed = attr.fwdMaxSpeed;
      newAttr.fwdMaxSpeedUnverified = attr.revMaxSpeedUnverified;
      newAttr.revMaxSpeedUnverified = attr.fwdMaxSpeedUnverified;
      newAttr.restrictions = attr.restrictions.clone();
      
      for (i=0; i<newAttr.restrictions.length; i++){
      	newAttr.restrictions[i] = newAttr.restrictions[i].withReverseDirection();
      }
      
      log("seg",seg);
		  log("attr",attr);
		  log("newAttr", newAttr);
		  
		  
      /*----------------------------------------------------------------------------
       New éditor:
       f = forward direction (A>B)
       r = reverse direction (B>A)
       
       waze.model._turnGraph._adjacencyList["69264747f"]
       --> {295413973f: {_instructionOpcode: null,
                        _restrictions:Array[0],
                        _state:1 }
       
       waze.model._turnGraph.getTurn(waze.model.segments.objects["69264747"],waze.model.segments.objects["69264746"])
       --> {_fromVertex, _toVertex , _turnData}
       
       _turn = waze.model.getTurnGraph().getTurnThroughNode(waze.model.nodes.get("74077390"),waze.model.segments.get("69264747"),waze.model.segments.get("69264746"))
             = waze.model._turnGraph.getTurn( _turn.getFromVertex(), _turn.getToVertex())
             --> {_fromVertex, _toVertex , _turnData}
       
       _turn.getTurnData().getInstructionOpcode()
    
       waze.model.getRoadGraph().getVertexNodeID(waze.model.getTurnGraph().getTurnThroughNode(waze.model.nodes.get("74077390"),waze.model.segments.get("69264747"),waze.model.segments.get("69264746")).getFromVertex())
       e {_fromVertex: e, _toVertex: e, _turnData: e}
              _fromVertex:e
                  _direction:true    --> A>B
                  _segmentID:69264747
              _toVertex:e
                  _direction:false    --> B>A
                  _segmentID:69264745
              _turnData:e
                  _instructionOpcode:null
                  _restrictions:Array[0]
                  _state:2
                  
       -------------------------------------
       CLASS_NAME: "Waze.Action.SetTurn" --> require("Waze/Model/Graph/Actions/SetTurn");
       
      -----------------------------------------------------------------------------*/ 
      var sconA={};
      var sconB={};
      var fromConnections = {};
      var toConnections = {};
      
      
      // pour les segments connecté à la node A
      for (var s=0; s<ndA.attributes.segIDs.length; s++)
      {
        var scon=ndA.attributes.segIDs[s];
        
        // On mémorise les directions autorisées vers le segment 
        if (debug){
          log("sconA["+scon+"]  ndA: "+ndA.attributes.id+" : " + attr.id);
          log("_turn",wazeModel.getTurnGraph().getTurnThroughNode(ndA,wazeModel.segments.get(scon),wazeModel.segments.get(attr.id)));
        }
        sconA[scon]= wazeModel.getTurnGraph().getTurnThroughNode(ndA,wazeModel.segments.get(scon),wazeModel.segments.get(attr.id));
        sconA[scon]._toVertex._direction = sconA[scon]._toVertex._direction ? false : true;
        if (scon == attr.id) //u-turn
          sconA[scon]._fromVertex._direction = sconA[scon]._fromVertex._direction ? false : true;
        // On mémorise les directions autorisées sortantes du segment 
        if (debug){
          log("toConnections["+scon+"]  ndA: "+ndA.attributes.id+" : " + attr.id);
          log("_turn",wazeModel.getTurnGraph().getTurnThroughNode(ndA,wazeModel.segments.get(attr.id),wazeModel.segments.get(scon)));
        }
        toConnections[scon] = wazeModel.getTurnGraph().getTurnThroughNode(ndA,wazeModel.segments.get(attr.id),wazeModel.segments.get(scon));
        toConnections[scon]._fromVertex._direction = toConnections[scon]._fromVertex._direction ? false : true;
        if (scon == attr.id) //u-turn
          toConnections[scon]._toVertex._direction = toConnections[scon]._toVertex._direction ? false : true;
      
      }
      // pour les segments connecté à la node B    
      for (var s=0; s<ndB.attributes.segIDs.length; s++)
      {
        var scon=ndB.attributes.segIDs[s];
        //if (scon != attr.id){
          if (debug){
            log("sconB["+scon+"]  ndB: "+ndB.attributes.id+" : " + attr.id);
            log("_turn",wazeModel.getTurnGraph().getTurnThroughNode(ndB,wazeModel.segments.get(scon),wazeModel.segments.get(attr.id)));
          }
          sconB[scon]= wazeModel.getTurnGraph().getTurnThroughNode(ndB,wazeModel.segments.get(scon),wazeModel.segments.get(attr.id));
          sconB[scon]._toVertex._direction = sconB[scon]._toVertex._direction ? false : true;
          if (scon == attr.id)  //u-turn
            sconB[scon]._fromVertex._direction = sconB[scon]._fromVertex._direction ? false : true;
          if (debug){
            log("fromConnections["+scon+"]  ndB: "+ndB.attributes.id+" : " + attr.id);
            log("_turn",wazeModel.getTurnGraph().getTurnThroughNode(ndB,wazeModel.segments.get(attr.id),wazeModel.segments.get(scon)));
          }
          fromConnections[scon] = wazeModel.getTurnGraph().getTurnThroughNode(ndB,wazeModel.segments.get(attr.id),wazeModel.segments.get(scon));
          fromConnections[scon]._fromVertex._direction = fromConnections[scon]._fromVertex._direction ? false : true;
          if (scon == attr.id) //u-turn
            fromConnections[scon]._toVertex._direction = fromConnections[scon]._toVertex._direction ? false : true;
          
        //}
      }
      
      /*
      log("wazeModel._turnGraph._adjacencyList["+attr.id+"f]", wazeModel._turnGraph._adjacencyList[attr.id+"f"]);
      log("wazeModel._turnGraph._adjacencyList["+attr.id+"r]", wazeModel._turnGraph._adjacencyList[attr.id+"r"]);
      
      */
      log("sconA",sconA);
      log("sconB",sconB);
      log("fromConnections", fromConnections);
      log("toConnections", toConnections);

      //on inverse la géométrie du segment
      var geo = seg.geometry.clone();
      geo.components.reverse();

      // controle de position
      var nbPoints = geo.components.length-1;
      if (!geo.components[0].equals(ndB.attributes.geometry)){
        if (debug) log("point 0 et dif de node A");
        var delta = {x:0, y:0};
        delta.x =ndB.attributes.geometry.x - geo.components[0].x;
        delta.y = ndB.attributes.geometry.y - geo.components[0].y;
        geo.components[0].move(delta.x, delta.y);
      } 
      if (!geo.components[nbPoints].equals(ndA.attributes.geometry)){
        if (debug) log("point "+nbPoints+ " est dif de node B");
        var delta = {x:0, y:0};
        delta.x = ndA.attributes.geometry.x - geo.components[nbPoints].x;
        delta.y = ndA.attributes.geometry.y - geo.components[nbPoints].y;
        geo.components[nbPoints].move(delta.x, delta.y);
        
      }
      
      // On deconnecte le segment
      //wazeModel.actionManager.add(new WazeActionDisconnectSegment(seg, ndB));
      //wazeModel.actionManager.add(new WazeActionDisconnectSegment(seg, ndA));
      
      // maj de la géo du seg
      wazeModel.actionManager.add(new WazeUpdateSegmentGeometry (seg,seg.geometry,geo));

      // On reconnecte le segment
      wazeModel.actionManager.add(new WazeActionConnectSegment(ndB, seg));
      wazeModel.actionManager.add(new WazeActionConnectSegment(ndA, seg));
      
      //on replace les paramètre inversé
      wazeModel.actionManager.add(new WazeActionMultiAction ([new WazeActionUpdateObject(seg, newAttr)]));

      //on replace les autorisations sortantes
      
      for (var sid  in fromConnections)
      {
        var segId = fromConnections[sid]._toVertex._segmentID;
        log("attr.id: " + attr.id + " --> NodeA: " + ndB.attributes.id + " --> segId: " + segId); 
        if (debug) log("fromConnections["+sid+"] = ", fromConnections[sid]);
        switch (fromConnections[sid]._turnData._state){
    		case 0 :
    		  var turn = new WazeModelGraphTurnData();
          turn = turn.withRestrictions(fromConnections[sid]._turnData._restrictions);
          turn = turn.withInstructionOpcode(fromConnections[sid]._turnData._instructionOpcode);
          turn._state = 1;
          var turn1 = new WazeModelGraphTurnData();
          turn1 = turn1.withRestrictions(fromConnections[sid]._turnData._restrictions);
          turn1 = turn1.withInstructionOpcode(fromConnections[sid]._turnData._instructionOpcode);
          turn1._state = 0;
          if (debug){
            log("turn ", turn);
            log("turn1 ", turn1);
          }
          wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, fromConnections[sid].withTurnData(turn)));
    		  wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, fromConnections[sid].withTurnData(turn1)));
    		  break;
    		
    		case 1 :wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn( wazeModel._turnGraph, fromConnections[sid]));
    		  break;
        }
        
      }
      
      for (var sid  in toConnections)
      {
        var segId = toConnections[sid]._toVertex._segmentID;
        log("attr.id: " + attr.id + " --> NodeB: " + ndA.attributes.id + " --> segId: " + segId);
        if (debug) log("toConnections["+sid+"] = ", toConnections[sid]);
        switch (toConnections[sid]._turnData._state){
    		case 0 :
    		  var turn = new WazeModelGraphTurnData();
          turn = turn.withRestrictions(toConnections[sid]._turnData._restrictions);
          turn = turn.withInstructionOpcode(toConnections[sid]._turnData._instructionOpcode);
          turn._state = 1;
          var turn1 = new WazeModelGraphTurnData();
          turn1 = turn1.withRestrictions(toConnections[sid]._turnData._restrictions);
          turn1 = turn1.withInstructionOpcode(toConnections[sid]._turnData._instructionOpcode);
          turn1._state = 0;
          if (debug){
            log("turn ", turn);
            log("turn1 ", turn1);
          }
          wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, toConnections[sid].withTurnData(turn)));
    		  wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, toConnections[sid].withTurnData(turn1)));
    		  break;
    		case 1 :wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, toConnections[sid]));
    		  break;
        }
        
      }
      
      
      //on replace les autorisations entrantes
      log("ndB", ndB);
    	for (var sid in sconB)
      { 
    	  log("sconB: "+sid+" ; nodeA: " + ndB.attributes.id + " attr.id: " + attr.id);
    	  if (debug) log("sconB[sid]:",sconB[sid]);
    		switch (sconB[sid]._turnData._state){
    		case 0 :
    		  var turn = new WazeModelGraphTurnData();
          turn = turn.withRestrictions(sconB[sid]._turnData._restrictions);
          turn = turn.withInstructionOpcode(sconB[sid]._turnData._instructionOpcode);
          turn._state = 1;
          var turn1 = new WazeModelGraphTurnData();
          turn1 = turn1.withRestrictions(sconB[sid]._turnData._restrictions);
          turn1 = turn1.withInstructionOpcode(sconB[sid]._turnData._instructionOpcode);
          turn1._state = 0;
          if (debug){
            log("turn ", turn);
            log("turn1 ", turn1);
          }
          wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, sconB[sid].withTurnData(turn)));
    		  wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, sconB[sid].withTurnData(turn1)));
    		  break;
    		case 1 :wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, sconB[sid]));
    		  break;
        }
        
    		
     	}
      log("ndA", ndA);
    	for (var sid in sconA)
      { 
        log("sconA : "+sid+" ; nodeB: " + ndA.attributes.id + " attr.id: " + attr.id);
    	  if (debug) log("sconA[sid]:",sconA[sid]);
    		switch (sconA[sid]._turnData._state){
    		case 0 :
    		  var turn = new WazeModelGraphTurnData();
          turn = turn.withRestrictions(sconA[sid]._turnData._restrictions);
          turn = turn.withInstructionOpcode(sconA[sid]._turnData._instructionOpcode);
          turn._state = 1;
          var turn1 = new WazeModelGraphTurnData();
          turn1 = turn1.withRestrictions(sconA[sid]._turnData._restrictions);
          turn1 = turn1.withInstructionOpcode(sconA[sid]._turnData._instructionOpcode);
          turn1._state = 0;
          if (debug){
            log("turn ", turn);
            log("turn1 ", turn1);
          }
          wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, sconA[sid].withTurnData(turn)));
    		  wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, sconA[sid].withTurnData(turn1)));
    		  break;
    		case 1 :wazeModel.actionManager.add(new WazeModelGraphActionsSetTurn(wazeModel._turnGraph, sconA[sid]));
    		  break;
        }
        
    	}
      log('Invert node for segment '+attr.id+': Ok');
  
  }
  

  WRNAB_bootstrap();

}var WRNAB_Injected_script = document.createElement("script");
WRNAB_Injected_script.textContent = '' + WRNAB_Injected.toString() + ' \n' + 'WRNAB_Injected();';
WRNAB_Injected_script.setAttribute("type", "application/javascript");
document.body.appendChild(WRNAB_Injected_script);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址