diff --git a/_locales/en/messages.json b/_locales/en/messages.json index e6a34579..1c5e56b0 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -632,5 +632,14 @@ "anniversary_tweet": { "message": "Do you remember when you joined Twitter? I do!\n#MyTwitterAnniversary" }, "you_shared_tweet": { "message": "You shared a tweet" }, "user_shared_tweet": { "message": "$NAME$ shared a tweet", "placeholders": { "name": { "content": "Display Name" } } }, - "transition_profile_banner": { "message": "Use transition on profile banner" } -} \ No newline at end of file + "transition_profile_banner": { "message": "Use transition on profile banner" }, + "custom_downloadtemplate": { "message": "Custom download template" }, + "custom_downloadtemplate_text": { "message": "Allows you to customize the names of the files when downloading a tweet's media." }, + "save_downloadtemplate": { "message": "Save download template" }, + "custom_downloadtemplate_hintName1": { "message": "{user_name}: User's name." }, + "custom_downloadtemplate_hintName2": { "message": "{user_screen_name}: User's account name. (Example: @dril)" }, + "custom_downloadtemplate_hintTime": { "message": "{timestamp}: Tweet's post date & time." }, + "custom_downloadtemplate_hintExtension": { "message": "{extension}: Downloaded tweet's file extension." }, + "custom_downloadtemplate_hintID": { "message": "{id}: Tweet's ID." }, + "custom_downloadtemplate_hintIndex": { "message": "{index}: Index for each file to download. (for posts with multiple media)" } +} diff --git a/layouts/settings/index.html b/layouts/settings/index.html index 938da9c7..f73df53d 100644 --- a/layouts/settings/index.html +++ b/layouts/settings/index.html @@ -393,6 +393,20 @@

__MSG_custom_css__




+

__MSG_custom_downloadtemplate__


+ __MSG_custom_downloadtemplate_text__
+
__MSG_custom_downloadtemplate_hintName1__ +
__MSG_custom_downloadtemplate_hintName2__ +
__MSG_custom_downloadtemplate_hintTime__ +
__MSG_custom_downloadtemplate_hintExtension__ +
__MSG_custom_downloadtemplate_hintID__ +
__MSG_custom_downloadtemplate_hintIndex__ +

+
+ +
+ +

__MSG_advanced_options__


@@ -437,4 +451,4 @@

__MSG_who_to_follow__


- \ No newline at end of file + diff --git a/layouts/settings/script.js b/layouts/settings/script.js index f86a988e..f63ac4b3 100644 --- a/layouts/settings/script.js +++ b/layouts/settings/script.js @@ -276,6 +276,8 @@ setTimeout(async () => { let disableFindHotkey = document.getElementById('disable-find-hotkey'); let customCSS = document.getElementById('custom-css'); let customCSSSave = document.getElementById('custom-css-save'); + let customDownloadTemplate = document.getElementById('custom-download'); + let customDownloadTemplateSave = document.getElementById('custom-download-save'); let savePreferredQuality = document.getElementById('save-preferred-quality'); let roundAvatars = document.getElementById('round-avatars-switch'); let modernUI = document.getElementById('modern-ui-switch'); @@ -907,6 +909,14 @@ setTimeout(async () => { console.error("Error saving CSS to DB:", error); }); }); + customDownloadTemplateSave.addEventListener('click', () => { + let val = customDownloadTemplate.value; + + vars.customDownloadTemplate = val; + chrome.storage.sync.set({ + customDownloadTemplate: val + }, () => { }); + }); autotranslateLanguageList.addEventListener('change', () => { addAutotranslateLanguage.disabled = autotranslateLanguageList.value === 'select'; }); @@ -1046,6 +1056,7 @@ setTimeout(async () => { writeCSSToDB(vars.customCSS) } customCSS.value = await readCSSFromDB(); + customDownloadTemplate.value = vars.customDownloadTemplate; document.getElementById('stt-div').hidden = vars.timelineType !== 'algo' && vars.timelineType !== 'algov2'; savePreferredQuality.checked = !!vars.savePreferredQuality; showOriginalImages.checked = !!vars.showOriginalImages; @@ -1281,4 +1292,4 @@ setTimeout(async () => { setInterval(updateUserData, 60000 * 3); setInterval(() => renderDiscovery(false), 60000 * 15); setInterval(renderTrends, 60000 * 5); -}, 50); \ No newline at end of file +}, 50); diff --git a/scripts/config.js b/scripts/config.js index 2a952629..d8c48ba9 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -32,7 +32,7 @@ async function loadVars() { 'acknowledgedCustomizationButton', 'modernUI', 'showExactValues', 'hideTimelineTypes', 'autotranslateLanguages', 'autotranslationMode', 'muteVideos', 'dontPauseVideos', 'showUserPreviewsOnMobile', 'systemDarkMode', 'localizeDigit', 'disableRetweetHotkey', 'disableLikeHotkey', 'disableFindHotkey', 'extensionCompatibilityMode', 'disableDataSaver', 'disableAcceptType', - 'showUserFollowerCountsInLists', 'showQuoteCount', 'hideUnfollowersPage', 'transitionProfileBanner' + 'showUserFollowerCountsInLists', 'showQuoteCount', 'hideUnfollowersPage', 'transitionProfileBanner', 'customDownloadTemplate' ], data => { // default variables if(typeof(data.linkColorsInTL) !== 'boolean') { @@ -77,6 +77,12 @@ async function loadVars() { customCSSVariables: '' }, () => {}); } + if(typeof(data.customDownloadTemplate) !== 'string') { + data.customDownloadTemplate = ''; + chrome.storage.sync.set({ + customDownloadTemplate: '' + }, () => {}); + } if(typeof(data.copyLinksAs) !== 'string') { data.copyLinksAs = 'twitter.com'; chrome.storage.sync.set({ @@ -234,4 +240,4 @@ async function loadVars() { }; console.log(1, vars); -loadVars(); \ No newline at end of file +loadVars(); diff --git a/scripts/helpers.js b/scripts/helpers.js index 72ceefb7..8e074947 100644 --- a/scripts/helpers.js +++ b/scripts/helpers.js @@ -3542,8 +3542,22 @@ async function appendTweet(t, timelineContainer, options = {}) { let extension = url.pathname.split('.').pop(); let _index = t.extended_entities.media.length > 1 ? "_"+(index+1) : ""; let filename = `${t.user.screen_name}_${ts}_${t.id_str}${_index}.${extension}`; - a.download = filename; + let filename_template = vars.customDownloadTemplate; + + // use the filename from the user's custom download template, if any + if(filename_template && (filename_template.length > 0)) { + const filesave_map = { + "user_screen_name": t.user.screen_name, + "user_name": t.user.name, + "extension": extension, + "timestamp": ts, + "id": t.id_str, + "index": _index + }; + filename = filename_template.replace(/\{([\w]+)\}/g, (_, key) => filesave_map[key]); + } + a.download = filename; a.click(); a.remove(); }).catch(e => { diff --git a/scripts/tweetviewer.js b/scripts/tweetviewer.js index 2e0a378f..ee7bec9d 100644 --- a/scripts/tweetviewer.js +++ b/scripts/tweetviewer.js @@ -2455,8 +2455,28 @@ class TweetViewer { downloading = false; let a = document.createElement('a'); a.href = URL.createObjectURL(blob); - a.download = media.type === 'photo' ? media.media_url_https.split('/').pop() : media.video_info.variants[0].url.split('/').pop(); - a.download = a.download.split('?')[0]; + + let ts = new Date(t.created_at).toISOString().split("T")[0]; + let extension = url.split('.').pop(); + //let _index = t.extended_entities.media.length > 1 ? "_"+(index+1) : ""; + let _index = ""; + let filename = `${t.user.screen_name}_${ts}_${t.id_str}${_index}.${extension}`; + let filename_template = vars.customDownloadTemplate; + + // use the filename from the user's custom download template, if any + if(filename_template && (filename_template.length > 0)) { + const filesave_map = { + "user_screen_name": t.user.screen_name, + "user_name": t.user.name, + "extension": extension, + "timestamp": ts, + "id": t.id_str, + "index": _index + }; + filename = filename_template.replace(/\{([\w]+)\}/g, (_, key) => filesave_map[key]); + } + + a.download = filename; a.click(); a.remove(); }).catch(e => {