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') { ...@@ -346,26 +346,103 @@ function executePrivacyUpdateFromContext(privacyLevel = 'friends_only') {
throw new Error('Could not find CSRF token. Please refresh the page and try again.'); 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; let payload;
if (mediaInfo.type === 'video') { if (mediaInfo.type === 'video') {
payload = { payload = {
video: { video: {
title: "", title: currentData.title,
description: "", description: currentData.description,
only_friends: privacyLevel === 'friends_only' ? true : false, only_friends: privacyLevel === 'friends_only' ? true : false,
tag_names: [], tag_names: currentData.tag_names,
user_tag_ids: [] user_tag_ids: currentData.user_tag_ids
}, },
render_flash: true render_flash: true
}; };
} else { } else {
payload = { payload = {
picture: { picture: {
caption: "", caption: currentData.caption,
content_privacy: privacyLevel === 'friends_only' ? "only_friends" : "public", content_privacy: privacyLevel === 'friends_only' ? "only_friends" : "public",
tag_names: [], tag_names: currentData.tag_names,
user_tag_ids: [] user_tag_ids: currentData.user_tag_ids
}, },
render_flash: true render_flash: true
}; };
...@@ -450,6 +527,7 @@ function executeBulkPrivacyUpdateFromContext() { ...@@ -450,6 +527,7 @@ function executeBulkPrivacyUpdateFromContext() {
async function updateMediaPrivacyById(mediaType, mediaId, csrfToken, privacyLevel = 'friends_only') { async function updateMediaPrivacyById(mediaType, mediaId, csrfToken, privacyLevel = 'friends_only') {
try { try {
// For bulk processing, we use default values since we don't have access to individual page data
let payload; let payload;
if (mediaType === 'video') { if (mediaType === 'video') {
payload = { payload = {
......
...@@ -57,34 +57,126 @@ ...@@ -57,34 +57,126 @@
return null; return null;
} }
// Function to get current media data for preserving existing values // Function to get current media data by parsing the story-data script tag
async function getCurrentMediaData(type, id) { function getCurrentMediaData() {
try { try {
const response = await fetch(`https://fetlife.com/${type}s/${id}`, { // Find the script tag with id "story-data"
method: 'GET', const storyDataScript = document.getElementById('story-data') || document.querySelector('script[id="story-data"]');
credentials: 'same-origin',
headers: { if (!storyDataScript) {
'Accept': 'application/json, text/javascript, */*; q=0.01', console.warn('Story data script not found, using defaults');
'X-Requested-With': 'XMLHttpRequest' 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);
} }
}); } catch (parseError) {
console.warn('Failed to parse story data JSON:', parseError);
if (!response.ok) { return {
throw new Error(`Failed to fetch ${type} data: ${response.status}`); title: '',
caption: '',
description: '',
tag_names: [],
user_tag_ids: []
};
} }
// For now, we'll use empty defaults since we're only updating privacy console.log('Parsed story data:', storyData);
// In a real implementation, you might want to parse the HTML response
// to extract current title/caption and tags // Extract data from attributes based on media type
return { let mediaData = {
title: '', title: '',
caption: '', caption: '',
description: '', description: '',
tag_names: [], tag_names: [],
user_tag_ids: [] 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) { } 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 { return {
title: '', title: '',
caption: '', caption: '',
...@@ -115,7 +207,7 @@ ...@@ -115,7 +207,7 @@
} }
// Step 3: Get current media data to preserve existing values // 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 // Step 4: Prepare payload based on media type and privacy level
let payload; let payload;
...@@ -210,7 +302,7 @@ ...@@ -210,7 +302,7 @@
} }
// Get current media data // Get current media data
const currentData = await getCurrentMediaData(mediaType, mediaId); const currentData = getCurrentMediaData();
// Prepare payload // Prepare payload
let 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