Commit 48578dba authored by Stefy Spora's avatar Stefy Spora

Improve story-data parsing to extract from attributes

- Update getCurrentMediaData to parse script tag with id 'story-data'
- Extract data from attributes.pictures for pictures:
  * title, caption, description, tags_names as tags, user_tags_ids as userTags
- Extract data from attributes.videos for videos:
  * title, description, tags_names as tags, user_tags_ids as userTags (no caption)
- Add fallback to direct attributes and root level data
- Update both content.js and background.js injected functions
- Preserve existing tags and user tags when updating privacy
- Use parsed data in XHR payloads instead of empty defaults
parent ec4a0433
......@@ -346,26 +346,103 @@ function executePrivacyUpdateFromContext(privacyLevel = 'friends_only') {
throw new Error('Could not find CSRF token. Please refresh the page and try again.');
}
// Step 3: Prepare payload based on media type and privacy level
// Step 3: Parse story-data script tag to get current media data
let currentData = {
title: '',
caption: '',
description: '',
tag_names: [],
user_tag_ids: []
};
try {
const storyDataScript = document.getElementById('story-data') || document.querySelector('script[id="story-data"]');
if (storyDataScript) {
const scriptContent = storyDataScript.textContent || storyDataScript.innerHTML;
if (scriptContent) {
let storyData;
const jsonMatch = scriptContent.match(/(\{[\s\S]*\})/);
if (jsonMatch) {
storyData = JSON.parse(jsonMatch[1]);
} else {
storyData = JSON.parse(scriptContent);
}
// Extract data from attributes based on media type
if (storyData.attributes) {
const attributes = storyData.attributes;
// Try to extract from pictures first
if (attributes.pictures && attributes.pictures.length > 0) {
const picture = attributes.pictures[0];
currentData = {
title: picture.title || '',
caption: picture.caption || '',
description: picture.description || picture.caption || '',
tag_names: picture.tags_names || picture.tags || [],
user_tag_ids: picture.user_tags_ids || picture.userTags || []
};
}
// Try to extract from videos
else if (attributes.videos && attributes.videos.length > 0) {
const video = attributes.videos[0];
currentData = {
title: video.title || '',
caption: '', // Videos don't have caption
description: video.description || '',
tag_names: video.tags_names || video.tags || [],
user_tag_ids: video.user_tags_ids || video.userTags || []
};
}
// Fallback to direct attributes
else {
currentData = {
title: attributes.title || attributes.name || '',
caption: attributes.caption || '',
description: attributes.description || attributes.caption || '',
tag_names: attributes.tags_names || attributes.tags || [],
user_tag_ids: attributes.user_tags_ids || attributes.userTags || []
};
}
}
// Fallback to root level data
else {
currentData = {
title: storyData.title || storyData.name || '',
caption: storyData.caption || '',
description: storyData.description || storyData.caption || '',
tag_names: storyData.tags_names || storyData.tags || [],
user_tag_ids: storyData.user_tags_ids || storyData.userTags || []
};
}
}
}
} catch (error) {
console.warn('Could not parse story data, using defaults:', error);
}
// Step 4: Prepare payload based on media type and privacy level
let payload;
if (mediaInfo.type === 'video') {
payload = {
video: {
title: "",
description: "",
title: currentData.title,
description: currentData.description,
only_friends: privacyLevel === 'friends_only' ? true : false,
tag_names: [],
user_tag_ids: []
tag_names: currentData.tag_names,
user_tag_ids: currentData.user_tag_ids
},
render_flash: true
};
} else {
payload = {
picture: {
caption: "",
caption: currentData.caption,
content_privacy: privacyLevel === 'friends_only' ? "only_friends" : "public",
tag_names: [],
user_tag_ids: []
tag_names: currentData.tag_names,
user_tag_ids: currentData.user_tag_ids
},
render_flash: true
};
......@@ -450,6 +527,7 @@ function executeBulkPrivacyUpdateFromContext() {
async function updateMediaPrivacyById(mediaType, mediaId, csrfToken, privacyLevel = 'friends_only') {
try {
// For bulk processing, we use default values since we don't have access to individual page data
let payload;
if (mediaType === 'video') {
payload = {
......
......@@ -57,34 +57,126 @@
return null;
}
// Function to get current media data for preserving existing values
async function getCurrentMediaData(type, id) {
// Function to get current media data by parsing the story-data script tag
function getCurrentMediaData() {
try {
const response = await fetch(`https://fetlife.com/${type}s/${id}`, {
method: 'GET',
credentials: 'same-origin',
headers: {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest'
// Find the script tag with id "story-data"
const storyDataScript = document.getElementById('story-data') || document.querySelector('script[id="story-data"]');
if (!storyDataScript) {
console.warn('Story data script not found, using defaults');
return {
title: '',
caption: '',
description: '',
tag_names: [],
user_tag_ids: []
};
}
// Extract the JSON content from the script tag
const scriptContent = storyDataScript.textContent || storyDataScript.innerHTML;
if (!scriptContent) {
console.warn('Story data script is empty, using defaults');
return {
title: '',
caption: '',
description: '',
tag_names: [],
user_tag_ids: []
};
}
// Parse the JSON data
let storyData;
try {
// The script content might be wrapped in a JavaScript assignment
// Try to extract just the JSON part
const jsonMatch = scriptContent.match(/(\{[\s\S]*\})/);
if (jsonMatch) {
storyData = JSON.parse(jsonMatch[1]);
} else {
storyData = JSON.parse(scriptContent);
}
});
if (!response.ok) {
throw new Error(`Failed to fetch ${type} data: ${response.status}`);
} catch (parseError) {
console.warn('Failed to parse story data JSON:', parseError);
return {
title: '',
caption: '',
description: '',
tag_names: [],
user_tag_ids: []
};
}
// For now, we'll use empty defaults since we're only updating privacy
// In a real implementation, you might want to parse the HTML response
// to extract current title/caption and tags
return {
console.log('Parsed story data:', storyData);
// Extract data from attributes based on media type
let mediaData = {
title: '',
caption: '',
description: '',
tag_names: [],
user_tag_ids: []
};
// Check if we have attributes and can extract media data
if (storyData.attributes) {
const attributes = storyData.attributes;
// Try to extract from pictures first
if (attributes.pictures && attributes.pictures.length > 0) {
const picture = attributes.pictures[0]; // Get first picture
mediaData = {
title: picture.title || '',
caption: picture.caption || '',
description: picture.description || picture.caption || '',
tag_names: picture.tags_names || picture.tags || [],
user_tag_ids: picture.user_tags_ids || picture.userTags || []
};
console.log('Extracted picture data from attributes:', mediaData);
}
// Try to extract from videos
else if (attributes.videos && attributes.videos.length > 0) {
const video = attributes.videos[0]; // Get first video
mediaData = {
title: video.title || '',
caption: '', // Videos don't have caption
description: video.description || '',
tag_names: video.tags_names || video.tags || [],
user_tag_ids: video.user_tags_ids || video.userTags || []
};
console.log('Extracted video data from attributes:', mediaData);
}
// Fallback to direct attributes
else {
mediaData = {
title: attributes.title || attributes.name || '',
caption: attributes.caption || '',
description: attributes.description || attributes.caption || '',
tag_names: attributes.tags_names || attributes.tags || [],
user_tag_ids: attributes.user_tags_ids || attributes.userTags || []
};
console.log('Extracted data from direct attributes:', mediaData);
}
}
// Fallback to root level data
else {
mediaData = {
title: storyData.title || storyData.name || '',
caption: storyData.caption || '',
description: storyData.description || storyData.caption || '',
tag_names: storyData.tags_names || storyData.tags || [],
user_tag_ids: storyData.user_tags_ids || storyData.userTags || []
};
console.log('Extracted data from root level:', mediaData);
}
return mediaData;
} catch (error) {
console.warn('Could not fetch current media data, using defaults:', error);
console.warn('Could not parse current media data, using defaults:', error);
return {
title: '',
caption: '',
......@@ -115,7 +207,7 @@
}
// Step 3: Get current media data to preserve existing values
const currentData = await getCurrentMediaData(mediaInfo.type, mediaInfo.id);
const currentData = getCurrentMediaData();
// Step 4: Prepare payload based on media type and privacy level
let payload;
......@@ -210,7 +302,7 @@
}
// Get current media data
const currentData = await getCurrentMediaData(mediaType, mediaId);
const currentData = getCurrentMediaData();
// Prepare payload
let payload;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment