Merge branch 'main' into main

This commit is contained in:
Aphex 2024-09-22 16:16:31 +02:00 committed by GitHub
commit d336e5bd2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 64 additions and 42 deletions

View File

@ -105,6 +105,18 @@ export const runAPI = (express, app, __dirname) => {
app.post('/', apiLimiter);
app.use('/tunnel', apiLimiterStream);
app.post('/', (req, res, next) => {
if (!acceptRegex.test(req.header('Accept'))) {
return fail(res, "error.api.header.accept");
}
if (!acceptRegex.test(req.header('Content-Type'))) {
return fail(res, "error.api.header.content_type");
}
next();
});
app.post('/', (req, res, next) => {
if (!env.turnstileSecret || !env.jwtSecret) {
return next();
@ -128,14 +140,6 @@ export const runAPI = (express, app, __dirname) => {
return fail(res, "error.api.auth.jwt.invalid");
}
if (!acceptRegex.test(req.header('Accept'))) {
return fail(res, "error.api.header.accept");
}
if (!acceptRegex.test(req.header('Content-Type'))) {
return fail(res, "error.api.header.content_type");
}
req.authorized = true;
} catch {
return fail(res, "error.api.generic");

View File

@ -65,3 +65,14 @@ export function merge(a, b) {
return a;
}
export function splitFilenameExtension(filename) {
const parts = filename.split('.');
const ext = parts.pop();
if (!parts.length) {
return [ ext, "" ]
} else {
return [ parts.join('.'), ext ]
}
}

View File

@ -3,6 +3,7 @@ import createFilename from "./create-filename.js";
import { createResponse } from "./request.js";
import { audioIgnore } from "./service-config.js";
import { createStream } from "../stream/manage.js";
import { splitFilenameExtension } from "../misc/utils.js";
export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disableMetadata, filenameStyle, twitterGif, requestIP, audioBitrate, alwaysProxy }) {
let action,
@ -32,10 +33,11 @@ export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disab
}
if (action === "muteVideo" && isAudioMuted && !r.filenameAttributes) {
const parts = r.filename.split(".");
const ext = parts.pop();
defaultParams.filename = `${parts.join(".")}_mute.${ext}`;
const [ name, ext ] = splitFilenameExtension(r.filename);
defaultParams.filename = `${name}_mute.${ext}`;
} else if (action === "gif") {
const [ name ] = splitFilenameExtension(r.filename);
defaultParams.filename = `${name}.gif`;
}
switch (action) {

View File

@ -176,7 +176,7 @@ export const services = {
Object.values(services).forEach(service => {
service.patterns = service.patterns.map(
pattern => new UrlPattern(pattern, {
segmentValueCharset: UrlPattern.defaultOptions.segmentValueCharset + '@\\.'
segmentValueCharset: UrlPattern.defaultOptions.segmentValueCharset + '@\\.:'
})
)
})

View File

@ -291,7 +291,7 @@ const convertGif = (streamInfo, res) => {
const [,,, muxOutput] = process.stdio;
res.setHeader('Connection', 'keep-alive');
res.setHeader('Content-Disposition', contentDisposition(streamInfo.filename.split('.')[0] + ".gif"));
res.setHeader('Content-Disposition', contentDisposition(streamInfo.filename));
pipe(muxOutput, res, shutdown);

View File

@ -1,7 +1,7 @@
import { existsSync, unlinkSync, appendFileSync } from "fs";
import { createInterface } from "readline";
import { Cyan, Bright } from "./misc/console-text.js";
import { loadJSON } from "./misc/load-from-fs.js";
import { Cyan, Bright } from "../misc/console-text.js";
import { loadJSON } from "../misc/load-from-fs.js";
import { execSync } from "child_process";
const { version } = loadJSON("./package.json");

View File

@ -1401,7 +1401,7 @@
"bsky": [
{
"name": "horizontal video",
"url": "https://bsky.app/profile/haileyok.com/post/3l3giwtwp222m",
"url": "https://bsky.app/profile/did:plc:oisofpd7lj26yvgiivf3lxsi/post/3l3giwtwp222m",
"params": {},
"expected": {
"code": 200,
@ -1410,7 +1410,7 @@
},
{
"name": "horizontal video, recordWithMedia",
"url": "https://bsky.app/profile/juicysteak117.gay/post/3l3wonhk23g2i",
"url": "https://bsky.app/profile/did:plc:ywbm3iywnhzep3ckt6efhoh7/post/3l3wonhk23g2i",
"params": {},
"expected": {
"code": 200,
@ -1419,7 +1419,7 @@
},
{
"name": "vertical video",
"url": "https://bsky.app/profile/haileyok.com/post/3l3jhpomhjk2m",
"url": "https://bsky.app/profile/did:plc:oisofpd7lj26yvgiivf3lxsi/post/3l3jhpomhjk2m",
"params": {},
"expected": {
"code": 200,
@ -1428,7 +1428,7 @@
},
{
"name": "vertical video (muted)",
"url": "https://bsky.app/profile/haileyok.com/post/3l3jhpomhjk2m",
"url": "https://bsky.app/profile/did:plc:oisofpd7lj26yvgiivf3lxsi/post/3l3jhpomhjk2m",
"params": {
"downloadMode": "mute"
},
@ -1439,7 +1439,7 @@
},
{
"name": "vertical video (audio)",
"url": "https://bsky.app/profile/haileyok.com/post/3l3jhpomhjk2m",
"url": "https://bsky.app/profile/did:plc:oisofpd7lj26yvgiivf3lxsi/post/3l3jhpomhjk2m",
"params": {
"downloadMode": "audio"
},
@ -1450,7 +1450,7 @@
},
{
"name": "single image",
"url": "https://bsky.app/profile/thehardyboycats.bsky.social/post/3l33flpoygt26",
"url": "https://bsky.app/profile/did:plc:k4a7d65fcyevbrnntjxh57go/post/3l33flpoygt26",
"params": {},
"expected": {
"code": 200,
@ -1459,7 +1459,7 @@
},
{
"name": "several images",
"url": "https://bsky.app/profile/tracey-m.bsky.social/post/3kzxuxbiul626",
"url": "https://bsky.app/profile/did:plc:rai7s6su2sy22ss7skouedl7/post/3kzxuxbiul626",
"params": {},
"expected": {
"code": 200,
@ -1467,8 +1467,8 @@
}
},
{
"name": "deleted post",
"url": "https://bsky.app/profile/samuel.bsky.team/post/3l2udah76ch2c",
"name": "deleted post/invalid user",
"url": "https://bsky.app/profile/notreal.bsky.team/post/3l2udah76ch2c",
"params": {},
"expected": {
"code": 400,
@ -1476,4 +1476,4 @@
}
}
]
}
}

1
packages/api-client/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
dist

View File

@ -47,7 +47,7 @@ and for nerds, we have a giant list of backend changes (that we are also excited
this update allows us to actually innovate and develop new & exciting features. we are no longer held back by the legacy codebase. first feature of such kind is on-device remuxing. go check it out!
oh yeah, we now have 2.5 million monthly users. kind of insane.
oh yeah, we now have over 2 million monthly users. kind of insane.
we hope you enjoy this update as much as we enjoyed making it. it was a really fun summer project for both of us.

View File

@ -65,7 +65,7 @@
"metadata.filename.basic": "basic",
"metadata.filename.pretty": "pretty",
"metadata.filename.nerdy": "nerdy",
"metadata.filename.description": "filename style will only be used for files tunnelled by cobalt. some services don't support filename styles other than classic.",
"metadata.filename.description": "filename style will only be used for files tunneled by cobalt. some services don't support filename styles other than classic.",
"metadata.filename.preview.video": "Video Title",
"metadata.filename.preview.audio": "Audio Title - Audio Author",
@ -88,17 +88,17 @@
"accessibility.motion.description": "disables animations and transitions whenever possible.",
"language": "language",
"language.auto.title": "use default browser language",
"language.auto.description": "automatically picks the best language for you. if preferred browser language isn't available, english is used instead.",
"language.auto.title": "automatic selection",
"language.auto.description": "cobalt will use your browser's default language if translation is available. if not, english will be used instead.",
"language.preferred.title": "preferred language",
"language.preferred.description": "if any text isnt translated to the preferred language, it will fall back to english.",
"language.preferred.description": "this language will be used when automatic selection is disabled. any text that isn't translated will be displayed in english.",
"privacy.analytics": "anonymous traffic analytics",
"privacy.analytics.title": "don't contribute to analytics",
"privacy.analytics.description": "anonymous traffic analytics are needed to get an approximate number of active cobalt users. no identifiable information about you is ever stored. all processed data is anonymized and aggregated.\n\nwe use a self-hosted plausible instance that doesn't use cookies and is fully compliant with GDPR, CCPA, and PECR.",
"privacy.analytics.learnmore": "learn more about plausible's dedication to privacy.",
"privacy.tunnel": "tunnelling",
"privacy.tunnel": "tunneling",
"privacy.tunnel.title": "always tunnel files",
"privacy.tunnel.description": "cobalt will hide your ip address, browser info, and bypass local network restrictions. when enabled, files will also have readable filenames that otherwise would be gibberish.",

View File

@ -59,7 +59,7 @@
<div class="action-button-icon">
<CopyIcon check={copied} />
</div>
copy
{$t("button.copy")}
</button>
{#if device.supports.share}

View File

@ -1,5 +1,4 @@
<script lang="ts">
import locale from "$lib/i18n/locale";
import languages from "$i18n/languages.json";
import { t, locales } from "$lib/i18n/translations";
@ -10,10 +9,12 @@
$: currentSetting = $settings.appearance.language;
$: disabled = $settings.appearance.autoLanguage;
const updateLocale = (lang: string) => {
const updateLocale = (event: Event) => {
const target = event.target as HTMLSelectElement;
updateSetting({
appearance: {
language: lang as keyof typeof languages,
language: target.value as keyof typeof languages,
},
});
};
@ -34,8 +35,7 @@
</div>
<select
id="setting-dropdown-appearance-language"
bind:value={$locale}
on:change={() => updateLocale($locale)}
on:change={updateLocale}
{disabled}
>
{#each $locales as value}

View File

@ -7,7 +7,7 @@ import type {
LocalizationContent
} from '$lib/types/i18n';
import languages from '$i18n/languages.json';
import _languages from '$i18n/languages.json';
const locFiles = import.meta.glob('$i18n/*/**/*.json');
const parsedLocfiles: StructuredLocfileInfo = {};
@ -22,6 +22,8 @@ for (const [path, loader] of Object.entries(locFiles)) {
}
const defaultLocale = 'en';
const languages: Record<string, string> = _languages;
const config: Config<{
value?: string;
formats?: string;
@ -30,6 +32,8 @@ const config: Config<{
}> = {
fallbackLocale: defaultLocale,
translations: Object.keys(parsedLocfiles).reduce((obj, lang) => {
languages[lang] ??= `${lang} (missing name)`;
return {
...obj,
[lang]: { languages }

View File

@ -18,7 +18,7 @@
<h3>leading privacy</h3>
<p>
all requests to backend are anonymous and all tunnels are encrypted.
we have a strict zero log policy and don't track <i>anything at all</i>.
we have a strict zero log policy and don't track <i>anything</i> about individual people.
</p>
<p>
to avoid caching or storing downloaded files, cobalt processes them on-fly, sending processed pieces directly to client.

View File

@ -25,10 +25,10 @@
<section id="saving">
<h3>saving</h3>
<p>
when using saving functionality, in some cases cobalt will encrypt & temporarily store information needed for tunnelling. it's stored in processing server's RAM for 90 seconds and irreversibly purged afterwards. no one has access to it, even instance owners, as long as they don't modify the official cobalt image.
when using saving functionality, in some cases cobalt will encrypt & temporarily store information needed for tunneling. it's stored in processing server's RAM for 90 seconds and irreversibly purged afterwards. no one has access to it, even instance owners, as long as they don't modify the official cobalt image.
</p>
<p>
processed/tunnelled files are never cached anywhere. everything is tunnelled live. cobalt's saving functionality is essentially a fancy proxy service.
processed/tunneled files are never cached anywhere. everything is tunneled live. cobalt's saving functionality is essentially a fancy proxy service.
</p>
</section>