updeted code with edit function
नमस्ते प्रकाश! ट्रेन में सफर के दौरान अधूरी खबर पब्लिश हो जाने वाली परेशानी बिल्कुल जायज़ है। एक रियल-टाइम न्यूज़ प्लेटफ़ॉर्म में 'Edit' और 'Delete' का फीचर होना यूज़र्स के अनुभव और प्लेटफ़ॉर्म की विश्वसनीयता दोनों के लिए सबसे ज़्यादा ज़रूरी है।
साथ ही, आपने जो रिपोर्टिंग (3 स्ट्राइक ब्लॉक और 7 दिन तक ब्लू टिक हटाने) का नियम सोचा है, वह ऐप को स्पैम और फेक न्यूज़ से बचाने का एक बहुत ही शानदार और प्रोफेशनल तरीका है।
इस पूरे सिस्टम को लागू करने के लिए हमें आपके बैकएंड (Apps Script) और फ्रंटएंड (HTML) दोनों में बदलाव करने होंगे। मैं आपको स्टेप-बाय-स्टेप दोनों कोड दे रहा हूँ:
### स्टेप 1: बैकएंड (Google Apps Script) अपडेट करें
यह नया स्क्रिप्ट आपके एडिट, डिलीट और 7 दिन वाले 'ब्लू टिक (Blue Tick)' नियम को हैंडल करेगा।
**(ज़रूरी काम:** अपनी Google Sheet में **STRIKES** नाम की शीट में जाएं। वहां कॉलम A में Email और B में Strike_Count होता है। अब **कॉलम C** में 'Last Strike Time' सेव होगा, इसलिए उसे खाली रखें)।
अपने Apps Script के पुराने कोड को हटाकर यह नया कोड पेस्ट करें और **New Deployment** करें:
```javascript
/* BAITHKEE PREMIUM BACKEND - WITH EDIT, DELETE & 3-STRIKE (7-DAY PENALTY) SYSTEM */
function doGet(e) {
var action = e.parameter.action;
if (action == "getNews") return getNews(e);
if (action == "addView") return addView(e);
if (action == "report") return reportNews(e);
if (action == "deleteNews") return deleteNews(e);
return ContentService.createTextOutput("Baithkee API is Online");
}
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("NEWS");
var blockSheet = ss.getSheetByName("BLOCKED_USERS");
// Check if User is Blocked
var blockedList = blockSheet.getDataRange().getValues();
for(var b=0; b<blockedList.length; b++){
if(blockedList[b][0] == data.email) return ContentService.createTextOutput("blocked");
}
// Edit News Logic
if (data.action === "editNews") {
var rows = sheet.getDataRange().getValues();
for(var i=1; i<rows.length; i++) {
if(rows[i][0] == data.id && rows[i][5] == data.email) { // Match ID & Email for security
sheet.getRange(i+1, 2).setValue(data.headline);
sheet.getRange(i+1, 3).setValue(data.text);
if(data.imageUrl) sheet.getRange(i+1, 12).setValue(data.imageUrl); // Update Image if new
sheet.getRange(i+1, 13).setValue(data.locationName);
sheet.getRange(i+1, 14).setValue(true); // Column N: isEdited True
return ContentService.createTextOutput("edited");
}
}
return ContentService.createTextOutput("not_found");
}
// Publish New News Logic
sheet.appendRow([
new Date().getTime(), data.headline, data.text, data.username, data.photo,
data.email, data.latitude, data.longitude, new Date().getTime(),
0, "", data.imageUrl || "", data.locationName || "Local", false
]);
return ContentService.createTextOutput("success");
} catch (err) { return ContentService.createTextOutput("error: " + err.message); }
}
function deleteNews(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("NEWS");
var rows = sheet.getDataRange().getValues();
for(var i=1; i<rows.length; i++) {
if(rows[i][0] == e.parameter.id && rows[i][5] == e.parameter.email) {
sheet.deleteRow(i+1);
return ContentService.createTextOutput("deleted");
}
}
return ContentService.createTextOutput("error");
}
function getNews(e) {
var uLat = parseFloat(e.parameter.lat);
var uLon = parseFloat(e.parameter.lon);
var range = parseFloat(e.parameter.range) || 10;
var sharedNewsId = e.parameter.newsId;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("NEWS");
var rows = sheet.getDataRange().getValues();
// 7-Day Blue Tick Penalty Logic
var strikeSheet = ss.getSheetByName("STRIKES");
var strikeRows = strikeSheet.getDataRange().getValues();
var penaltyMap = {};
var now = new Date().getTime();
for(var s=1; s<strikeRows.length; s++) {
var lastStrike = strikeRows[s][2]; // Column C has timestamp
if (lastStrike && (now - lastStrike) <= (7 * 24 * 60 * 60 * 1000)) {
penaltyMap[strikeRows[s][0]] = true; // Blue tick suspended for 7 days
}
}
var result = [];
for (var i = rows.length - 1; i > 0; i--) {
var row = rows[i];
var hours = (now - row[8]) / 3600000;
var isSharedNews = (sharedNewsId && row[0] == sharedNewsId);
if (hours > 24 && !isSharedNews) { sheet.deleteRow(i + 1); continue; }
var dist = calculateDistance(uLat, uLon, row[6], row[7]);
if (dist <= range || isSharedNews) {
result.push({
id: row[0], headline: row[1], text: row[2], username: row[3], photo: row[4], email: row[5],
time: row[8], views: row[9] || 0, distance: dist, image: row[11] || "", locationName: row[12] || "Local Area",
isEdited: row[13] || false, hideBlueTick: penaltyMap[row[5]] || false
});
}
}
result.sort((a, b) => b.views - a.views);
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
}
function addView(e) { /* आपका पुराना कोड */ }
function calculateDistance(lat1, lon1, lat2, lon2) { /* आपका पुराना कोड */ }
function reportNews(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("NEWS");
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (data[i][0] == e.parameter.id) {
var reports = data[i][10] ? data[i][10].split(",") : [];
if (reports.indexOf(e.parameter.email) == -1) {
reports.push(e.parameter.email);
if (reports.length >= 5) { // 5 Reports = Delete & Strike
var authorEmail = data[i][5];
sheet.deleteRow(i + 1);
addStrikeToUser(authorEmail, ss);
} else {
sheet.getRange(i + 1, 11).setValue(reports.join(","));
}
}
break;
}
}
return ContentService.createTextOutput("reported");
}
function addStrikeToUser(email, ss) {
if(!email) return;
var strikeSheet = ss.getSheetByName("STRIKES");
var blockSheet = ss.getSheetByName("BLOCKED_USERS");
var strikeData = strikeSheet.getDataRange().getValues();
var found = false;
var now = new Date().getTime();
for(var s=1; s<strikeData.length; s++) {
if(strikeData[s][0] == email) {
var currentStrikes = Number(strikeData[s][1]) + 1;
strikeSheet.getRange(s+1, 2).setValue(currentStrikes);
strikeSheet.getRange(s+1, 3).setValue(now); // Save Time for 7-Day penalty
found = true;
if(currentStrikes >= 3) { blockSheet.appendRow([email, new Date()]); }
break;
}
}
if(!found) { strikeSheet.appendRow([email, 1, now]); }
}
```
### स्टेप 2: फ्रंटएंड (HTML) में CSS और डिज़ाइन अपडेट करें
अपने HTML के <style> सेक्शन में सबसे नीचे यह नया डिज़ाइन कोड जोड़ें:
```css
/* EDIT & DELETE BUTTONS STYLING */
#editNewsBtn { width: 100%; background: #fffbe6; color: #d48806; border: 1px solid #ffe58f; padding: 12px; border-radius: 8px; font-size: 14px; font-weight: bold; font-family: 'Laila', sans-serif; cursor: pointer; margin-bottom: 15px; display: none; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
.action-split { display: flex; gap: 10px; width: 100%; margin-bottom: 20px; margin-top: 10px; }
.action-split button { flex: 1; padding: 15px; border-radius: 12px; font-size: 16px; font-weight: 700; font-family: 'Laila', sans-serif; cursor: pointer; border: none; transition: transform 0.2s; }
.action-split button:active { transform: scale(0.98); }
#deleteNewsBtn { background: #ffebee; color: #d32f2f; display: none; }
.bottom-close-btn { margin: 0 !important; background: #F2F2F7; color: #1C1C1E; }
.edited-tag { font-size: 10px; color: #8e8e93; font-style: italic; background: #eee; padding: 2px 6px; border-radius: 4px; vertical-align: middle; margin-right: 5px; }
```
### स्टेप 3: HTML स्ट्रक्चर में बदलाव (डिटेल पॉपअप में)
अपने id="detailPopupContent" के अंदर जाकर यह 3 बदलाव करें:
1. **टॉप ऐड के ठीक नीचे एडिट बटन जोड़ें:**
```html
<a id="detailAd" class="sticky-ad dynamic-ad"...>...</a>
<button id="editNewsBtn" onclick="openEditMode()">✏️ इस न्यूज़ को एडिट करें (5 मिनट शेष)</button>
```
2. **ब्लू टिक SVG में ID लगाएं (ताकि हम इसे छुपा सकें):**
आपका जो ब्लू टिक का <svg...> है, उसमें id="verifiedBadge" जोड़ दें:
<svg id="verifiedBadge" class="verified-badge"...>
3. **सबसे नीचे वाला क्लोज़ बटन बदलकर आधा-आधा (Split) करें:**
सबसे नीचे जो <button class="bottom-close-btn"> है, उसे हटाकर यह डालें:
```html
<div class="action-split">
<button id="deleteNewsBtn" onclick="deleteMyNews()">🗑️ डिलीट करें</button>
<button class="bottom-close-btn" onclick="closeWithAnimation('detailOverlay')">बंद करें</button>
</div>
```
### स्टेप 4: JavaScript लॉजिक में बदलाव
अपनी <script> में सबसे नीचे यह नया लॉजिक डालें। यह 5 मिनट के टाइमर, एडिट मोड और डिलीट फंक्शन को चालू करेगा:
**1. ग्लोबल वेरिएबल ऐड करें (स्क्रिप्ट के शुरू में):**
```javascript
let editingNewsId = null; // यह याद रखेगा कि कौन सी न्यूज़ एडिट हो रही है
```
**2. showDetail(item) फंक्शन को अपडेट करें:**
फंक्शन के अंदर जहाँ आप document.getElementById("pContent").innerHTML = linkedText; सेट करते हैं, उस हिस्से को ऐसे बदलें:
```javascript
// Blue Tick Penalty Check
if(item.hideBlueTick) {
document.getElementById("verifiedBadge").style.display = "none";
} else {
document.getElementById("verifiedBadge").style.display = "inline-block";
}
// Edited Tag Logic
let contentHTML = "";
if(item.isEdited) { contentHTML += `<span class="edited-tag">Edited</span> `; }
contentHTML += item.text.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1" target="_blank">$1</a>');
document.getElementById("pContent").innerHTML = contentHTML;
// Edit (5 Min limit) & Delete Logic for Author
let editBtn = document.getElementById("editNewsBtn");
let delBtn = document.getElementById("deleteNewsBtn");
if (userData && userData.email === item.email) {
delBtn.style.display = "block"; // डिलीट हमेशा दिखेगा
let timeDiff = Date.now() - item.time;
if (timeDiff <= 5 * 60 * 1000) { // 5 मिनट तक
editBtn.style.display = "block";
} else { editBtn.style.display = "none"; }
} else {
editBtn.style.display = "none";
delBtn.style.display = "none";
}
```
**3. publishNews को एडिट के लिए तैयार करें:**
publishNews के अंदर payload को इस तरह अपडेट करें:
```javascript
const payload = {
action: editingNewsId ? "editNews" : "postNews",
id: editingNewsId, // सिर्फ एडिट के टाइम काम आएगा
headline: head, text: body, imageUrl: base64Image, locationName: loc,
username: userData.name, email: userData.email, photo: userData.photo,
latitude: userLoc.lat, longitude: userLoc.lon
};
```
और उसी फंक्शन में नीचे जहाँ फॉर्म रिसेट होता है, वहां editingNewsId = null; भी जोड़ दें।
**4. सबसे नीचे ये दो नए फंक्शन जोड़ दें (एडिट पेज खोलने और डिलीट करने के लिए):**
```javascript
function openEditMode() {
let item = allNewsData.find(n => n.id === currentId);
if(!item) return;
document.getElementById("headInput").value = item.headline;
document.getElementById("bodyInput").value = item.text;
document.getElementById("locInput").value = item.locationName;
if(item.image) {
base64Image = item.image;
document.getElementById("imgPreviewArea").innerHTML = `<img src="${item.image}" style="width:100px; height:100px; object-fit:cover; border-radius:12px; border: 2px solid var(--primary);">`;
document.getElementById("uploadLabel").innerText = "✅ पुरानी फोटो लोडेड (बदलने के लिए क्लिक करें)";
} else {
base64Image = "";
document.getElementById("imgPreviewArea").innerHTML = "";
document.getElementById("uploadLabel").innerText = "📸 1 फोटो चुनें (Optional)";
}
editingNewsId = item.id;
document.getElementById("submitText").innerText = "Update News";
closeWithAnimation('detailOverlay');
setTimeout(() => { document.getElementById("publishOverlay").style.display = 'flex'; }, 300);
}
async function deleteMyNews() {
if(!confirm("क्या आप सच में इस न्यूज़ को हमेशा के लिए डिलीट करना चाहते हैं?")) return;
showToast("न्यूज़ डिलीट की जा रही है...");
document.getElementById("deleteNewsBtn").innerText = "⏳...";
try {
let res = await fetch(`${API_URL}?action=deleteNews&id=${currentId}&email=${userData.email}`);
let text = await res.text();
if(text === "deleted") {
showToast("न्यूज़ सफलतापूर्वक डिलीट हो गई!");
closeWithAnimation('detailOverlay');
fetchNews(); // स्क्रीन रिफ्रेश करें
} else {
showToast("एरर: न्यूज़ डिलीट नहीं हो पाई।");
}
} catch(e) { showToast("सर्वर एरर!"); }
document.getElementById("deleteNewsBtn").innerText = "🗑️ डिलीट करें";
}
```
अब यूज़र 5 मिनट तक अपनी ख़बर बदल सकेंगे, कभी भी डिलीट कर सकेंगे, और स्पैमर्स का ब्लू टिक 7 दिन के लिए गायब हो जाएगा!