PageSourceSearch

https://www.efvalve.com/wp-content/plugins/l-translate-dashboard/assets/lsm-chatway-track.js?ver=1.1.0

js efvalve.com collected 2026-10-04 04:55:41 UTC 6,760 bytes, 249 lines download raw bytes

1/**
2 * Chatway 访客消息 -> L-TRANSLATE /cj
3 * 无需 Chatway Dashboard Webhook,在浏览器侧拦截 widget 发往 chatway.app 的消息请求。
4 */
5(function () {
6  "use strict";
7
8  var CFG = window.__LTD_CHATWAY__ || {};
9  var ENDPOINT = CFG.endpoint || "https://tr.junj.cc/cj";
10  var sent = Object.create(null);
11  var sentKeys = [];
12
13  function isChatwayUrl(url) {
14    if (!url) return false;
15    var u = String(url).toLowerCase();
16    return u.indexOf("chatway.app") !== -1;
17  }
18
19  function parseBody(body) {
20    if (body == null) return null;
21    if (typeof body === "string") {
22      try {
23        return JSON.parse(body);
24      } catch (e) {
25        return null;
26      }
27    }
28    if (typeof ArrayBuffer !== "undefined" && body instanceof ArrayBuffer) {
29      try {
30        return JSON.parse(new TextDecoder("utf-8").decode(body));
31      } catch (e) {
32        return null;
33      }
34    }
35    if (typeof body === "object" && typeof body.byteLength === "number") {
36      try {
37        return JSON.parse(new TextDecoder("utf-8").decode(body));
38      } catch (e) {
39        return null;
40      }
41    }
42    return null;
43  }
44
45  function pickText(obj) {
46    if (!obj || typeof obj !== "object") return "";
47    var keys = ["content", "text", "body", "message", "msg"];
48    for (var i = 0; i < keys.length; i++) {
49      var v = obj[keys[i]];
50      if (typeof v === "string" && v.trim()) return v.trim();
51    }
52    return "";
53  }
54
55  function pickRole(obj) {
56    if (!obj || typeof obj !== "object") return "";
57    return String(
58      obj.sender_type ||
59        obj.senderType ||
60        obj.sender ||
61        obj.from ||
62        obj.role ||
63        obj.user_type ||
64        ""
65    )
66      .trim()
67      .toLowerCase();
68  }
69
70  function isVisitorRole(role) {
71    if (!role) return true;
72    if (
73      role.indexOf("agent") !== -1 ||
74      role.indexOf("admin") !== -1 ||
75      role.indexOf("operator") !== -1 ||
76      role.indexOf("staff") !== -1
77    ) {
78      return false;
79    }
80    return true;
81  }
82
83  function collectMessageNodes(root, out, depth) {
84    if (!root || typeof root !== "object" || depth > 4) return;
85    if (Array.isArray(root)) {
86      for (var i = 0; i < root.length; i++) {
87        collectMessageNodes(root[i], out, depth + 1);
88      }
89      return;
90    }
91    var text = pickText(root);
92    var role = pickRole(root);
93    var id =
94      root.id ||
95      root.message_id ||
96      root.messageId ||
97      root.uuid ||
98      "";
99    var conv =
100      root.conversation_id ||
101      root.conversationId ||
102      root.chat_id ||
103      root.chatId ||
104      (root.conversation && (root.conversation.id || root.conversation.conversation_id)) ||
105      "";
106    if (text && isVisitorRole(role)) {
107      out.push({
108        content: text,
109        id: id,
110        conversation_id: conv,
111        name:
112          root.name ||
113          root.visitor_name ||
114          (root.visitor && root.visitor.name) ||
115          "",
116        email:
117          root.email ||
118          root.visitor_email ||
119          (root.visitor && root.visitor.email) ||
120          "",
121        phone:
122          root.phone ||
123          (root.visitor && root.visitor.phone) ||
124          "",
125      });
126    }
127    var keys = Object.keys(root);
128    for (var j = 0; j < keys.length; j++) {
129      collectMessageNodes(root[keys[j]], out, depth + 1);
130    }
131  }
132
133  function getLanding() {
134    try {
135      var raw = localStorage.getItem("lsm_first_landing");
136      return raw ? JSON.parse(raw) : {};
137    } catch (e) {
138      return {};
139    }
140  }
141
142  function rememberEvent(eventId) {
143    if (sent[eventId]) return false;
144    sent[eventId] = 1;
145    sentKeys.push(eventId);
146    if (sentKeys.length > 300) {
147      var old = sentKeys.shift();
148      delete sent[old];
149    }
150    return true;
151  }
152
153  function sendInquiry(payload) {
154    try {
155      var body = new URLSearchParams(payload).toString();
156      var blob = new Blob([body], {
157        type: "application/x-www-form-urlencoded;charset=UTF-8",
158      });
159      if (navigator.sendBeacon && navigator.sendBeacon(ENDPOINT, blob)) return;
160      fetch(ENDPOINT, {
161        method: "POST",
162        mode: "no-cors",
163        keepalive: true,
164        headers: {
165          "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
166        },
167        body: body,
168      }).catch(function () {});
169    } catch (e) {}
170  }
171
172  function forwardMessage(msg) {
173    var text = msg.content || "";
174    if (!text) return;
175    var convId = String(msg.conversation_id || "unknown");
176    var msgId = String(msg.id || text.slice(0, 64));
177    var eventId = "chatway:client:" + convId + ":" + msgId;
178    if (!rememberEvent(eventId)) return;
179
180    var landing = getLanding();
181    sendInquiry({
182      form_source: "chatway",
183      form_name: "Chatway Live Chat",
184      form_id: "chatway",
185      site_domain: location.hostname,
186      page_url: location.href,
187      "your-inquiry": text,
188      message: text,
189      event_id: eventId,
190      chatway_conversation_id: convId,
191      chatway_message_id: msgId,
192      name: msg.name || "",
193      email: msg.email || "",
194      phone: msg.phone || "",
195      landing_url: landing.urlFull || "",
196      source_type: landing.type || "",
197      source_medium: landing.medium || "",
198      utm_source: landing.utmSource || "",
199      utm_medium: landing.utmMedium || "",
200      utm_campaign: landing.campaign || "",
201      gclid: landing.gclid || "",
202    });
203  }
204
205  function handleChatwayRequest(url, method, body) {
206    if (!isChatwayUrl(url) || String(method || "GET").toUpperCase() !== "POST") {
207      return;
208    }
209    var data = parseBody(body);
210    if (!data) return;
211    var messages = [];
212    collectMessageNodes(data, messages, 0);
213    for (var i = 0; i < messages.length; i++) {
214      forwardMessage(messages[i]);
215    }
216  }
217
218  var origFetch = window.fetch;
219  if (typeof origFetch === "function") {
220    window.fetch = function (input, init) {
221      try {
222        var url =
223          typeof input === "string"
224            ? input
225            : input && typeof input.url === "string"
226              ? input.url
227              : "";
228        var method = (init && init.method) || "GET";
229        var body = init && init.body;
230        handleChatwayRequest(url, method, body);
231      } catch (e) {}
232      return origFetch.apply(this, arguments);
233    };
234  }
235
236  var origOpen = XMLHttpRequest.prototype.open;
237  var origSend = XMLHttpRequest.prototype.send;
238  XMLHttpRequest.prototype.open = function (method, url) {
239    this.__ltdChatwayMethod = method;
240    this.__ltdChatwayUrl = url;
241    return origOpen.apply(this, arguments);
242  };
243  XMLHttpRequest.prototype.send = function (body) {
244    try {
245      handleChatwayRequest(this.__ltdChatwayUrl, this.__ltdChatwayMethod, body);
246    } catch (e) {}
247    return origSend.apply(this, arguments);
248  };
249})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.