Skip to content

Commit a70d33c

Browse files
committed
xem tin nhan bi go - wip
1 parent fe96409 commit a70d33c

File tree

3 files changed

+385
-0
lines changed

3 files changed

+385
-0
lines changed

popup/tabs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ const tabs = [
9292
{
9393
...CATEGORY.facebook,
9494
scripts: [
95+
s.fb_revealDeletedMessages,
9596
createTitle("--- UI ---", "--- Giao diện ---"),
9697
s.fb_toggleLight,
9798
s.fb_toggleNewFeed,
Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
export default {
2+
icon: "https://github.com/HoangTran0410/RevealDeletedFBMessages/raw/master/icons/icon48.png",
3+
name: {
4+
en: "Facebook - Reveal deleted messages",
5+
vi: "Facebook - Xem tin nhắn bị gỡ",
6+
},
7+
description: {
8+
en: "View deleted messages (since function was turned on) on facebook messenger.",
9+
vi: "Xem lại những tin nhắn đã bị đối phương xóa (kể từ khi bật chức năng) trong facebook messenger.",
10+
},
11+
whiteList: ["https://*.facebook.com/*", "https://*.messenger.com/*"],
12+
13+
onDocumentStart: () => {
14+
// Lưu tất cả tin nhắn - có thể truy cập được từ console trong web facebook
15+
let rvdfm_all_msgs = [];
16+
let rvdfm_all_users = [];
17+
18+
(function () {
19+
console.log("Extension RVDFM - Xem Tin Nhắn Bị Gỡ Trên FB đã BẬT");
20+
21+
rvdfm_all_msgs = JSON.parse(localStorage.rvdfm_all_msgs || "[]");
22+
console.log(
23+
`RVDFM Đã tải lên ${rvdfm_all_msgs.length} tin nhắn từ LocalStorage.`
24+
);
25+
26+
// Lưu lại vào localStorage mỗi khi tắt tab
27+
window.addEventListener("beforeunload", () => {
28+
localStorage.rvdfm_all_msgs = JSON.stringify(rvdfm_all_msgs);
29+
});
30+
31+
//#region ============================ Những hàm hỗ trợ ============================
32+
// Hàm decode data websocket về tiếng việt, loại bỏ những thằng \\
33+
const parse = (str) => {
34+
let ret = str;
35+
let limit = 10;
36+
while (--limit > 0) {
37+
try {
38+
if (ret[0] === '"') ret = JSON.parse(ret);
39+
else ret = JSON.parse(`"${ret}"`);
40+
} catch (e) {
41+
break;
42+
}
43+
}
44+
return ret;
45+
};
46+
47+
// Hàm xuất ra console, xuất chữ và hình - https://stackoverflow.com/a/26286167
48+
const log = {
49+
text: (str, color = "white", bg = "transparent") => {
50+
console.log(`%c${str}`, `color: ${color}; background: ${bg}`);
51+
},
52+
};
53+
// #endregion
54+
55+
//#region ========================================= BẮT ĐẦU HACK :)) =========================================
56+
57+
// Lưu lại webSocket gốc của browser
58+
const original_WebSocket = window.WebSocket;
59+
60+
// Tạo 1 fake webSocket constructor - facebook sẽ gọi hàm này để tạo socket
61+
window.WebSocket = function fakeConstructor(dt, config) {
62+
const websocket_instant = new original_WebSocket(dt, config);
63+
64+
// hàm hỗ trợ
65+
const isMsgIdStr = (str) => str?.startsWith("mid.$");
66+
const isLink = (str) => str?.startsWith("https://");
67+
68+
// Chèn event on message => để bắt tất cả event được dùng bởi facebook trong webSocket
69+
websocket_instant.addEventListener("message", async function (achunk) {
70+
// chuyển binary code của websocket về string utf8
71+
const utf8_str = new TextDecoder("utf-8").decode(achunk.data);
72+
73+
if (
74+
utf8_str[0] === "1" ||
75+
utf8_str[0] === "2" ||
76+
utf8_str[0] === "3"
77+
) {
78+
// Xem trong dữ liệu có id của tin nhắn nào không
79+
const have_msg_id = /(?=mid\.\$)(.*?)(?=\\")/.exec(utf8_str);
80+
81+
// Nếu không có id tin nhắn
82+
if (!have_msg_id) {
83+
const users_data = [];
84+
85+
const user_data_zones =
86+
/(?=\(LS.sp\(\\"25\\")(.*?)(?=:LS.resolve)/gm.exec(utf8_str);
87+
88+
if (user_data_zones != null) {
89+
user_data_zones.forEach((zone) => {
90+
const user_id =
91+
/(?<=\?entity_id=)(.*?)(?=\&entity_type)/.exec(zone);
92+
const avatars = /(?=https)(.*?)(?=\\",)/g.exec(zone);
93+
const small_avatar = parse(avatars[0]);
94+
const big_avatar = parse(avatars[1]);
95+
96+
const user_msg_id = /(?<=, )(.*?)(?=,\[0,1\],)/gm.exec(zone);
97+
});
98+
}
99+
100+
for (let i = 0; i < all_strings.length; i++) {
101+
const str_i = all_strings[i];
102+
103+
// Thông tin người dùng
104+
if (str_i === "13" && all_strings[i + 1] === "25") {
105+
const small_avatar = all_strings[i + 2];
106+
const large_avatar = all_strings[i + 4];
107+
const user_id = /(?<=\?entity_id=).*?(?=\&entity_type)/.exec(
108+
all_strings[i + 3]
109+
)[0];
110+
const full_user_name = all_strings[i + 6];
111+
const short_user_name = all_strings[i + 8];
112+
const unknown_id = all_strings[i + 9];
113+
114+
// Có những event bắt đầu bằng 13 ,25 nhưng không có user name => loại
115+
if (full_user_name) {
116+
users_data.push({
117+
user_id,
118+
small_avatar,
119+
large_avatar,
120+
full_user_name,
121+
short_user_name,
122+
unknown_id,
123+
});
124+
}
125+
}
126+
}
127+
128+
if (users_data.length) {
129+
log.text("Users data: ", "yellow", "black");
130+
console.log(users_data);
131+
}
132+
133+
// Lưu vào rvdfm_all_users
134+
rvdfm_all_users = rvdfm_all_users.concat(users_data);
135+
136+
return;
137+
}
138+
139+
// Lấy ra tất cả các thông tin dùng được trong dữ liệu (những chuỗi nằm giữa 2 dấu nháy kép)
140+
const all_strings_regex = /(\\\")(.*?)(\\\")(?=[,)])/g;
141+
let all_strings = utf8_str.match(all_strings_regex) || [];
142+
all_strings = all_strings.map((str) => parse(str));
143+
144+
// Nếu all_strings có chứa thông tin thì log ra (cho dev dễ debug)
145+
if (all_strings.length) {
146+
// Lấy ra request id: Đây chỉ là mã định danh cho request, tăng dần đều qua từng request...
147+
const request_id = /(?<=\"request_id\":)(.*?)(?=,)/.exec(
148+
utf8_str
149+
)[0];
150+
151+
log.text(
152+
"RVDFM - VÀO LÚC " + new Date().toLocaleString(),
153+
"blue",
154+
"#fff9"
155+
);
156+
console.log("Mọi thông tin: ", {
157+
request_id,
158+
all: all_strings,
159+
utf8_str,
160+
});
161+
} else {
162+
// Không có thông tin gì thì thoát luôn
163+
return;
164+
}
165+
166+
// Bắt đầu lấy ra những tin nhắn từ lượng thông tin trên
167+
let chat = [];
168+
for (let i = 0; i < all_strings.length; i++) {
169+
const str_i = all_strings[i];
170+
171+
// Tin nhắn chữ
172+
if (str_i === "insertMessage" && isMsgIdStr(all_strings[i + 2])) {
173+
const content = all_strings[i + 1];
174+
if (content) {
175+
chat.push({
176+
type: "Chữ",
177+
content: content,
178+
id: all_strings[i + 2],
179+
});
180+
}
181+
}
182+
183+
// Tin nhắn đính kèm: image / gif / video / âm thanh / file
184+
if (
185+
str_i === "insertBlobAttachment" &&
186+
isLink(all_strings[i + 2])
187+
) {
188+
const isImg = all_strings[i + 1]?.startsWith("image-");
189+
const isGif = all_strings[i + 1]?.startsWith("gif-");
190+
const isVideo = all_strings[i + 1]?.startsWith("video-");
191+
const isAudio = all_strings[i + 1]?.startsWith("audioclip-");
192+
193+
const type = isImg
194+
? "Hình ảnh"
195+
: isGif
196+
? "GIF"
197+
: isVideo
198+
? "Video"
199+
: isAudio
200+
? "Âm thanh"
201+
: "Đính kèm";
202+
203+
for (let j = i; j < all_strings.length - 1; j++) {
204+
if (isMsgIdStr(all_strings[j])) {
205+
chat.push({
206+
type: type,
207+
content: all_strings[i + 2],
208+
id: all_strings[j],
209+
});
210+
break;
211+
}
212+
}
213+
}
214+
215+
// Tin nhắn nhãn dán
216+
if (
217+
str_i === "insertMessage" &&
218+
isMsgIdStr(all_strings[i + 1]) &&
219+
isLink(all_strings[i + 6])
220+
) {
221+
chat.push({
222+
type: "Nhãn dán",
223+
content: all_strings[i + 6],
224+
id: all_strings[i + 1],
225+
});
226+
}
227+
228+
// Thả react
229+
if (
230+
str_i === "upsertReaction" &&
231+
isMsgIdStr(all_strings[i + 1])
232+
) {
233+
chat.push({
234+
type: "Thả react",
235+
content: all_strings[i + 2],
236+
id: all_strings[i + 1],
237+
});
238+
}
239+
240+
// Gỡ react
241+
if (
242+
str_i === "deleteReaction" &&
243+
isMsgIdStr(all_strings[i + 1])
244+
) {
245+
const id = all_strings[i + 1];
246+
const content =
247+
rvdfm_all_msgs.find((c) => c.id === id)?.content || "";
248+
249+
chat.push({
250+
type: "Gỡ react",
251+
content: content,
252+
id: id,
253+
});
254+
}
255+
256+
// Tin nhắn chia sẻ vị trí / vị trí trực tiếp
257+
if (
258+
str_i === "xma_live_location_sharing" &&
259+
isMsgIdStr(all_strings[i - 2]) &&
260+
isLink(all_strings[i + 1])
261+
) {
262+
const link = all_strings[i + 1];
263+
264+
chat.push({
265+
type: "Chia sẻ",
266+
content: link,
267+
id: all_strings[i - 2],
268+
});
269+
}
270+
271+
// Thông tin user
272+
// if (str_i === "533" && isLink(all_strings[i + 1])) {
273+
// const avatar = all_strings[i + 1];
274+
// const user_name = all_strings[i + 2];
275+
276+
// chat.push({
277+
// type: "Người dùng",
278+
// avatar: avatar,
279+
// name: user_name,
280+
// });
281+
// }
282+
283+
// Tin nhắn đang chờ
284+
// if (str_i === "130" && all_strings[i + 3] === "pending") {
285+
// chat.push({
286+
// type: "Tin nhắn đang chờ",
287+
// content: all_strings[i + 1],
288+
// avatar: all_strings[i + 2],
289+
// });
290+
// }
291+
292+
// Thu hồi tin nhắn
293+
if (
294+
str_i === "deleteThenInsertMessage" &&
295+
isMsgIdStr(all_strings[i + 2])
296+
) {
297+
const id = all_strings[i + 2];
298+
const msgs =
299+
rvdfm_all_msgs.filter(
300+
(c) => c.id === id && c.type !== "Thu hồi"
301+
) || [];
302+
303+
chat.push({
304+
type: "Thu hồi",
305+
msgs: msgs,
306+
id: id,
307+
});
308+
}
309+
}
310+
311+
// Chèn thời gian hiện tại vào
312+
chat = chat.map((_) => ({ ..._, time: Date.now() }));
313+
314+
console.log("Thông tin lọc được:", chat);
315+
316+
// Lưu vào rvdfm_all_msgs
317+
const old_length = rvdfm_all_msgs.length;
318+
for (let c of chat) {
319+
let isDuplicated =
320+
-1 !==
321+
rvdfm_all_msgs.findIndex(
322+
(_msg) => JSON.stringify(c) === JSON.stringify(_msg)
323+
);
324+
325+
if (!isDuplicated) {
326+
rvdfm_all_msgs = rvdfm_all_msgs.concat(chat);
327+
328+
// Tin nhắn thu hồi
329+
if (c.type === "Thu hồi") {
330+
const deleted_msg_type = c.msgs
331+
.map((_c) => c.type || "không rõ loại")
332+
.join(",");
333+
334+
log.text(
335+
`> Tin nhắn thu hồi: (${deleted_msg_type})`,
336+
"black",
337+
"#f35369"
338+
);
339+
console.log(
340+
c.msgs || "(RVDFM: không có dữ liệu cho tin nhắn này)"
341+
);
342+
343+
rvdfmSendDeletedMsgToContentJs(c.msgs);
344+
}
345+
346+
// Tin nhắn thả/gỡ react
347+
else if (c.type == "Thả react" || c.type === "Gỡ react") {
348+
const target_msg = rvdfm_all_msgs.filter(
349+
(_msg) => _msg.id === c.id
350+
);
351+
352+
log.text(`> ${c.type}:`, "black", "yellow");
353+
console.log(
354+
target_msg || "(RVDFM: không có dữ liệu cho tin nhắn này)"
355+
);
356+
}
357+
}
358+
}
359+
360+
// Hiển thị thông tin lưu tin nhắn mới
361+
const new_lenght = rvdfm_all_msgs.length;
362+
const new_msg_count = new_lenght - old_length;
363+
if (new_msg_count) {
364+
rvdfmSendSavedCounterToContentJs(new_msg_count, new_lenght);
365+
log.text(
366+
`> RVDFM Đã lưu ${new_msg_count} tin nhắn mới! (${new_lenght})`,
367+
"green"
368+
);
369+
}
370+
}
371+
});
372+
373+
return websocket_instant;
374+
};
375+
376+
// Giữ nguyên prototype chỉ đổi constructor thành fake constructor
377+
window.WebSocket.prototype = original_WebSocket.prototype;
378+
window.WebSocket.prototype.constructor = window.WebSocket;
379+
// #endregion
380+
})();
381+
},
382+
};

0 commit comments

Comments
 (0)