diff --git a/README.md b/README.md index 54d91236..bdeb81a2 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,62 @@ # cobalt -Sleek and easy to use social media downloader built on JavaScript. Try it out live: [co.wukko.me](https://co.wukko.me/)! +Sleek and easy to use social media downloader built with JavaScript. + +Try it now: [co.wukko.me](https://co.wukko.me/) ![cobalt logo](https://raw.githubusercontent.com/wukko/cobalt/current/src/front/icons/wide.png "cobalt logo") -## What is cobalt? -cobalt aims to be the ultimate social media downloader, that is efficient, pretty, and doesn't bother you with ads or privacy invasion agreement popups. +## What's cobalt? +cobalt aims to be the ultimate social media downloader, that is efficient, pretty, and doesn't bother you with ads or privacy invasion agreement popups. It also doesn't remux anything, so you get media in best quality possible (unless you change that in settings). -cobalt doesn't remux any videos, so you get videos of max quality available (unless you change that in settings). +## Supported services -## What's supported? -- Twitter -- TikTok -- douyin -- YouTube and YouTube Music +### Video - bilibili.com +- douyin - Reddit +- TikTok +- Twitter +- YouTube +- YouTube Music - VK +### Audio +- YouTube +- YouTube Music + +## Translations +- Spanish: [@adrigoomy](https://github.com/adrigoomy) +- French: [@lexito-o](https://github.com/lexito-o) +- Indonesian: [@LyfeV](https://github.com/LyfeV) + +## How you can help cobalt speak your language +Take English or Russian localization from [this directory](https://github.com/wukko/cobalt/tree/current/src/localization/languages) and use it as a base for your translation. Then simply make a pull request and it'll be out for everyone upon review! + +### What you should keep in mind: +- Do **NOT** use formal language, that's boring and lame. Use informal language on all occasions. +- Strings are **ALWAYS** lowercase unless it's an internal value like {ContactLink} or STRESSED LIKE THIS. +- Keep translations as friendly and fun as possible. +- Word-for-word translations from original language are not valid. +- You can rephrase sentences as long as they keep the same sense. +- You can add wordplays or puns if it feels natural to do so. +- Even though I love cursing, keep that away from translations. +- Be nice. + ## TO-DO + +### Services +- [ ] Tumblr support - [ ] niconico support - [ ] Instagram support -- [ ] Quality switching for bilibili and Twitter -- [ ] Language picker in settings -- [ ] Make cobalt fully PWA compatible (add a service worker) -- [ ] Make switch buttons in settings selectable with keyboard -- [ ] Remake page rendering module to be more versatile -- [ ] Matching could be redone, I'll see what I can do +- [ ] SoundCloud support (?) +- [ ] Add an option to save Twitter GIFs as `.gif` instead of `.mp4` +- [ ] Quality switching for bilibili -## Disclaimer -This is my passion project, so update scheduele depends on my motivation. Don't expect any consistency in that. +### Other +- [ ] Language picker in settings +- [ ] Make switch buttons in settings selectable with keyboard +- [ ] Make cobalt fully PWA compatible (add a service worker) +- [ ] Make page rendering module more versatile ## Host an instance yourself Code might be a little messy, but I do my best to improve it with every commit. @@ -50,12 +78,15 @@ Code might be a little messy, but I do my best to improve it with every commit. - xml-js - ytdl-core -Setup script installs all needed **npm** dependencies, but you have to install Node.js and git yourself, if you don't have those already. +Setup script installs all needed `npm` dependencies, but you have to install `Node.js` and `git` yourself. 1. Clone the repo: `git clone https://github.com/wukko/cobalt` 2. Run setup script and follow instructions: `npm run setup` 3. Run cobalt via `npm start` 4. Done. +## Disclaimer +This is my passion project, so update scheduele depends solely on my motivation. Don't expect any consistency in that. + ## License -cobalt is under [AGPL-3.0 license](https://github.com/wukko/cobalt/blob/current/LICENSE), please keep that in mind. +cobalt is under [AGPL-3.0](https://github.com/wukko/cobalt/blob/current/LICENSE). diff --git a/jsconfig.json b/jsconfig.json index 0864127e..3a840ef5 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -10,4 +10,4 @@ "node_modules", "**/node_modules/*" ] -} \ No newline at end of file +} diff --git a/src/cobalt.js b/src/cobalt.js index f1458d0f..fe3179af 100644 --- a/src/cobalt.js +++ b/src/cobalt.js @@ -127,4 +127,4 @@ if (fs.existsSync('./.env')) { }); } else { console.log('Required config files are missing. Please run "npm run setup" first.') -} \ No newline at end of file +} diff --git a/src/front/cobalt.css b/src/front/cobalt.css index b1bb3fed..0eb55e34 100644 --- a/src/front/cobalt.css +++ b/src/front/cobalt.css @@ -496,4 +496,4 @@ input[type="checkbox"] { .bottom-link { padding-bottom: 2rem; } -} \ No newline at end of file +} diff --git a/src/front/cobalt.js b/src/front/cobalt.js index ade79ffc..682c13ca 100644 --- a/src/front/cobalt.js +++ b/src/front/cobalt.js @@ -200,4 +200,4 @@ eid("url-input-area").addEventListener("keyup", (event) => { if (event.key === 'Enter') { eid("download-button").click(); } -}) \ No newline at end of file +}) diff --git a/src/localization/languages/en.json b/src/localization/languages/en.json index 10958ac2..0b5d13bf 100644 --- a/src/localization/languages/en.json +++ b/src/localization/languages/en.json @@ -73,4 +73,4 @@ "Download": "download", "CopyURL": "copy url" } -} \ No newline at end of file +} diff --git a/src/localization/languages/ru.json b/src/localization/languages/ru.json index 27e37f49..0095e2e8 100644 --- a/src/localization/languages/ru.json +++ b/src/localization/languages/ru.json @@ -73,4 +73,4 @@ "Download": "скачать", "CopyURL": "скопировать ссылку" } -} \ No newline at end of file +} diff --git a/src/modules/api.js b/src/modules/api.js index 740857f7..998d8530 100644 --- a/src/modules/api.js +++ b/src/modules/api.js @@ -33,4 +33,4 @@ export async function getJSON(originalURL, ip, lang, format, quality) { } catch (e) { return apiJSON(0, { t: loc(lang, 'ErrorSomethingWentWrong') }); } -} \ No newline at end of file +} diff --git a/src/modules/config.js b/src/modules/config.js index da7f7081..49c80071 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -15,4 +15,4 @@ supportedLanguages = config.supportedLanguages, quality = config.quality, internetExplorerRedirect = config.internetExplorerRedirect, donations = config.donations, -ffmpegArgs = config.ffmpegArgs \ No newline at end of file +ffmpegArgs = config.ffmpegArgs diff --git a/src/modules/match.js b/src/modules/match.js index 03397e9a..31211d09 100644 --- a/src/modules/match.js +++ b/src/modules/match.js @@ -119,4 +119,4 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit } catch (e) { return apiJSON(0, { t: genericError(lang, host) }) } -} \ No newline at end of file +} diff --git a/src/modules/pageRender.js b/src/modules/pageRender.js index 7e9b3fa4..ec445503 100644 --- a/src/modules/pageRender.js +++ b/src/modules/pageRender.js @@ -202,4 +202,4 @@ export default function(obj) { } catch (err) { return `${loc(obj.lang, 'ErrorPageRenderFail', obj.hash)}`; } -} \ No newline at end of file +} diff --git a/src/modules/services/_config.json b/src/modules/services/_config.json index 7b2f6fc6..9b443a42 100644 --- a/src/modules/services/_config.json +++ b/src/modules/services/_config.json @@ -73,4 +73,4 @@ "patterns": ["video/:postId", ":id"], "enabled": true } -} \ No newline at end of file +} diff --git a/src/modules/services/bilibili.js b/src/modules/services/bilibili.js index 11886880..07aa392e 100644 --- a/src/modules/services/bilibili.js +++ b/src/modules/services/bilibili.js @@ -31,4 +31,3 @@ export default async function(obj) { return { error: loc(obj.lang, 'ErrorBadFetch') }; } } - diff --git a/src/modules/services/reddit.js b/src/modules/services/reddit.js index c7642de5..be033693 100644 --- a/src/modules/services/reddit.js +++ b/src/modules/services/reddit.js @@ -25,4 +25,4 @@ export default async function(obj) { } catch (err) { return { error: loc(obj.lang, 'ErrorBadFetch') }; } -} \ No newline at end of file +} diff --git a/src/modules/services/twitter.js b/src/modules/services/twitter.js index fdfa009a..23b6d51b 100644 --- a/src/modules/services/twitter.js +++ b/src/modules/services/twitter.js @@ -54,4 +54,4 @@ export default async function (obj) { } catch (err) { return { error: loc(obj.lang, 'ErrorBadFetch') }; } -} \ No newline at end of file +} diff --git a/src/modules/services/vk.js b/src/modules/services/vk.js index 17d90947..655ec4ed 100644 --- a/src/modules/services/vk.js +++ b/src/modules/services/vk.js @@ -44,4 +44,4 @@ export default async function(obj) { } catch (err) { return { error: loc(obj.lang, 'ErrorBadFetch') }; } -} \ No newline at end of file +} diff --git a/src/modules/services/youtube.js b/src/modules/services/youtube.js index b0d3e526..d2f3cd03 100644 --- a/src/modules/services/youtube.js +++ b/src/modules/services/youtube.js @@ -71,4 +71,3 @@ export default async function (obj) { return { error: loc(obj.lang, 'ErrorBadFetch') }; } } - diff --git a/src/modules/setup.js b/src/modules/setup.js index 207a9a43..514706c7 100644 --- a/src/modules/setup.js +++ b/src/modules/setup.js @@ -51,4 +51,4 @@ let final = () => { console.log("You can re-run this script any time to update the configuration.") console.log("\nYou're now ready to start the main project.\nHave fun!") rl.close() -} \ No newline at end of file +} diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index c8b3416c..3a7bdebd 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -43,4 +43,4 @@ export function verifyStream(ip, id, hmac, exp, salt) { } catch (e) { return { status: 500, body: { status: "error", text: "Internal Server Error" } }; } -} \ No newline at end of file +} diff --git a/src/modules/stream/selectQuality.js b/src/modules/stream/selectQuality.js index 2bc22282..e2b99417 100644 --- a/src/modules/stream/selectQuality.js +++ b/src/modules/stream/selectQuality.js @@ -29,4 +29,4 @@ export default function(service, quality, maxQuality) { return closest(quality, s) } } -} \ No newline at end of file +} diff --git a/src/modules/stream/types.js b/src/modules/stream/types.js index d910e259..edb86432 100644 --- a/src/modules/stream/types.js +++ b/src/modules/stream/types.js @@ -110,4 +110,4 @@ export async function streamAudioOnly(streamInfo, res) { } catch (e) { internalError(res); } -} \ No newline at end of file +} diff --git a/src/modules/sub/crypto.js b/src/modules/sub/crypto.js index 4946bf79..03d27d12 100644 --- a/src/modules/sub/crypto.js +++ b/src/modules/sub/crypto.js @@ -8,4 +8,4 @@ export function md5(string) { } export function UUID() { return randomUUID(); -} \ No newline at end of file +} diff --git a/src/modules/sub/currentCommit.js b/src/modules/sub/currentCommit.js index f2897323..7dfb1f9b 100644 --- a/src/modules/sub/currentCommit.js +++ b/src/modules/sub/currentCommit.js @@ -7,4 +7,4 @@ export function getCommitInfo() { let d = execSync(`git show -s --format='%s;;;%B'`).toString().trim().replace(/[\r\n]/gm, '\n').split(';;;') d[1] = d[1].replace(d[0], '').trim().toString().replace(/[\r\n]/gm, '
') return d -} \ No newline at end of file +} diff --git a/src/modules/sub/errors.js b/src/modules/sub/errors.js index 371f64f7..c321b5ba 100644 --- a/src/modules/sub/errors.js +++ b/src/modules/sub/errors.js @@ -8,4 +8,4 @@ export function errorUnsupported(lang) { } export function genericError(lang, host) { return loc(lang, 'ErrorBrokenLink', host); -} \ No newline at end of file +} diff --git a/src/modules/sub/loadJSON.js b/src/modules/sub/loadJSON.js index c431fc57..205c36d6 100644 --- a/src/modules/sub/loadJSON.js +++ b/src/modules/sub/loadJSON.js @@ -6,4 +6,4 @@ export default function(path) { } catch(e) { return false } -} \ No newline at end of file +} diff --git a/src/modules/sub/utils.js b/src/modules/sub/utils.js index d6838606..ca2cef6b 100644 --- a/src/modules/sub/utils.js +++ b/src/modules/sub/utils.js @@ -56,4 +56,4 @@ export function unicodeDecode(str) { return str.replace(/\\u[\dA-F]{4}/gi, (unicode) => { return String.fromCharCode(parseInt(unicode.replace(/\\u/g, ""), 16)); }); -} \ No newline at end of file +}