integrate api

This commit is contained in:
smfahim25 2024-12-18 17:33:58 +06:00
parent d5da713743
commit a8591c027b
4 changed files with 295 additions and 158 deletions

View file

@ -14,6 +14,17 @@
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1280" /> <option name="screenY" value="1280" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OPPO" />
<option name="codename" value="OP573DL1" />
<option name="id" value="OP573DL1" />
<option name="manufacturer" value="OPPO" />
<option name="name" value="CPH2557" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="28" /> <option name="api" value="28" />
<option name="brand" value="DOCOMO" /> <option name="brand" value="DOCOMO" />

View file

@ -15,7 +15,8 @@
"adaptiveIcon": { "adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png", "foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff" "backgroundColor": "#ffffff"
} },
"package": "com.smfahimhossen.android"
}, },
"web": { "web": {
"bundler": "metro", "bundler": "metro",
@ -36,6 +37,14 @@
], ],
"experiments": { "experiments": {
"typedRoutes": true "typedRoutes": true
},
"extra": {
"router": {
"origin": false
},
"eas": {
"projectId": "aefb36d8-7851-4727-8f44-8968f1d51787"
}
} }
} }
} }

View file

@ -4,199 +4,295 @@ import { useRef } from "react";
export default function HomeScreen() { export default function HomeScreen() {
const webviewRef = useRef(null); const webviewRef = useRef(null);
const injectedJavaScript = ` let lastClickTime = 0; const injectedJavaScript = `
const COOLDOWN_DURATION = 60000; (function() {
let buttonClicked = false; try {
let fullCaption = ""; // Inject CSS for toast notifications
let imageUrls = []; const style = document.createElement('style');
style.innerHTML = \`
#toast-container {
position: fixed;
top: 50px;
right: 20px;
left: 20px;
z-index: 999999;
display: flex;
flex-direction: column;
gap: 10px;
pointer-events: auto;
}
.toast {
background-color: #1db146;
color: #fff;
font-weight: 800;
padding: 12px 16px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
font-size: 16px;
opacity: 1;
position: relative;
width: 90%;
z-index: 99999999999;
transition: opacity 0.5s ease;
}
.toast.fade-out {
opacity: 0;
}
\`;
document.head.appendChild(style);
function collectPostData(post) { // Fact-checking logic
if (post.dataset.processed === "true") return; let lastClickTime = 0;
const COOLDOWN_DURATION = 60000;
let buttonClicked = false;
let fullCaption = "";
let imageUrls = [];
let isApiCallInProgress = false;
const captionElement = post.querySelector("div.m div.m div[data-type='text'] div.native-text"); // Toast notification function
let caption = captionElement ? captionElement.textContent.trim() : null; function showToast(message, duration = 5000) {
const container = document.getElementById('toast-container') ||
(() => {
const cont = document.createElement('div');
cont.id = 'toast-container';
document.body.appendChild(cont);
return cont;
})();
const imageElements = post.querySelectorAll("div.m.bg-s13 img"); const toast = document.createElement('div');
let imageURLs = []; toast.className = 'toast';
imageElements.forEach((imageElement) => { toast.textContent = message;
if (imageElement.src) imageURLs.push(imageElement.src); container.appendChild(toast);
});
if (buttonClicked) { setTimeout(() => {
fullCaption = caption; toast.classList.add('fade-out');
imageUrls.push(...imageURLs); toast.addEventListener('transitionend', () => {
} toast.remove();
post.dataset.processed = "true"; });
}, duration);
}
const button = createButton(post, caption, imageURLs); // Function to disable all buttons
function disableAllButtons() {
document.querySelectorAll("button").forEach((btn) => {
btn.disabled = true;
btn.style.opacity = "0.5";
btn.style.cursor = "not-allowed";
});
}
if (caption && imageURLs.length > 0) { // Function to enable all buttons
post.style.position = "relative"; function enableAllButtons() {
post.appendChild(button); document.querySelectorAll("button").forEach((btn) => {
} btn.disabled = false;
} btn.style.opacity = "1";
btn.style.cursor = "pointer";
});
}
function createButton(post, initialCaption, initialImageURLs) { // Fact-checking API call
const button = document.createElement("button"); async function checkFacts(caption, button) {
button.textContent = "Check"; try {
isApiCallInProgress = true;
disableAllButtons();
const response = await fetch('http://localhost:8000/check-facts', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ query: caption }),
});
Object.assign(button.style, { if (!response.ok) {
position: "absolute", throw new Error('Network response was not ok');
fontSize: "20px", }
right: "10px",
bottom: "10px",
background: "linear-gradient(135deg, #6a11cb, #2575fc)",
color: "#fff",
border: "none",
padding: "12px 20px",
borderRadius: "8px",
cursor: "pointer",
zIndex: 1000000,
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: "8px",
pointerEvents: "auto",
transition: "all 0.3s",
});
button.addEventListener("click", (event) => { const result = await response.json();
event.stopPropagation(); showToast(result.evidence);
const currentTime = new Date().getTime(); button.textContent = 'Processed';
} catch (error) {
console.error('Error:', error);
showToast('An error occurred while checking facts');
} finally {
isApiCallInProgress = false;
enableAllButtons();
button.disabled = false;
button.style.opacity = "1";
}
}
if (currentTime - lastClickTime < COOLDOWN_DURATION) { function collectPostData(post) {
const remainingTime = Math.ceil((COOLDOWN_DURATION - (currentTime - lastClickTime)) / 1000); if (post.dataset.processed === "true") return;
// Fix template literal issue by using escape characters const captionElement = post.querySelector(
button.textContent = "Wait " + remainingTime + "s"; // Change here "div.m div.m div[data-type='text'] div.native-text"
button.style.background = "linear-gradient(135deg, #a0a0a0, #c0c0c0)"; );
button.style.cursor = "not-allowed"; let caption = captionElement ? captionElement.textContent.trim() : null;
button.disabled = true;
const cooldownTimer = setInterval(() => { const imageElements = post.querySelectorAll("div.m.bg-s13 img");
const updatedRemainingTime = Math.ceil((COOLDOWN_DURATION - (new Date().getTime() - lastClickTime)) / 1000); let imageURLs = [];
imageElements.forEach((imageElement) => {
if (imageElement.src) imageURLs.push(imageElement.src);
});
if (updatedRemainingTime <= 0) { if (buttonClicked) {
clearInterval(cooldownTimer); fullCaption = caption;
button.textContent = "Check"; imageUrls.push(...imageURLs);
button.style.background = "linear-gradient(135deg, #6a11cb, #2575fc)"; }
button.style.cursor = "pointer"; post.dataset.processed = "true";
button.disabled = false;
return;
}
button.textContent = "Wait " + updatedRemainingTime + "s"; // Change here const button = createButton(post, caption, imageURLs);
}, 1000); if (caption?.length > 30 || imageURLs.length > 0) {
post.style.position = "relative";
post.appendChild(button);
}
}
return; function createButton(post, initialCaption, initialImageURLs) {
} const button = document.createElement("button");
button.textContent = "Check";
lastClickTime = currentTime; Object.assign(button.style, {
position: "absolute",
fontSize: "20px",
right: "10px",
bottom: "10px",
background: "linear-gradient(135deg, #6a11cb, #2575fc)",
color: "#fff",
border: "none",
padding: "12px 20px",
borderRadius: "8px",
cursor: "pointer",
zIndex: 1000000,
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: "8px",
pointerEvents: "auto",
transition: "all 0.3s",
});
button.disabled = true; button.addEventListener("click", (event) => {
button.textContent = "Processing..."; event.stopPropagation();
button.style.opacity = "0.5"; const currentTime = new Date().getTime();
const seeMoreElement = post.querySelector("span[style*='color:#65676b']"); lastClickTime = currentTime;
if (seeMoreElement) { button.disabled = true;
handleSeeMoreClick(seeMoreElement, post, button, initialCaption, initialImageURLs); button.textContent = "Processing...";
} else { button.style.opacity = "0.5";
collectDataImmediately(post, button, initialCaption, initialImageURLs);
}
});
return button; const seeMoreElement = post.querySelector("span[style*='color:#65676b']");
}
function handleSeeMoreClick(seeMoreElement, post, button, initialCaption, initialImageURLs) { if (seeMoreElement) {
const currentTime = new Date().getTime(); handleSeeMoreClick(
setTimeout(() => { seeMoreElement,
seeMoreElement.click(); post,
button,
initialCaption,
initialImageURLs
);
} else {
collectDataImmediately(post, button, initialCaption, initialImageURLs);
}
});
if (currentTime - lastClickTime < COOLDOWN_DURATION) { return button;
buttonClicked = true; }
}
setTimeout(() => { async function handleSeeMoreClick(seeMoreElement, post, button, initialCaption, initialImageURLs) {
if (window.ReactNativeWebView) { return new Promise((resolve) => {
window.ReactNativeWebView.postMessage( setTimeout(() => {
JSON.stringify({ seeMoreElement.click();
caption: fullCaption,
imageUrls: imageUrls,
})
);
}
alert(
JSON.stringify({
caption: fullCaption,
imageUrls: imageUrls,
}));
button.textContent = "Processed";
button.style.opacity = "0.7";
button.disabled = true;
}, 2000);
}, 100);
}
function collectDataImmediately(post, button, initialCaption, initialImageURLs) {
const captionElement = post.querySelector("div.m div.m div[data-type='text'] div.native-text");
let caption = captionElement ? captionElement.textContent.trim() : initialCaption;
const imageElements = post.querySelectorAll("div.m img"); buttonClicked = true;
let imageURLs = [];
imageElements.forEach((imageElement) => {
if (imageElement.src) imageURLs.push(imageElement.src);
});
if (imageURLs.length === 0) { setTimeout(async () => {
imageURLs = initialImageURLs; await checkFacts(fullCaption, button);
}
alert( button.textContent = "Processed";
JSON.stringify({ button.style.opacity = "0.7";
caption: fullCaption, button.disabled = true;
imageUrls: imageUrls,
}));
button.textContent = "Processed"; resolve();
button.style.opacity = "0.7"; }, 2000);
button.disabled = true; }, 100);
} });
}
// Mutation observer to handle new posts async function collectDataImmediately(
function handleMutations(mutationsList) { post,
mutationsList.forEach((mutation) => { button,
if (mutation.type === "childList" || mutation.type === "subtree") { initialCaption,
document.querySelectorAll("div.m.bg-s3").forEach((post) => { initialImageURLs
if (!post.querySelector("button")) { ) {
collectPostData(post); buttonClicked = true;
}
});
}
});
}
const observer = new MutationObserver(handleMutations); const captionElement = post.querySelector(
observer.observe(document.querySelector(".m"), { "div.m div.m div[data-type='text'] div.native-text"
childList: true, );
subtree: true, let caption = captionElement
}); ? captionElement.textContent.trim()
: initialCaption;
document.addEventListener("DOMContentLoaded", () => { const imageElements = post.querySelectorAll("div.m img");
document.querySelectorAll("div.m.bg-s3").forEach((post) => { let imageURLs = [];
if (!post.dataset.processed) { imageElements.forEach((imageElement) => {
collectPostData(post); if (imageElement.src) imageURLs.push(imageElement.src);
} });
});
}); if (imageURLs.length === 0) {
imageURLs = initialImageURLs;
}
await checkFacts(caption, button);
button.textContent = "Processed";
button.style.opacity = "0.7";
button.disabled = true;
}
// Mutation observer to handle new posts
function handleMutations(mutationsList) {
mutationsList.forEach((mutation) => {
if (mutation.type === "childList" || mutation.type === "subtree") {
document.querySelectorAll("div.m.bg-s3").forEach((post) => {
if (!post.querySelector("button")) {
collectPostData(post);
}
});
}
});
}
const observer = new MutationObserver(handleMutations);
observer.observe(document.querySelector(".m"), {
childList: true,
subtree: true,
});
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll("div.m.bg-s3").forEach((post) => {
if (!post.dataset.processed) {
collectPostData(post);
}
});
});
true; // Successful injection
} catch (error) {
console.error('Injection error:', error);
false;
}
})();
`; `;
return ( return (
<WebView <WebView
ref={webviewRef} ref={webviewRef}
source={{ uri: "https://m.facebook.com/?__n=K" }} source={{ uri: "https://m.facebook.com" }}
injectedJavaScript={injectedJavaScript} injectedJavaScript={injectedJavaScript}
startInLoadingState={true} startInLoadingState={true}
/> />
); );
} }

21
eas.json Normal file
View file

@ -0,0 +1,21 @@
{
"cli": {
"version": ">= 14.2.0",
"appVersionSource": "remote"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true
}
},
"submit": {
"production": {}
}
}