From 02529c0b54ddacaf1de4abddfdebbcb744df5792 Mon Sep 17 00:00:00 2001 From: wukko Date: Thu, 27 Oct 2022 22:27:20 +0600 Subject: [PATCH] 4.1: better tiktok image downloads and celebrations --- package.json | 2 +- src/config.json | 23 +++++++++++++++++ src/front/cobalt.js | 4 +-- src/front/emoji/candle.svg | 7 ++++++ src/front/emoji/cat.svg | 13 ++++++++++ src/front/emoji/christmas_tree.svg | 11 +++++++++ src/front/emoji/dog.svg | 11 +++++++++ src/front/emoji/pumpkin.svg | 7 ++++++ src/modules/changelog/changelog.json | 16 +++++++----- src/modules/config.js | 3 ++- src/modules/emoji.js | 8 +++++- src/modules/pageRender/elements.js | 8 ++++++ src/modules/pageRender/page.js | 7 +++--- src/modules/processing/matchActionDecider.js | 10 ++++++-- src/modules/services/tiktok.js | 26 +++++++++++--------- src/modules/stream/manage.js | 2 +- 16 files changed, 129 insertions(+), 29 deletions(-) create mode 100644 src/front/emoji/candle.svg create mode 100644 src/front/emoji/cat.svg create mode 100644 src/front/emoji/christmas_tree.svg create mode 100644 src/front/emoji/dog.svg create mode 100644 src/front/emoji/pumpkin.svg diff --git a/package.json b/package.json index e7716635..597ccbc0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cobalt", "description": "save what you love", - "version": "4.0.1", + "version": "4.1", "author": "wukko", "exports": "./src/cobalt.js", "type": "module", diff --git a/src/config.json b/src/config.json index bfe1adea..044ac2ef 100644 --- a/src/config.json +++ b/src/config.json @@ -29,6 +29,29 @@ "mid": "720", "low": "480" }, + "celebrations": { + "01-01": "🎄", + "02-17": "đŸ˜ē", + "02-22": "đŸ˜ē", + "03-01": "đŸ˜ē", + "05-26": "🀄", + "08-08": "đŸ˜ē", + "08-26": "đŸļ", + "10-29": "đŸ˜ē", + "10-30": "🎃", + "10-31": "🎃", + "11-01": "đŸ•¯ī¸", + "11-02": "đŸ•¯ī¸", + "12-23": "🎄", + "12-24": "🎄", + "12-25": "🎄", + "12-26": "🎄", + "12-27": "🎄", + "12-28": "🎄", + "12-29": "🎄", + "12-30": "🎄", + "12-31": "🎄" + }, "supportedAudio": ["mp3", "ogg", "wav", "opus"], "ffmpegArgs": { "webm": ["-c:v", "copy", "-c:a", "copy"], diff --git a/src/front/cobalt.js b/src/front/cobalt.js index d5ee4474..65b0f1bc 100644 --- a/src/front/cobalt.js +++ b/src/front/cobalt.js @@ -336,7 +336,7 @@ async function download(url) { case "picker": if (j.audio && j.url) { changeDownloadButton(2, '?..') - fetch(`${j.audio}&p=1&origin=front`).then(async (res) => { + fetch(`${j.audio}&p=1`).then(async (res) => { let jp = await res.json(); if (jp.status === "continue") { changeDownloadButton(2, '>>>'); @@ -356,7 +356,7 @@ async function download(url) { break; case "stream": changeDownloadButton(2, '?..') - fetch(`${j.url}&p=1&origin=front`).then(async (res) => { + fetch(`${j.url}&p=1`).then(async (res) => { let jp = await res.json(); if (jp.status === "continue") { changeDownloadButton(2, '>>>'); window.location.href = j.url; diff --git a/src/front/emoji/candle.svg b/src/front/emoji/candle.svg new file mode 100644 index 00000000..f62a93d3 --- /dev/null +++ b/src/front/emoji/candle.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/front/emoji/cat.svg b/src/front/emoji/cat.svg new file mode 100644 index 00000000..a29d581e --- /dev/null +++ b/src/front/emoji/cat.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/front/emoji/christmas_tree.svg b/src/front/emoji/christmas_tree.svg new file mode 100644 index 00000000..dead8216 --- /dev/null +++ b/src/front/emoji/christmas_tree.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/front/emoji/dog.svg b/src/front/emoji/dog.svg new file mode 100644 index 00000000..03056a1f --- /dev/null +++ b/src/front/emoji/dog.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/front/emoji/pumpkin.svg b/src/front/emoji/pumpkin.svg new file mode 100644 index 00000000..3dcf031a --- /dev/null +++ b/src/front/emoji/pumpkin.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/modules/changelog/changelog.json b/src/modules/changelog/changelog.json index 03eae835..20940e1f 100644 --- a/src/modules/changelog/changelog.json +++ b/src/modules/changelog/changelog.json @@ -1,13 +1,17 @@ { "current": { - "version": "4.0", - "title": "better and faster than ever", - "content": "this update has a ton of improvements and new features.\n\nchanges you probably care about:\n- cobalt now has support for recorded twitter spaces! download the previous conversation no matter how long it was.\n- download speeds from youtube are at least 10 times better now. you're welcome.\n- both video and audio length limits have been extended to 2 hours.\n- audio downloads from youtube, youtube music, twitter spaces, and soundcloud now have metadata! most often it's just title and artist, but when cobalt is able to get more info, it adds that metadata too.\n- tiktok downloads have been fixed, yet again, and if they ever break in the future, cobalt will fall back to downloading a less annoyingly watermarked video.\n- soundcloud downloads have been fixed, too.\n\nless notable changes:\n- currently experimenting with using mp3 as default audio format. if you set something other than mp3 before, it'll be set to mp3. you can always change it back in settings. let me know what you think about this.\n- \"download audio\" button from image picker no longer stays on the screen after popup was closed.\n- clipboard button now shows up depending on your browser's support for it.\n- you can no longer manually hide the clipboard button, 'cause it's unnecessary.\n- small internal improvements such as separation of changelog version and title.\n- fair bit of internal clean up.\n\nif you want to help me implement covers for downloaded audios, you can do it on github.\n\nfun fact: average cobalt user is 10 times cooler than everyone else." + "version": "4.1", + "title": "better tiktok image downloads", + "content": "here's what's up:\n- tiktok images are saved as .jpeg instead of .webp (finally, i know).\n- added support for image downloads from douyin.\n- fixed tiktok audio downloads from the image picker.\n- emoji in about button now changes on special occasions. be it halloween or christmas, {appName} will change just a tiny bit to fit in :D\n\nif you're not caught up with new stuff in {appName} 4.x yet, check out the previous changelog down below. there's a ton of stuff to like." }, "history": [{ + "version": "4.0", + "title": "better and faster than ever", + "content": "this update has a ton of improvements and new features.\n\nchanges you probably care about:\n- {appName} now has support for recorded twitter spaces! download the previous conversation no matter how long it was.\n- download speeds from youtube are at least 10 times better now. you're welcome.\n- both video and audio length limits have been extended to 2 hours.\n- audio downloads from youtube, youtube music, twitter spaces, and soundcloud now have metadata! most often it's just title and artist, but when {appName} is able to get more info, it adds that metadata too.\n- tiktok downloads have been fixed, yet again, and if they ever break in the future, {appName} will fall back to downloading a less annoyingly watermarked video.\n- soundcloud downloads have been fixed, too.\n\nless notable changes:\n- currently experimenting with using mp3 as default audio format. if you set something other than mp3 before, it'll be set to mp3. you can always change it back in settings. let me know what you think about this.\n- \"download audio\" button from image picker no longer stays on the screen after popup was closed.\n- clipboard button now shows up depending on your browser's support for it.\n- you can no longer manually hide the clipboard button, 'cause it's unnecessary.\n- small internal improvements such as separation of changelog version and title.\n- fair bit of internal clean up.\n\nif you want to help me implement covers for downloaded audios, you can do it on github.\n\nfun fact: average {appName} user is 10 times cooler than a regular person." + }, { "version": "3.7", "title": "support for multi media tweets is here!", - "content": "{appName} now lets you save any of the videos or gifs in a tweet. even if there are many of them.\n\nsimply paste a link like you'd usually do and {appName} will ask what exactly you want to save.\n\nFIREFOX USERS: if you have strict tracking protection on, you might wanna turn it off for {appName}, or else twitter video previews won't load. firefox filters out twitter image cdn as if it was a tracker, which it's not. it's a false-positive.\n\nhowever, you can leave it on if you're fine with blank squares and video numbers. i have thought of that in prior, you're welcome.\n\nother changes:\n- repurposed ex tiktok-only image picker to be dynamic and adapt depending on content to pick. that's exactly how twitter multi media downloads work.\n- cobalt is now properly viewable on phones with tiny screens, such as first gen iphone se.\n- scrollbars now should be visible only where they're needed.\n- brought back proper twitter api, because other one doesn't have multi media stuff (at least yet).\n- cleaned up some internal files, including main frontend js file.\n- reorganized some files in project directory, now you won't get lost when contributing or just looking through cobalt's code." + "content": "{appName} now lets you save any of the videos or gifs in a tweet. even if there are many of them.\n\nsimply paste a link like you'd usually do and {appName} will ask what exactly you want to save.\n\nFIREFOX USERS: if you have strict tracking protection on, you might wanna turn it off for {appName}, or else twitter video previews won't load. firefox filters out twitter image cdn as if it was a tracker, which it's not. it's a false-positive.\n\nhowever, you can leave it on if you're fine with blank squares and video numbers. i have thought of that in prior, you're welcome.\n\nother changes:\n- repurposed ex tiktok-only image picker to be dynamic and adapt depending on content to pick. that's exactly how twitter multi media downloads work.\n- {appName} is now properly viewable on phones with tiny screens, such as first gen iphone se.\n- scrollbars now should be visible only where they're needed.\n- brought back proper twitter api, because other one doesn't have multi media stuff (at least yet).\n- cleaned up some internal files, including main frontend js file.\n- reorganized some files in project directory, now you won't get lost when contributing or just looking through {appName}'s code." }, { "version": "3.6.2 + 3.6.3", "title": "less disturbance", @@ -15,7 +19,7 @@ }, { "version": "3.6", "title": "improvements all around!", - "content": "- download mode switcher is moving places, it's now right next to link input area.\n- smart mode has been renamed to auto mode, because this name is easier to understand.\n- all spacings in ui have been evened out. no more eye strain.\n- added support for twitter /video/1 links\n- clipboard button exception has been redone to prepare for adoption of readtext clipboard api in firefox.\n- cobalt is now using different tiktok api endpoint, because previous one got killed, just like the one before.\n- \"other\" settings tab has been cleaned up." + "content": "- download mode switcher is moving places, it's now right next to link input area.\n- smart mode has been renamed to auto mode, because this name is easier to understand.\n- all spacings in ui have been evened out. no more eye strain.\n- added support for twitter /video/1 links\n- clipboard button exception has been redone to prepare for adoption of readtext clipboard api in firefox.\n- {appName} is now using different tiktok api endpoint, because previous one got killed, just like the one before.\n- \"other\" settings tab has been cleaned up." }, { "version": "3.5.4", "title": "tiktok support is back :D", @@ -23,7 +27,7 @@ }, { "version": "3.5.2", "title": "vk clips support, improved changelog system, and less bugs", - "content": "new features: \n- added support for vk clips. {appName} now lets you download even more cringy videos!\n- added update history right to the changelog menu. it's not loaded by default to minimize page load time, but can be loaded upon pressing a button. probably someone will enjoy this.\n- as you've just read, cobalt now has on-demand blocks. they're rendered on server upon request and exist to prevent any unnecessary clutter by default. the first feature to use on-demand rendering is history of updates in changelog tab.\n\nchanges:\n- moved twitter entry to about tab and made it localized.\n- added clarity to what services exactly are supported in about tab.\n\nbug fixes:\n- cobalt should no longer crash to firefox users if they love to play around with user-agent switching.\n- vk videos of any resolution and aspect ratio should now be downloadable.\n- vk quality picking has been fixed after vk broke it for parsers on their side." + "content": "new features: \n- added support for vk clips. {appName} now lets you download even more cringy videos!\n- added update history right to the changelog menu. it's not loaded by default to minimize page load time, but can be loaded upon pressing a button. probably someone will enjoy this.\n- as you've just read, {appName} now has on-demand blocks. they're rendered on server upon request and exist to prevent any unnecessary clutter by default. the first feature to use on-demand rendering is history of updates in changelog tab.\n\nchanges:\n- moved twitter entry to about tab and made it localized.\n- added clarity to what services exactly are supported in about tab.\n\nbug fixes:\n- {appName} should no longer crash to firefox users if they love to play around with user-agent switching.\n- vk videos of any resolution and aspect ratio should now be downloadable.\n- vk quality picking has been fixed after vk broke it for parsers on their side." }, { "version": "3.5", "title": "ui revamp and usability imporvements", diff --git a/src/modules/config.js b/src/modules/config.js index f40e1706..6e3d81c0 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -19,4 +19,5 @@ export const internetExplorerRedirect = config.internetExplorerRedirect, donations = config.donations, ffmpegArgs = config.ffmpegArgs, - supportedAudio = config.supportedAudio + supportedAudio = config.supportedAudio, + celebrations = config.celebrations diff --git a/src/modules/emoji.js b/src/modules/emoji.js index 2bc587ec..34a831e1 100644 --- a/src/modules/emoji.js +++ b/src/modules/emoji.js @@ -8,10 +8,16 @@ const names = { "đŸĒ…": "pinata", "đŸĒ„": "magic_wand", "🐲": "dragon_face", + "🀄": "dragon_face_wukko", "💸": "money_with_wings", "⚙ī¸": "gear", "☚ī¸": "frowning_face", - "📋": "clipboard" + "📋": "clipboard", + "🎃": "pumpkin", + "🎄": "christmas_tree", + "đŸ•¯ī¸": "candle", + "đŸ˜ē": "cat", + "đŸļ": "dog" } let sizing = { 22: 0.4, diff --git a/src/modules/pageRender/elements.js b/src/modules/pageRender/elements.js index 184f1f4d..236e1dad 100644 --- a/src/modules/pageRender/elements.js +++ b/src/modules/pageRender/elements.js @@ -1,3 +1,5 @@ +import { celebrations } from "../config.js"; + export function switcher(obj) { let items = ``; switch(obj.name) { @@ -135,3 +137,9 @@ export function footerButtons(obj) { return ` ` } + +export function celebrationsEmoji() { + let n = new Date().toISOString().split('T')[0].split('-'); + let dm = `${n[1]}-${n[2]}`; + return Object.keys(celebrations).includes(dm) ? celebrations[dm] : "🐲"; +} diff --git a/src/modules/pageRender/page.js b/src/modules/pageRender/page.js index cdb62923..e81ce65d 100644 --- a/src/modules/pageRender/page.js +++ b/src/modules/pageRender/page.js @@ -1,11 +1,10 @@ -import { backdropLink, checkbox, footerButtons, multiPagePopup, popup, popupWithBottomButtons, settingsCategory, switcher } from "./elements.js"; -import { services, appName, authorInfo, version, quality, repo, donations, supportedAudio } from "../config.js"; +import { backdropLink, celebrationsEmoji, checkbox, footerButtons, multiPagePopup, popup, popupWithBottomButtons, settingsCategory, switcher } from "./elements.js"; +import { services as s, appName, authorInfo, version, quality, repo, donations, supportedAudio } from "../config.js"; import { getCommitInfo } from "../sub/currentCommit.js"; import loc from "../../localization/manager.js"; import emoji from "../emoji.js"; import changelogManager from "../changelog/changelogManager.js"; -let s = services; let com = getCommitInfo(); let enabledServices = Object.keys(s).filter((p) => { @@ -311,7 +310,7 @@ export default function(obj) { footerButtons([{ name: "about", type: "popup", - text: `${emoji("🐲", 22)} ${loc(obj.lang, 'AboutTab')}`, + text: `${emoji(celebrationsEmoji() , 22)} ${loc(obj.lang, 'AboutTab')}`, aria: loc(obj.lang, 'AccessibilityOpenAbout') }, { name: "settings", diff --git a/src/modules/processing/matchActionDecider.js b/src/modules/processing/matchActionDecider.js index bc74d566..476c85a2 100644 --- a/src/modules/processing/matchActionDecider.js +++ b/src/modules/processing/matchActionDecider.js @@ -48,10 +48,16 @@ export default function(r, host, ip, audioFormat, isAudioOnly) { switch (host) { case "douyin": case "tiktok": + let type = "render"; + if (audioFormat === "mp3" || audioFormat === "best") { + audioFormat = "mp3" + type = "bridge" + } return apiJSON(5, { + type: type, picker: r.picker, u: Array.isArray(r.urls) ? r.urls[1] : r.urls, service: host, ip: ip, - filename: r.audioFilename, salt: process.env.streamSalt, isAudioOnly: true, audioFormat: audioFormat, copy: audioFormat === "best" ? true : false + filename: r.audioFilename, salt: process.env.streamSalt, isAudioOnly: true, audioFormat: audioFormat, copy: audioFormat === "best" ? true : false, }) case "twitter": return apiJSON(5, { @@ -64,7 +70,7 @@ export default function(r, host, ip, audioFormat, isAudioOnly) { let copy = false; if (!supportedAudio.includes(audioFormat)) audioFormat = "best"; - if ((host === "tiktok" || host === "douyin") && isAudioOnly && services.tiktok.audioFormats.includes(audioFormat)) { + if ((host == "tiktok" || host == "douyin") && isAudioOnly && services.tiktok.audioFormats.includes(audioFormat)) { if (r.isMp3) { if (audioFormat === "mp3" || audioFormat === "best") { audioFormat = "mp3" diff --git a/src/modules/services/tiktok.js b/src/modules/services/tiktok.js index 6493b16a..28d7c640 100644 --- a/src/modules/services/tiktok.js +++ b/src/modules/services/tiktok.js @@ -15,17 +15,16 @@ let config = { } } function selector(j, h, id) { + let t; switch (h) { case "tiktok": - let t = j["aweme_list"].filter((v) => { - if (v["aweme_id"] == id) return true - }) - if (t.length > 0) { - return t[0] - } else return false + t = j["aweme_list"].filter((v) => { if (v["aweme_id"] == id) return true }) + break; case "douyin": - return j['item_list'][0] + t = j['item_list'].filter((v) => { if (v["aweme_id"] == id) return true }) + break; } + if (t.length > 0) { return t[0] } else return false } export default async function(obj) { @@ -53,10 +52,13 @@ export default async function(obj) { } else throw new Error() } else throw new Error() } - let video, videoFilename, audioFilename, isMp3, audio, - images = detail["image_post_info"] ? detail["image_post_info"]["images"] : false, + let video, videoFilename, audioFilename, isMp3, audio, images, filenameBase = `${obj.host}_${obj.postId}`; - + if (obj.host == "tiktok") { + images = detail["image_post_info"] ? detail["image_post_info"]["images"] : false + } else { + images = detail["images"] ? detail["images"] : false + } if (!obj.isAudioOnly && !images) { video = obj.host === "tiktok" ? detail["video"]["play_addr"]["url_list"][0] : detail["video"]["play_addr"]["url_list"][0].replace("playwm", "play"); videoFilename = `${filenameBase}_video_nw.mp4` // nw - no watermark @@ -98,7 +100,9 @@ export default async function(obj) { if (images) { let imageLinks = []; for (let i in images) { - imageLinks.push({url: images[i]["display_image"]["url_list"][0]}) + let selector = obj.host == "tiktok" ? images[i]["display_image"]["url_list"] : images[i]["url_list"]; + selector = selector.filter((i) => { if (i.includes(".jpeg?")) return true; }) + imageLinks.push({url: selector[0]}) } return { picker: imageLinks, diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index 84ed5eaa..da58a309 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -23,7 +23,7 @@ export function createStream(obj) { audioFormat: obj.audioFormat, time: obj.time, copy: obj.copy, - metadata: obj.fileMetadata + metadata: obj.fileMetadata ? obj.fileMetadata : false }); return `${process.env.selfURL}api/stream?t=${streamUUID}&e=${exp}&h=${ghmac}`; }