Skip to content

Commit 78aae86

Browse files
committed
who is typing is working
1 parent 80e3b4f commit 78aae86

File tree

6 files changed

+180
-56
lines changed

6 files changed

+180
-56
lines changed

popup/helpers/utils.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,19 @@ export async function viewScriptSource(script) {
2525
}
2626

2727
export async function updateScriptClickCount(scriptId) {
28-
let res = await fetch("https://useful-script-statistic.onrender.com/count", {
29-
method: "POST",
30-
headers: { "Content-Type": "application/json" },
31-
body: JSON.stringify({ script: scriptId }),
32-
});
33-
return await res.text();
28+
// return; // TODO remove this before commit
29+
try {
30+
let res = await fetch(
31+
"https://useful-script-statistic.onrender.com/count",
32+
{
33+
method: "POST",
34+
headers: { "Content-Type": "application/json" },
35+
body: JSON.stringify({ script: scriptId }),
36+
}
37+
);
38+
return await res.text();
39+
} catch (e) {
40+
console.log("ERROR update script click count: ", e);
41+
return null;
42+
}
3443
}

popup/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ function createScriptButton(script, isFavorite = false) {
159159
checkmark.className = "checkmark tooltip";
160160
checkmark.onclick = async (e) => {
161161
let newValue = toggleActiveScript(script.id);
162-
newValue && updateScriptClickCount(script.id).then(console.log);
162+
newValue && updateScriptClickCount(script.id);
163163
updateButtonChecker(script, buttonContainer, newValue);
164164
};
165165

@@ -318,7 +318,7 @@ async function runScript(script) {
318318
if (willRun) {
319319
try {
320320
recentScriptsSaver.add(script);
321-
updateScriptClickCount(script.id).then(console.log);
321+
updateScriptClickCount(script.id);
322322
if (isFunction(script.onClickExtension)) await script.onClickExtension();
323323
if (isFunction(script.onClick))
324324
await runScriptInCurrentTab(script.onClick);

scripts/content-scripts/scripts/ufs_global_webpage_context.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,40 @@ const UsefulScriptGlobalPageContext = {
113113
"/picture?height=500&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662"
114114
);
115115
},
116+
getUserProfileDataFromUid: async (uid) => {
117+
const variables = {
118+
userID: uid,
119+
shouldDeferProfilePic: false,
120+
useVNextHeader: false,
121+
scale: 1.5,
122+
};
123+
let f = new URLSearchParams();
124+
f.append("fb_dtsg", require("DTSGInitialData").token);
125+
f.append("fb_api_req_friendly_name", "ProfileCometHeaderQuery");
126+
f.append("variables", JSON.stringify(variables));
127+
f.append("doc_id", "4159355184147969");
128+
129+
let res = await fetch("https://www.facebook.com/api/graphql/", {
130+
method: "POST",
131+
headers: { "content-type": "application/x-www-form-urlencoded" },
132+
body: f,
133+
});
134+
135+
let text = await res.text();
136+
return {
137+
name: UsefulScriptsUtils.decodeEscapedUnicodeString(
138+
/"name":"(.*?)"/.exec(text)?.[1]
139+
),
140+
profiePicLarge: UsefulScriptsUtils.decodeEscapedUnicodeString(
141+
/"profilePicLarge":{"uri":"(.*?)"/.exec(text)?.[1]
142+
),
143+
// profiePicMedium: /"profilePicMedium":{"uri":"(.*?)"/.exec(text)?.[1],
144+
// profiePicSmall: /"profilePicSmall":{"uri":"(.*?)"/.exec(text)?.[1],
145+
// profilePic160: /"profilePic160":{"uri":"(.*?)"/.exec(text)?.[1],
146+
gender: /"gender":"(.*?)"/.exec(text)?.[1],
147+
alternateName: /"alternate_name":"(.*?)"/.exec(text)?.[1],
148+
};
149+
},
116150
decodeArrId(arrId) {
117151
return arrId[0] * 4294967296 + arrId[1];
118152
},
@@ -232,6 +266,7 @@ const UsefulScriptsUtils = {
232266
// https://stackoverflow.com/a/40410744/11898496
233267
// Giải mã từ dạng 'http\\u00253A\\u00252F\\u00252Fexample.com' về 'http://example.com'
234268
decodeEscapedUnicodeString(str) {
269+
if (!str) return "";
235270
return decodeURIComponent(
236271
JSON.parse('"' + str.replace(/\"/g, '\\"') + '"')
237272
);

scripts/fb_revealDeletedMessages.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export default {
88
en: "View deleted messages (since function was turned on) on facebook messenger.",
99
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.",
1010
},
11+
infoLink:
12+
"https://www.facebook.com/groups/j2team.community/posts/1651683238497123/",
13+
1114
whiteList: ["https://*.facebook.com/*", "https://*.messenger.com/*"],
1215

1316
onDocumentStart: () => {
@@ -140,9 +143,4 @@ export default {
140143
};
141144
});
142145
},
143-
144-
onClickExtension: () =>
145-
window.open(
146-
"https://www.facebook.com/groups/j2team.community/posts/1651683238497123/"
147-
),
148146
};

scripts/fb_whoIsTyping.css

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#ufs-who-is-typing {
2+
position: fixed;
3+
top: 50px;
4+
left: 50px;
5+
max-height: calc(100vh - 100px);
6+
overflow: auto;
7+
background-color: #fff;
8+
border-radius: 3px;
9+
}
10+
11+
#ufs-who-is-typing.collapsed .ufs-noti-item {
12+
display: none;
13+
}
14+
15+
#ufs-who-is-typing .ufs-header button {
16+
float: right;
17+
display: inline-block;
18+
font-size: 20px;
19+
line-height: 15px;
20+
cursor: pointer;
21+
}
22+
23+
#ufs-who-is-typing .ufs-noti-item {
24+
position: relative;
25+
padding: 5px;
26+
margin: 10px;
27+
font-size: 1.3em;
28+
background-color: #f1f1f1;
29+
}
30+
31+
#ufs-who-is-typing .ufs-close-btn {
32+
position: absolute;
33+
top: 5px;
34+
right: 5px;
35+
font-size: 12px;
36+
color: #fff;
37+
background-color: #d92e2e;
38+
border: none;
39+
cursor: pointer;
40+
border-radius: 3px;
41+
}
42+
43+
#ufs-who-is-typing .ufs-avatar {
44+
width: 60px;
45+
height: 60px;
46+
border-radius: 5px;
47+
float: left;
48+
margin-right: 10px;
49+
border-radius: 50%;
50+
box-shadow: inset 0 0 0 1px #181a1b0d;
51+
}
52+
53+
#ufs-who-is-typing .ufs-content p {
54+
padding: 0;
55+
margin: 0;
56+
}
57+
58+
.clearfix::after {
59+
content: "";
60+
clear: both;
61+
display: table;
62+
}

scripts/fb_whoIsTyping.js

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,67 +11,87 @@ export default {
1111
whiteList: ["https://*.facebook.com/*", "https://*.messenger.com/*"],
1212

1313
onDocumentStart: () => {
14-
function notifyTypingEvent() {
15-
// TODO add notification UI
16-
}
17-
function saveTyingEvent(uid, typing) {
18-
let key = "ufs-fb_whoIsTyping";
19-
let old = JSON.parse(localStorage.getItem(key) ?? "[]");
20-
old.push({
21-
time: new Date().getTime(),
22-
uid: uid,
23-
typing: typing,
24-
});
25-
localStorage.setItem(key, JSON.stringify(old));
26-
}
14+
window.ufs_whoIsTyping_Cached = {};
2715

2816
const WebSocketOrig = window.WebSocket;
2917
window.WebSocket = function fakeConstructor(dt, config) {
3018
const websocket_instant = new WebSocketOrig(dt, config);
3119
websocket_instant.addEventListener("message", async function (achunk) {
3220
let utf8_str = new TextDecoder("utf-8").decode(achunk.data);
3321

34-
if (
35-
utf8_str.includes("updateTypingIndicator") ||
36-
utf8_str.includes("mid.$")
37-
) {
38-
let isStartTyping = utf8_str.includes(",true)");
39-
let isStopTyping = utf8_str.includes(",false)");
22+
if (utf8_str.includes("updateTypingIndicator")) {
23+
console.log("abc");
24+
try {
25+
let isStartTyping = utf8_str.includes(",true)");
26+
let isStopTyping = utf8_str.includes(",false)");
4027

41-
let arr = utf8_str.match(/(\[)(.*?)(\])/g);
42-
let uid = UsefulScriptGlobalPageContext.Facebook.decodeArrId(
43-
JSON.parse(arr[arr.length - 2])
44-
);
28+
let arr = utf8_str.match(/(\[)(.*?)(\])/g);
29+
let uid = UsefulScriptGlobalPageContext.Facebook.decodeArrId(
30+
JSON.parse(arr[arr.length - 2])
31+
);
4532

46-
console.log(uid, isStartTyping, utf8_str);
47-
saveTyingEvent(uid, isStartTyping);
33+
if (!(uid in window.ufs_whoIsTyping_Cached)) {
34+
let userData =
35+
await UsefulScriptGlobalPageContext.Facebook.getUserProfileDataFromUid(
36+
uid
37+
);
38+
window.ufs_whoIsTyping_Cached[uid] = userData;
39+
40+
console.log(userData);
41+
}
42+
43+
let { name, profiePicLarge } = window.ufs_whoIsTyping_Cached[uid];
44+
notifyTypingEvent(uid, name, profiePicLarge, isStartTyping);
45+
} catch (e) {
46+
console.log("ERROR: ", e);
47+
}
4848
}
4949
});
5050
return websocket_instant;
5151
};
5252
window.WebSocket.prototype = WebSocketOrig.prototype;
5353
window.WebSocket.prototype.constructor = window.WebSocket;
5454

55-
requireLazy(
56-
[
57-
"LSUpdateTypingIndicator",
58-
"LSTypingUpdateTypingIndicatorStoredProcedure_Optimized",
59-
],
60-
(L1, L2) => {
61-
const L1Orig = L1.prototype.constructor;
62-
L1.prototype.constructor = function () {
63-
console.log(arguments);
64-
return L1Orig.apply(this, arguments);
55+
function notifyTypingEvent(uid, name, avatar, isTyping) {
56+
let divId = "ufs-who-is-typing";
57+
let exist = document.querySelector("#" + divId);
58+
if (!exist) {
59+
exist = document.createElement("div");
60+
exist.id = divId;
61+
exist.innerHTML = `<div class="ufs-header clearfix">
62+
<button>+</button>
63+
</div>`;
64+
exist.querySelector(".ufs-header button").onclick = (e) => {
65+
exist.classList.toggle("collapsed");
6566
};
6667

67-
const L2Orig = L2.prototype.constructor;
68-
L2.prototype.constructor = function () {
69-
console.log("L2", arguments);
70-
return L2Orig.apply(this, arguments);
71-
};
68+
document.body.appendChild(exist);
69+
70+
UsefulScriptGlobalPageContext.Extension.getURL(
71+
"scripts/fb_whoIsTyping.css"
72+
).then(UsefulScriptGlobalPageContext.DOM.injectCssFile);
7273
}
73-
);
74-
},
7574

76-
onDocumentIdle: () => {},
75+
let time = new Date().toLocaleTimeString();
76+
let text =
77+
`<b><a target="_blank" href="https://fb.com/${uid}">${name}</a></b>` +
78+
` ${isTyping ? "đang" : "ngưng"} nhắn cho bạn.`;
79+
80+
let newNoti = document.createElement("div");
81+
newNoti.className = "ufs-noti-item clearfix";
82+
newNoti.innerHTML = `
83+
<button class="ufs-close-btn">X</button>
84+
<img src="${avatar}" class="ufs-avatar" />
85+
<div class="ufs-content">
86+
<p class="ufs-time">${time}</p>
87+
<p class="ufs-text">${text}</p>
88+
</div>
89+
`;
90+
newNoti.querySelector(".ufs-close-btn").onclick = () => {
91+
newNoti.remove();
92+
if (!exist.querySelector("ufs-noti-item")) exist.remove();
93+
};
94+
exist.appendChild(newNoti);
95+
}
96+
},
7797
};

0 commit comments

Comments
 (0)